| @@ -63,10 +63,14 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| const manhourPercentageByGrade = watch("manhourPercentageByGrade"); | |||
| const totalManhour = watch("totalManhour"); | |||
| const totalPercentage = Math.round(Object.values(manhourPercentageByGrade).reduce( | |||
| const totalPercentage = Object.values(manhourPercentageByGrade).reduce( | |||
| (acc, percent) => acc + percent, | |||
| 0, | |||
| ) * 100) / 100; | |||
| ); | |||
| // const totalPercentage = Math.round(Object.values(manhourPercentageByGrade).reduce( | |||
| // (acc, percent) => acc + percent, | |||
| // 0, | |||
| // ) * 100) / 100; | |||
| const makeUpdatePercentage = useCallback( | |||
| (gradeId: Grade["id"]) => (percentage?: number) => { | |||
| @@ -152,7 +156,7 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| <TableCellEdit | |||
| key={`${column.id}${idx}`} | |||
| value={manhourPercentageByGrade[column.id]} | |||
| renderValue={(val) => val + "%"} | |||
| renderValue={((val) => (val.toString().includes(".")? val.toString() : val.toFixed(1)) + "%")} | |||
| // renderValue={(val) => percentFormatter.format(val)} | |||
| onChange={makeUpdatePercentage(column.id)} | |||
| convertValue={(inputValue) => Number(inputValue)} | |||
| @@ -162,7 +166,7 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| /> | |||
| ))} | |||
| <TableCell sx={{ ...(totalPercentage === 100 && leftBorderCellSx), ...(totalPercentage !== 100 && { ...errorCellSx, borderRight: "1px solid", borderColor: "error.main" }) }}> | |||
| {totalPercentage + "%"} | |||
| {((totalPercentage.toString().includes(".") && totalPercentage.toString() || totalPercentage.toFixed(1)) + "%")} | |||
| {/* {percentFormatter.format(totalPercentage)} */} | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -271,7 +275,7 @@ const ResourceAllocationByStage: React.FC<Props> = ({ grades, allTasks }) => { | |||
| <TableCellEdit | |||
| value={currentTaskGroups[tg.id].percentAllocation} | |||
| // renderValue={(val) => percentFormatter.format(val)} | |||
| renderValue={(val) => val + "%"} | |||
| renderValue={(val) => ((val.toString().includes(".")? val.toString() : val.toFixed(1)) + "%")} | |||
| onChange={makeUpdatePercentage(tg.id)} | |||
| convertValue={(inputValue) => Number(inputValue)} | |||
| cellSx={{ | |||
| @@ -311,12 +315,27 @@ const ResourceAllocationByStage: React.FC<Props> = ({ grades, allTasks }) => { | |||
| ...(Object.values(currentTaskGroups).reduce((acc, tg) => acc + tg.percentAllocation, 0,) !== 100 && errorCellSx) | |||
| }} | |||
| > | |||
| {percentFormatter.format( | |||
| Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation / 100, | |||
| {((Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation, | |||
| 0, | |||
| ), | |||
| )} | |||
| ).toString().includes(".") && Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation, | |||
| 0,) || Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => (acc + tg.percentAllocation), | |||
| 0, | |||
| ).toFixed(1)) + "%" )} | |||
| {/* {percentFormatter.format( | |||
| Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation / 100, | |||
| 0, | |||
| ), | |||
| ).includes(".") && percentFormatter.format(Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation / 100, | |||
| 0,), | |||
| ) || Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => (acc + tg.percentAllocation), | |||
| 0, | |||
| ).toFixed(1) + "%" } */} | |||
| </TableCell> | |||
| <TableCell sx={rightBorderCellSx}> | |||
| {manhourFormatter.format( | |||
| @@ -53,10 +53,14 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| const { watch, register, setValue, formState: { errors }, setError, clearErrors } = useFormContext<NewTaskTemplateFormInputs>(); | |||
| const manhourPercentageByGrade = watch("manhourPercentageByGrade"); | |||
| const totalPercentage = Math.round(Object.values(manhourPercentageByGrade).reduce( | |||
| const totalPercentage = Object.values(manhourPercentageByGrade).reduce( | |||
| (acc, percent) => acc + percent, | |||
| 0, | |||
| ) * 100) / 100; | |||
| ); | |||
| // const totalPercentage = Math.round(Object.values(manhourPercentageByGrade).reduce( | |||
| // (acc, percent) => acc + percent, | |||
| // 0, | |||
| // ) * 100) / 100; | |||
| const makeUpdatePercentage = useCallback( | |||
| (gradeId: Grade["id"]) => (percentage?: number) => { | |||
| @@ -114,7 +118,8 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| <TableCellEdit | |||
| key={`${column.id}${idx}`} | |||
| value={manhourPercentageByGrade[column.id]} | |||
| renderValue={(val) => val + "%"} | |||
| renderValue={(val) => ((val.toString().includes(".")? val.toString() : val.toFixed(1)) + "%")} | |||
| // renderValue={(val) => val.toFixed(1) + "%"} | |||
| onChange={makeUpdatePercentage(column.id)} | |||
| convertValue={(inputValue) => Number(inputValue)} | |||
| cellSx={{ backgroundColor: "primary.lightest" }} | |||
| @@ -123,7 +128,8 @@ const ResourceAllocationByGrade: React.FC<Props> = ({ grades }) => { | |||
| /> | |||
| ))} | |||
| <TableCell sx={{ ...(totalPercentage === 100 && leftBorderCellSx), ...(totalPercentage !== 100 && { ...errorCellSx, borderRight: "1px solid", borderColor: "error.main" }) }}> | |||
| {totalPercentage + "%"} | |||
| {((totalPercentage.toString().includes(".") && totalPercentage.toString() || totalPercentage.toFixed(1) )+ "%")} | |||
| {/* {totalPercentage.toFixed(1) + "%"} */} | |||
| </TableCell> | |||
| </TableRow> | |||
| </TableBody> | |||
| @@ -214,7 +220,7 @@ const ResourceAllocationByStage: React.FC<Props> = ({ grades, allTasks }) => { | |||
| <TableCellEdit | |||
| value={currentTaskGroups[tg.id].percentAllocation} | |||
| // renderValue={(val) => percentFormatter.format(val)} | |||
| renderValue={(val) => val + "%"} | |||
| renderValue={(val) => ((val.toString().includes(".")? val.toString() : val.toFixed(1)) + "%")} | |||
| onChange={makeUpdatePercentage(tg.id)} | |||
| convertValue={(inputValue) => Number(inputValue)} | |||
| cellSx={{ | |||
| @@ -239,12 +245,27 @@ const ResourceAllocationByStage: React.FC<Props> = ({ grades, allTasks }) => { | |||
| ...(Object.values(currentTaskGroups).reduce((acc, tg) => acc + tg.percentAllocation, 0,) !== 100 && { ...errorCellSx, borderRight: "1px solid", borderColor: "error.main"}) | |||
| }} | |||
| > | |||
| {percentFormatter.format( | |||
| {((Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation, | |||
| 0, | |||
| ).toString().includes(".") && Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation, | |||
| 0,) || Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => (acc + tg.percentAllocation), | |||
| 0, | |||
| ).toFixed(1)) + "%" )} | |||
| {/* {percentFormatter.format( | |||
| Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation / 100, | |||
| 0, | |||
| ), | |||
| )} | |||
| ).includes(".") && percentFormatter.format(Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => acc + tg.percentAllocation / 100, | |||
| 0,), | |||
| ) || Object.values(currentTaskGroups).reduce( | |||
| (acc, tg) => (acc + tg.percentAllocation), | |||
| 0, | |||
| ).toFixed(1) + "%" } */} | |||
| </TableCell> | |||
| </TableRow> | |||
| </TableBody> | |||
| @@ -385,7 +385,7 @@ const ProgressByClient: React.FC<Props> = () => { | |||
| enabled: true, | |||
| y: { | |||
| formatter: function (val) { | |||
| return val.toFixed(1) + "%"; | |||
| return (val.toString().includes(".") ? val.toString() : val.toFixed(1)) + "%"; | |||
| } | |||
| } | |||
| }, | |||
| @@ -427,7 +427,7 @@ const ProgressByClient: React.FC<Props> = () => { | |||
| <br> | |||
| ${t("Spent Manhours")}: ${spentManhours.toFixed(2)} hours | |||
| <br> | |||
| Percentage: ${value.toFixed(1)}% | |||
| Percentage: ${value.toString().includes(".") ? value.toString() : value.toFixed(1)}% | |||
| </div> | |||
| `; | |||
| @@ -468,7 +468,7 @@ const ProgressByTeam: React.FC = () => { | |||
| enabled: true, | |||
| y: { | |||
| formatter: function (val) { | |||
| return val.toFixed(1) + "%"; | |||
| return (val.toString().includes(".") ? val.toString() : val.toFixed(1)) + "%"; | |||
| } | |||
| } | |||
| }, | |||
| @@ -505,9 +505,9 @@ const ProgressByTeam: React.FC = () => { | |||
| const tooltipContent = ` | |||
| <div style="width: auto;"> | |||
| <span style="font-weight: bold;">${projectCode} - ${projectName}</span> | |||
| <br>${t("Budget Manhours")}:${budgetManhours.toFixed(2)} hours | |||
| <br>${t("Spent Manhours")}:${spentManhours.toFixed(2)} hours | |||
| <br>Percentage:${value.toFixed(1)}% | |||
| <br>${t("Budget Manhours")}: ${budgetManhours.toFixed(2)} hours | |||
| <br>${t("Spent Manhours")}: ${spentManhours.toFixed(2)} hours | |||
| <br>Percentage: ${value.toString().includes(".") ? value.toString() : value.toFixed(1)}% | |||
| </div> | |||
| `; | |||
| @@ -35,6 +35,10 @@ interface Props { | |||
| Index: number; | |||
| } | |||
| const dataBaseStyle:any = { color: "#6b87cf", textAlign: "right" } | |||
| const dataNegativeStyle:any = { color: "#f896aa", textAlign: "right" } | |||
| const dataPositiveStyle:any = { color: "#71d19e", textAlign: "right" } | |||
| const ProjectFinancialCard: React.FC<Props> = ({ | |||
| Title, | |||
| TotalActiveProjectNumber, | |||
| @@ -77,74 +81,63 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||
| {Title} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Active Project")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalActiveProjectNumber.toLocaleString()} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Fees")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalFees.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Budget")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Cumulative Expenditure")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalCumulative.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Invoiced Amount")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalInvoicedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Un-Invoiced Amount")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalUnInvoicedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Total Received Amount")} | |||
| </div> | |||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||
| <div className="text-lg font-medium mx-5" style={dataBaseStyle}> | |||
| {TotalReceivedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||
| </div> | |||
| <hr /> | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Cash Flow Status")} | |||
| </div> | |||
| {CashFlowStatus === "Negative" && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#f896aa" }} | |||
| > | |||
| {t(CashFlowStatus)} | |||
| </div> | |||
| <hr /> | |||
| </> | |||
| )} | |||
| {CashFlowStatus === "Positive" && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#71d19e" }} | |||
| className="text-lg font-medium mx-5" | |||
| style={CashFlowStatus === "Negative" && dataNegativeStyle || dataPositiveStyle} | |||
| > | |||
| {t(CashFlowStatus)} | |||
| </div> | |||
| @@ -152,52 +145,30 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||
| </> | |||
| )} | |||
| <div | |||
| className="text-sm mt-2 font-medium ml-5" | |||
| className="text-sm mt-2 font-medium mx-5" | |||
| style={{ color: "#898d8d" }} | |||
| > | |||
| {t("Cost Performance Index") + " (CPI)"} | |||
| </div> | |||
| {Number(CostPerformanceIndex) < 1 && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#f896aa" }} | |||
| > | |||
| {CostPerformanceIndex} | |||
| </div> | |||
| <hr /> | |||
| </> | |||
| )} | |||
| {Number(CostPerformanceIndex) >= 1 && ( | |||
| { ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#71d19e" }} | |||
| className="text-lg font-medium mx-5 mb-2" | |||
| style={Number(CostPerformanceIndex) < 1 && dataNegativeStyle || dataPositiveStyle} | |||
| > | |||
| {CostPerformanceIndex} | |||
| </div> | |||
| <hr /> | |||
| </> | |||
| )} | |||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||
| <div className="text-sm font-medium mx-5" style={{ color: "#898d8d" }}> | |||
| {t("Projected Cash Flow Status")} | |||
| </div> | |||
| {ProjectedCashFlowStatus === "Negative" && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#f896aa" }} | |||
| > | |||
| {t(ProjectedCashFlowStatus)} | |||
| </div> | |||
| <hr /> | |||
| </> | |||
| )} | |||
| {ProjectedCashFlowStatus === "Positive" && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5" | |||
| style={{ color: "#71d19e" }} | |||
| className="text-lg font-medium mx-5" | |||
| style={ProjectedCashFlowStatus === "Negative" && dataNegativeStyle || dataPositiveStyle} | |||
| > | |||
| {t(ProjectedCashFlowStatus)} | |||
| </div> | |||
| @@ -205,7 +176,7 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||
| </> | |||
| )} | |||
| <div | |||
| className="text-sm mt-2 font-medium ml-5" | |||
| className="text-sm mt-2 font-medium mx-5" | |||
| style={{ color: "#898d8d" }} | |||
| > | |||
| {t("Projected Cost Performance Index") + " (CPI)"} | |||
| @@ -213,18 +184,8 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||
| {Number(ProjectedCPI) < 1 && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#f896aa" }} | |||
| > | |||
| {ProjectedCPI} | |||
| </div> | |||
| </> | |||
| )} | |||
| {Number(ProjectedCPI) >= 1 && ( | |||
| <> | |||
| <div | |||
| className="text-lg font-medium ml-5 mb-2" | |||
| style={{ color: "#71d19e" }} | |||
| className="text-lg font-medium mx-5 mb-2" | |||
| style={Number(ProjectedCPI) < 1 && dataNegativeStyle || dataPositiveStyle} | |||
| > | |||
| {ProjectedCPI} | |||
| </div> | |||
| @@ -554,7 +554,7 @@ const ProjectResourceConsumptionRanking: React.FC = () => { | |||
| enabled: true, | |||
| y: { | |||
| formatter: function (val) { | |||
| return val.toFixed(1) + "%"; | |||
| return (val.toString().includes(".") ? val.toString() : val.toFixed(1)) + "%"; | |||
| } | |||
| } | |||
| }, | |||
| @@ -596,7 +596,7 @@ const ProjectResourceConsumptionRanking: React.FC = () => { | |||
| <br> | |||
| ${t("Spent Manhours")}: ${spentManhours.toFixed(2)} ${t("hours")} | |||
| <br> | |||
| Percentage: ${value.toFixed(1)}% | |||
| Percentage: ${value.toString().includes(".") ? value.toString() : value.toFixed(1)}% | |||
| </div> | |||
| `; | |||