{
const [monthlyChartRightMax, setMonthlyChartRightMax]: any[] = React.useState(10);
const [monthlyAnticipateLeftMax, setMonthlyAnticipateLeftMax]: any[] = React.useState(10);
const [receivedPercentage,setReceivedPercentage]: any[] = React.useState(0);
+ const [invoicedPercentage,setInvoicedPercentage]: any[] = React.useState(0);
+ const [totalFee,setTotalFee]: any[] = React.useState(0);
const [totalBudget,setTotalBudget]: any[] = React.useState(0);
const [totalInvoiced,setTotalInvoiced]: any[] = React.useState(0);
const [totalReceived,setTotalReceived]: any[] = React.useState(0);
@@ -121,6 +124,8 @@ const ProjectCashFlow: React.FC = () => {
const cashFlowReceivableAndExpenditureData = await fetchProjectsCashFlowReceivableAndExpenditure(selectedProjectIdList);
if(cashFlowReceivableAndExpenditureData.length !== 0){
setReceivedPercentage(cashFlowReceivableAndExpenditureData[0].receivedPercentage)
+ setInvoicedPercentage(cashFlowReceivableAndExpenditureData[0].invoicedPercentage)
+ setTotalFee(cashFlowReceivableAndExpenditureData[0].totalProjectFee)
setTotalInvoiced(cashFlowReceivableAndExpenditureData[0].totalInvoiced)
setTotalReceived(cashFlowReceivableAndExpenditureData[0].totalReceived)
setReceivable(cashFlowReceivableAndExpenditureData[0].receivable)
@@ -511,9 +516,9 @@ const ProjectCashFlow: React.FC = () => {
const accountsReceivableOptions: ApexOptions = {
colors: ["#20E647"],
- series: [receivedPercentage],
+ series: [receivedPercentage,invoicedPercentage],
chart: {
- height: 350,
+ height: 50,
type: "radialBar",
},
plotOptions: {
@@ -533,13 +538,23 @@ const ProjectCashFlow: React.FC = () => {
},
dataLabels: {
name: {
- show: false,
+ show: true,
+ fontSize: "0.9em",
},
value: {
color: "#3e98c7",
- fontSize: "3em",
+ fontSize: "1.5em",
show: true,
},
+ total: {
+ show: true,
+ color: "#20E647",
+ fontSize: "0.9em",
+ label: 'Receivable / Invoiced',
+ formatter: function (w:any) {
+ return receivedPercentage + "% / " + invoicedPercentage + "%"
+ },
+ }
},
},
},
@@ -555,7 +570,7 @@ const ProjectCashFlow: React.FC = () => {
stroke: {
lineCap: "round",
},
- labels: ["AccountsReceivable"],
+ labels: ["Accounts Receivable","Account Invoiced"],
};
const expenditureOptions: ApexOptions = {
@@ -582,11 +597,12 @@ const ProjectCashFlow: React.FC = () => {
},
dataLabels: {
name: {
- show: false,
+ show: true,
+ fontSize: "0.9em",
},
value: {
color: "#3e98c7",
- fontSize: "3em",
+ fontSize: "1.5em",
show: true,
},
},
@@ -604,7 +620,7 @@ const ProjectCashFlow: React.FC = () => {
stroke: {
lineCap: "round",
},
- labels: ["AccountsReceivable"],
+ labels: ["Accounts Expenditure"],
};
const rows = [
@@ -812,12 +828,26 @@ const ProjectCashFlow: React.FC = () => {
className="text-slate-500"
title="Accounts Receivable (HKD)"
/>
+
+
+
+ Total Project Fee
+
+
+ ${totalFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
= ({
TotalBudget,
TotalCumulative,
TotalInvoicedAmount,
+ TotalUnInvoicedAmount,
TotalReceivedAmount,
CashFlowStatus,
CostPerformanceIndex,
ClickedIndex,
+ ProjectedCPI,
+ ProjectedCashFlowStatus,
Index,
}) => {
const [SearchCriteria, setSearchCriteria] = React.useState({});
@@ -106,6 +112,13 @@ const ProjectFinancialCard: React.FC
= ({
{TotalInvoicedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
+ Total Un-Invoiced Amount
+
+
+ {TotalUnInvoicedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
+
Total Received Amount
@@ -164,6 +177,57 @@ const ProjectFinancialCard: React.FC = ({
>
)}
+
+ Projected Cash Flow Status
+
+ {ProjectedCashFlowStatus === "Negative" && (
+ <>
+
+ {ProjectedCashFlowStatus}
+
+
+ >
+ )}
+ {ProjectedCashFlowStatus === "Positive" && (
+ <>
+
+ {CashFlowStatus}
+
+
+ >
+ )}
+
+ Projected Cost Performance Index (CPI)
+
+ {Number(ProjectedCPI) < 1 && (
+ <>
+
+ {ProjectedCPI}
+
+ >
+ )}
+ {Number(ProjectedCPI) >= 1 && (
+ <>
+
+ {ProjectedCPI}
+
+ >
+ )}
);
};
diff --git a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx b/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx
index 02d56e4..cab3985 100644
--- a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx
+++ b/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx
@@ -133,6 +133,40 @@ const ProjectFinancialSummary: React.FC = () => {
}
},
},
+ {
+ id: 'projectedCashFlowStatus',
+ field: 'projectedCashFlowStatus',
+ headerName: "Projected Cash Flow Status",
+ minWidth:100,
+ renderCell: (params:any) => {
+ if (params.row.projectedCashFlowStatus === "Positive") {
+ return (
+
{params.row.projectedCashFlowStatus}
+ )
+ } else if (params.row.projectedCashFlowStatus === "Negative") {
+ return (
+
{params.row.projectedCashFlowStatus}
+ )
+ }
+ },
+ },
+ {
+ id: 'projectedCpi',
+ field: 'projectedCpi',
+ headerName: "Projected CPI",
+ minWidth:50,
+ renderCell: (params:any) => {
+ if (params.row.projectedCpi >= 1) {
+ return (
+
{params.row.projectedCpi}
+ )
+ } else if (params.row.projectedCpi < 1) {
+ return (
+
{params.row.projectedCpi}
+ )
+ }
+ },
+ },
{
id: 'totalFee',
field: 'totalFee',
@@ -292,86 +326,119 @@ const columns2 = [
}
},
},
- {
- id: "cpi",
- field: "cpi",
- headerName: "CPI",
- minWidth:50,
- renderCell: (params: any) => {
- if (params.row.cpi >= 1) {
- return
{params.row.cpi};
- } else if (params.row.cpi < 1) {
- return
{params.row.cpi};
- }
- },
+ {
+ id: "cpi",
+ field: "cpi",
+ headerName: "CPI",
+ minWidth:50,
+ renderCell: (params: any) => {
+ if (params.row.cpi >= 1) {
+ return
{params.row.cpi};
+ } else if (params.row.cpi < 1) {
+ return
{params.row.cpi};
+ }
},
-
-{
- id: 'totalFees',
- field: 'totalFees',
- headerName: "Total Fees (HKD)",
- minWidth:50,
- renderCell: (params:any) => {
+ },
+ {
+ id: 'projectedCashFlowStatus',
+ field: 'projectedCashFlowStatus',
+ headerName: "Projected Cash Flow Status",
+ minWidth:100,
+ renderCell: (params:any) => {
+ if (params.row.projectedCashFlowStatus === "Positive") {
+ return (
+
{params.row.projectedCashFlowStatus}
+ )
+ } else if (params.row.projectedCashFlowStatus === "Negative") {
+ return (
+
{params.row.projectedCashFlowStatus}
+ )
+ }
+ },
+ },
+ {
+ id: 'projectedCpi',
+ field: 'projectedCpi',
+ headerName: "Projected CPI",
+ minWidth:50,
+ renderCell: (params:any) => {
+ if (params.row.projectedCpi >= 1) {
+ return (
+
{params.row.projectedCpi}
+ )
+ } else if (params.row.projectedCpi < 1) {
+ return (
+
{params.row.projectedCpi}
+ )
+ }
+ },
+ },
+ {
+ id: 'totalFees',
+ field: 'totalFees',
+ headerName: "Total Fees (HKD)",
+ minWidth:50,
+ renderCell: (params:any) => {
+ return (
+
${params.row.totalFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ )
+ },
+ },
+ {
+ id: 'totalBudget',
+ field: 'totalBudget',
+ headerName: "Total Budget (HKD)",
+ minWidth:50,
+ renderCell: (params:any) => {
return (
-
${params.row.totalFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
${params.row.totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
)
},
-},
-{
- id: 'totalBudget',
- field: 'totalBudget',
- headerName: "Total Budget (HKD)",
- minWidth:50,
- renderCell: (params:any) => {
- return (
-
${params.row.totalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- )
-},
-},
-{
- id: 'totalCumulativeExpenditure',
- field: 'totalCumulativeExpenditure',
- headerName: "Total Cumulative Expenditure (HKD)",
- minWidth:250,
- renderCell: (params:any) => {
- return (
-
${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- )
},
-},
-{
- id: 'totalInvoicedAmount',
- field: 'totalInvoicedAmount',
- headerName: "Total Invoiced Amount (HKD)",
- minWidth:250,
- renderCell: (params:any) => {
- return (
-
${params.row.totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- )
+ {
+ id: 'totalCumulativeExpenditure',
+ field: 'totalCumulativeExpenditure',
+ headerName: "Total Cumulative Expenditure (HKD)",
+ minWidth:250,
+ renderCell: (params:any) => {
+ return (
+
${params.row.cumulativeExpenditure.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ )
+ },
},
-},
-{
- id: 'totalUnInvoicedAmount',
- field: 'totalUnInvoicedAmount',
- headerName: "Total Un-invoiced Amount (HKD)",
- minWidth:250,
- renderCell: (params:any) => {
- return (
-
${params.row.totalUninvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- )
+ {
+ id: 'totalInvoicedAmount',
+ field: 'totalInvoicedAmount',
+ headerName: "Total Invoiced Amount (HKD)",
+ minWidth:250,
+ renderCell: (params:any) => {
+ return (
+
${params.row.totalInvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ )
+ },
+ },
+ {
+ id: 'totalUnInvoicedAmount',
+ field: 'totalUnInvoicedAmount',
+ headerName: "Total Un-invoiced Amount (HKD)",
+ minWidth:250,
+ renderCell: (params:any) => {
+ return (
+
${params.row.totalUninvoiced.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ )
+ },
},
-},
-{
- id: 'totalReceivedAmount',
- field: 'totalReceivedAmount',
- headerName: "Total Received Amount (HKD)",
- minWidth:250,
- renderCell: (params:any) => {
- return (
-
${params.row.totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- )
+ {
+ id: 'totalReceivedAmount',
+ field: 'totalReceivedAmount',
+ headerName: "Total Received Amount (HKD)",
+ minWidth:250,
+ renderCell: (params:any) => {
+ return (
+
${params.row.totalReceived.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ )
+ },
},
-},
];
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
@@ -398,7 +465,7 @@ const columns2 = [
{projectFinancialData.map((record:any, index:any) => (
handleCardClick(record,index)}>
-
+
))}
diff --git a/src/components/ProjectResourceConsumptionRanking/ProjectResourceConsumptionRanking.tsx b/src/components/ProjectResourceConsumptionRanking/ProjectResourceConsumptionRanking.tsx
new file mode 100644
index 0000000..340f856
--- /dev/null
+++ b/src/components/ProjectResourceConsumptionRanking/ProjectResourceConsumptionRanking.tsx
@@ -0,0 +1,923 @@
+"use client";
+import * as React from "react";
+import Grid from "@mui/material/Grid";
+import { useState, useEffect, useMemo } from "react";
+import Paper from "@mui/material/Paper";
+import { TFunction } from "i18next";
+import { useTranslation } from "react-i18next";
+import { Card, CardHeader } from "@mui/material";
+import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
+import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
+import ReactApexChart from "react-apexcharts";
+import { ApexOptions } from "apexcharts";
+import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
+import ReportProblemIcon from "@mui/icons-material/ReportProblem";
+import dynamic from "next/dynamic";
+import "../../app/global.css";
+import { AnyARecord, AnyCnameRecord } from "dns";
+import SearchBox, { Criterion } from "../SearchBox";
+import ProgressByTeamSearch from "@/components/ProgressByTeamSearch";
+import { Suspense } from "react";
+import { useSearchParams } from 'next/navigation';
+import { fetchAllTeamProjects, TeamProjectResult, fetchTeamProjects, fetchAllTeamConsumption} from "@/app/api/teamprojects/actions";
+// const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });
+
+interface Props {
+ projects: TeamProjectResult[];
+}
+type SearchQuery = Partial
>;
+type SearchParamNames = keyof SearchQuery;
+
+const ProjectResourceConsumptionRanking: React.FC = () => {
+ const searchParams = useSearchParams();
+ const teamLeadId = searchParams.get('teamLeadId');
+ const [activeTab, setActiveTab] = useState("financialSummary");
+ const [SearchCriteria, setSearchCriteria] = React.useState({});
+ const { t } = useTranslation("dashboard");
+ const [projectData, setProjectData]: any[] = React.useState([]);
+ const [filteredResult, setFilteredResult]:any[] = useState([]);
+ const [teamCode, setTeamCode] = useState("");
+ const [teamName, setTeamName] = useState("");
+ const [projectArray, setProjectArray]: any[] = useState([]);
+ const [percentageArray, setPercentageArray]: any[] = useState([]);
+ const [colorArray, setColorArray]: any[] = useState([]);
+ const [selectionModel, setSelectionModel]: any[] = React.useState([]);
+ const [pieChartColor, setPieChartColor]: any[] = React.useState([]);
+ const [totalSpentPercentage, setTotalSpentPercentage]: any = React.useState();
+ const [projectBudgetManhour, setProjectBudgetManhour]: any =
+ React.useState("-");
+ const [actualManhourSpent, setActualManhourSpent]: any = React.useState("-");
+ const [remainedManhour, setRemainedManhour]: any = React.useState("-");
+ const [lastUpdate, setLastUpdate]: any = React.useState("-");
+ const [dropdownDemo, setDropdownDemo] = useState("");
+ const [dateDemo, setDateDemo] = useState(null);
+ const [checkboxDemo, setCheckboxDemo] = useState(false);
+ const [receiptFromDate, setReceiptFromDate] = useState(null);
+ const [receiptToDate, setReceiptToDate] = useState(null);
+ const [selectedRows, setSelectedRows] = useState([]);
+ const [chartProjectName, setChartProjectName]:any[] = useState([]);
+ const [chartProjectDisplayName, setChartProjectDisplayName]:any[] = useState([]);
+ const [chartProjectBudgetedHour, setChartProjectBudgetedHour]:any[] = useState([]);
+ const [chartProjectSpentHour, setChartProjectSpentHour]:any[] = useState([]);
+ const [chartManhourConsumptionPercentage, setChartManhourConsumptionPercentage]:any[] = useState([]);
+ const color = ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b",
+ "#f58a9b", "#8ef4d1", "#92caf9", "#a798f9", "#fad287",
+ "#f595a6", "#88f1cc", "#9dcff5", "#a39bf5", "#f8de83",
+ "#f5a0b1", "#82eec7", "#a8d4f1", "#9f9ef1", "#f6ea7f",
+ "#f5abb4", "#7cebca", "#b3d9ed", "#9ba1ed", "#f4f67b",
+ "#f5b6b7", "#76e8cd", "#bed6e9", "#97a4e9", "#f2fa77",
+ "#f5c1ba", "#70e5d0", "#c9d3e5", "#93a7e5", "#f0fe73",
+ "#f5ccbd", "#6ae2d3", "#d4d0e1", "#8faae1", "#eefe6f",
+ "#f5d7c0", "#64dfd6", "#dfc5dd", "#8badd5", "#ecfe6b",
+ "#f5e2c3", "#5edcd9", "#eabada", "#87b0c9", "#eafc67",
+ "#f5edc6", "#58d9dc", "#f5afd6", "#83b3bd", "#e8fc63",
+ "#f5f8c9", "#52d6df", "#ffacd2", "#7fb6b1", "#e6fc5f",
+ "#f5ffcc", "#4cd3e2", "#ffa9ce", "#7bb9a5", "#e4fc5b",
+ "#f2ffcf", "#46d0e5", "#ffa6ca", "#77bc99", "#e2fc57",
+ "#efffd2", "#40cde8", "#ffa3c6", "#73bf8d", "#e0fc53",
+ "#ecffd5", "#3acaeb", "#ffa0c2", "#6fc281", "#defb4f",
+ "#e9ffd8", "#34c7ee", "#ff9dbe", "#6bc575", "#dcfb4b",
+ "#e6ffdb", "#2ec4f1", "#ff9aba", "#67c869", "#dafb47",
+ "#e3ffde", "#28c1f4", "#ff97b6", "#63cb5d", "#d8fb43",
+ "#e0ffe1", "#22bef7", "#ff94b2", "#5fce51", "#d6fb3f",
+ "#ddfee4", "#1cbbfa", "#ff91ae", "#5bd145", "#d4fb3b",
+ "#dafee7", "#16b8fd", "#ff8eaa", "#57d439", "#d2fb37",
+ "#d7feea", "#10b5ff", "#ff8ba6", "#53d72d", "#d0fb33",
+ "#d4feed", "#0ab2ff", "#ff88a2", "#4fda21", "#cefb2f",
+ "#d1fef0", "#04afff", "#ff859e", "#4bdd15", "#ccfb2b"];
+ const [teamProjectResult, setTeamProjectResult]:any[] = useState([]);
+ const [currentPageProjectList, setCurrentPageProjectList]: any[] = React.useState([]);
+ const [currentPageProjectNameList, setCurrentPageProjectNameList]: any[] = React.useState([]);
+ const [currentPageProjectBudgetedManhourList, setCurrentPageProjectBudgetedManhourList]: any[] = React.useState([]);
+ const [currentPageProjectSpentManhourList, setCurrentPageProjectSpentManhourList]: any[] = React.useState([]);
+ const [currentPagePercentage, setCurrentPagePercentage]: any[] = React.useState([]);
+ const [currentPageColor, setCurrentPageColor]: any[] = React.useState([]);
+ const [currentPage, setCurrentPage] = useState(1);
+ const recordsPerPage = 10;
+ const [tableSorting, setTableSorting] = useState('ProjectName');
+ const [selectedTeamIdList, setSelectedTeamIdList]: any[] = React.useState([]);
+
+ const fetchTeamData = async () => {
+ const teamprojects = await fetchTeamProjects();
+ setProjectData(teamprojects)
+ setFilteredResult(teamprojects)
+ }
+
+ const fetchData = async () => {
+ console.log(selectedTeamIdList)
+ if (selectedTeamIdList) {
+ try {
+ const clickResult = await fetchAllTeamConsumption(
+ selectedTeamIdList,tableSorting)
+ console.log(clickResult)
+ setTeamProjectResult(clickResult);
+ } catch (error) {
+ console.error('Error fetching team consumption:', error);
+ }
+ }
+ }
+
+ const searchCriteria: Criterion[] = useMemo(
+ () => [
+ { label: "Team Code", paramName: "teamCode", type: "text" },
+ { label: "Team Name", paramName: "teamName", type: "text" },
+ ],
+ [t],
+ );
+
+ useEffect(() => {
+ const projectNo = []
+ const projectName = []
+ const projectBudgetedManHour = []
+ const projectSpentManHour = []
+ const manhourConsumptionPercentage = []
+ for (let i = 0; i < teamProjectResult.length; i++){
+ teamProjectResult[i].color = color[i]
+ console.log(teamProjectResult[i])
+ projectNo.push(teamProjectResult[i].projectCode + "(" + teamProjectResult[i].team + ")")
+ projectName.push(teamProjectResult[i].projectName)
+ projectBudgetedManHour.push(teamProjectResult[i].budgetedManhour)
+ projectSpentManHour.push(teamProjectResult[i].spentManhour)
+ manhourConsumptionPercentage.push(teamProjectResult[i].manhourConsumptionPercentage)
+ }
+ setChartProjectName(projectNo)
+ setChartProjectDisplayName(projectName)
+ setChartProjectBudgetedHour(projectBudgetedManHour)
+ setChartProjectSpentHour(projectSpentManHour)
+ setChartManhourConsumptionPercentage(manhourConsumptionPercentage)
+ }, [teamProjectResult]);
+
+ useEffect(() => {
+ fetchTeamData()
+ }, []);
+
+ useEffect(() => {
+ fetchData()
+ }, [selectedTeamIdList,tableSorting]);
+
+ const rows = [
+ {
+ id: 1,
+ teamCode: "TEAM-001",
+ teamName: "Team A",
+ noOfProjects: "5",
+ },
+ {
+ id: 2,
+ teamCode: "TEAM-001",
+ teamName: "Team B",
+ noOfProjects: "5",
+ },
+ {
+ id: 3,
+ teamCode: "TEAM-001",
+ teamName: "Team C",
+ noOfProjects: "3",
+ },
+ {
+ id: 4,
+ teamCode: "TEAM-001",
+ teamName: "Team D",
+ noOfProjects: "1",
+ },
+ ];
+ //['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b']
+ const rows2 = [
+ {
+ id: 1,
+ project: "Consultancy Project 123",
+ team: "XXX",
+ teamLeader: "XXX",
+ currentStage: "Contract Documentation",
+ budgetedManhour: "200.00",
+ spentManhour: "120.00",
+ remainedManhour: "80.00",
+ comingPaymentMilestone: "31/03/2024",
+ alert: false,
+ color: "#f57f90",
+ },
+ {
+ id: 2,
+ project: "Consultancy Project 456",
+ team: "XXX",
+ teamLeader: "XXX",
+ currentStage: "Report Preparation",
+ budgetedManhour: "400.00",
+ spentManhour: "200.00",
+ remainedManhour: "200.00",
+ comingPaymentMilestone: "20/02/2024",
+ alert: false,
+ color: "#94f7d6",
+ },
+ {
+ id: 3,
+ project: "Construction Project A",
+ team: "YYY",
+ teamLeader: "YYY",
+ currentStage: "Construction",
+ budgetedManhour: "187.50",
+ spentManhour: "200.00",
+ remainedManhour: "12.50",
+ comingPaymentMilestone: "13/12/2023",
+ alert: true,
+ color: "#87c5f5",
+ },
+ {
+ id: 4,
+ project: "Construction Project B",
+ team: "XXX",
+ teamLeader: "XXX",
+ currentStage: "Post Construction",
+ budgetedManhour: "100.00",
+ spentManhour: "40.00",
+ remainedManhour: "60.00",
+ comingPaymentMilestone: "05/01/2024",
+ alert: false,
+ color: "#ab95f5",
+ },
+ {
+ id: 5,
+ project: "Construction Project C",
+ team: "YYY",
+ teamLeader: "YYY",
+ currentStage: "Construction",
+ budgetedManhour: "300.00",
+ spentManhour: "150.00",
+ remainedManhour: "150.00",
+ comingPaymentMilestone: "31/03/2024",
+ alert: false,
+ color: "#fcd68b",
+ },
+ ];
+
+ const searchColumns = [
+ {
+ id: "teamCode",
+ field: "teamCode",
+ headerName: "Team Code",
+ flex: 1,
+ },
+ {
+ id: "teamName",
+ field: "teamName",
+ headerName: "Team Name",
+ flex: 1,
+ },
+ {
+ id: "projectNo",
+ field: "projectNo",
+ headerName: "No. of Projects",
+ flex: 1,
+ },
+ ];
+
+ const columns = [
+ {
+ id: "clientCode",
+ field: "clientCode",
+ headerName: "Client Code",
+ flex: 1,
+ },
+ {
+ id: "clientName",
+ field: "clientName",
+ headerName: "Client Name",
+ flex: 1,
+ },
+ {
+ id: "clientSubsidiaryCode",
+ field: "clientSubsidiaryCode",
+ headerName: "Client Subsidiary Code",
+ flex: 1,
+ },
+ {
+ id: "noOfProjects",
+ field: "noOfProjects",
+ headerName: "No. of Projects",
+ flex: 1,
+ },
+ ];
+
+ const columns2 = [
+ {
+ id: "color",
+ field: "color",
+ headerName: "",
+ renderCell: (params: any) => {
+ return (
+
+ );
+ },
+ flex: 0.1,
+ },
+ {
+ id: "projectCode",
+ field: "projectCode",
+ headerName: "Project No",
+ minWidth:100
+ },
+ {
+ id: "projectName",
+ field: "projectName",
+ headerName: "Project",
+ minWidth:300
+ },
+ {
+ id: "team",
+ field: "team",
+ headerName: "Team",
+ minWidth:50
+ },
+ {
+ id: "teamLead",
+ field: "teamLead",
+ headerName: "Team Leader",
+ minWidth: 70
+ },
+ {
+ id: "expectedStage",
+ field: "expectedStage",
+ headerName: "Expected Stage",
+ minWidth: 300,
+ renderCell: (params: any) => {
+ if (params.row.expectedStage != null){
+ const expectedStage = params.row.expectedStage;
+ const lines = expectedStage.split(",").map((line:any, index:any) => (
+
+ {line.trim()}
+
+
+ ));
+ return {lines}
;
+ } else {
+ return -
;
+ }
+
+ },
+ },
+ {
+ id: "budgetedManhour",
+ field: "budgetedManhour",
+ headerName: "Budgeted Manhour",
+ minWidth: 70,
+ renderCell: (params: any) => {
+ return {params.row.budgetedManhour.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })};
+ }
+ },
+ {
+ id: "spentManhour",
+ field: "spentManhour",
+ headerName: "Spent Manhour",
+ renderCell: (params: any) => {
+ if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
+ return (
+ {params.row.spentManhour.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ );
+ } else {
+ return {params.row.spentManhour.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })};
+ }
+ },
+ minWidth: 70
+ },
+ {
+ id: "remainedManhour",
+ field: "remainedManhour",
+ headerName: "Remained Manhour",
+ renderCell: (params: any) => {
+ if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
+ return (
+ ({params.row.remainedManhour.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })})
+ );
+ } else {
+ return {params.row.remainedManhour.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })};
+ }
+ },
+ minWidth: 70
+ },
+ {
+ id: "comingPaymentMilestone",
+ field: "comingPaymentMilestone",
+ headerName: "Coming Payment Milestone",
+ minWidth: 100
+ },
+ {
+ id: "alert",
+ field: "alert",
+ headerName: "Alert",
+ renderCell: (params: any) => {
+ if (params.row.alert === true) {
+ return (
+
+
+
+ );
+ } else {
+ return ;
+ }
+ },
+ flex: 0.1,
+ },
+ ];
+
+ const InputFields = [
+ {
+ id: "teamCode",
+ label: "Team Code",
+ type: "text",
+ value: teamCode,
+ setValue: setTeamCode,
+ },
+ {
+ id: "teamName",
+ label: "Team Name",
+ type: "text",
+ value: teamName,
+ setValue: setTeamName,
+ },
+
+ // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo },
+ // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo },
+ // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo },
+ // { id: ['receiptFromDate','receiptToDate'], label: ["收貨日期","收貨日期"], value: [receiptFromDate ? receiptFromDate : null, receiptToDate ? receiptToDate : null],
+ // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' },
+ ];
+
+ const stageDeadline = [
+ "31/03/2024",
+ "20/02/2024",
+ "01/12/2023",
+ "05/01/2024",
+ "31/03/2023",
+ ];
+
+ const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [
+ {
+ data: [17.1, 28.6, 5.7, 48.6],
+ },
+ ];
+
+ const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [
+ {
+ name: "Project Resource Consumption Percentage",
+ data: [80, 55, 40, 65, 70],
+ },
+ ];
+
+ const options2: ApexOptions = {
+ chart: {
+ type: "donut",
+ },
+ colors: colorArray,
+ plotOptions: {
+ pie: {
+ donut: {
+ labels: {
+ show: true,
+ name: {
+ show: true,
+ },
+ value: {
+ show: true,
+ fontWeight: 500,
+ fontSize: "30px",
+ color: "#3e98c7",
+ },
+ total: {
+ show: true,
+ showAlways: true,
+ label: "Spent",
+ fontFamily: "sans-serif",
+ formatter: function (val) {
+ return totalSpentPercentage + "%";
+ },
+ },
+ },
+ },
+ },
+ },
+ labels: projectArray,
+ legend: {
+ show: false,
+ },
+ responsive: [
+ {
+ breakpoint: 480,
+ options: {
+ chart: {
+ width: 200,
+ },
+ legend: {
+ position: "bottom",
+ show: false,
+ },
+ },
+ },
+ ],
+ };
+
+ const options: ApexOptions = {
+ chart: {
+ type: "bar",
+ height: 450,
+ },
+ tooltip: {
+ enabled: true, // Enable tooltip
+ custom: ({ series, seriesIndex, dataPointIndex, w }) => {
+
+ const projectCode = currentPageProjectList[dataPointIndex];
+ const projectName = currentPageProjectNameList[dataPointIndex];
+ const budgetManhours = currentPageProjectBudgetedManhourList[dataPointIndex];
+ const spentManhours = currentPageProjectSpentManhourList[dataPointIndex];
+ const value = series[seriesIndex][dataPointIndex];
+ const tooltipContent = `
+
+ ${projectCode} - ${projectName}
+
+ Budget Manhours: ${budgetManhours} hours
+
+ Spent Manhours: ${spentManhours} hours
+
+ Percentage: ${value}%
+
+ `;
+
+ return tooltipContent;
+ },
+ },
+ series: [{
+ name: "Project Resource Consumption Percentage",
+ data: currentPagePercentage,
+ },],
+ colors: currentPageColor,
+ plotOptions: {
+ bar: {
+ horizontal: true,
+ distributed: true,
+ dataLabels: {
+ position: 'top'
+ },
+ },
+ },
+ dataLabels: {
+ enabled: true,
+ textAnchor: 'end',
+ formatter: (val) => `${val}%`,
+ },
+ xaxis: {
+ categories: currentPageProjectList,
+ },
+ yaxis: {
+ title: {
+ text: "Projects",
+ },
+ labels: {
+ maxWidth: 200,
+ style: {
+ cssClass: "apexcharts-yaxis-label",
+ },
+ },
+ },
+ title: {
+ text: "Project Resource Consumption Percentage",
+ align: "center",
+ },
+ grid: {
+ borderColor: "#f1f1f1",
+ xaxis: {
+ lines: {
+ show: true,
+ }
+ }
+ },
+ annotations: {},
+ };
+
+ const handleSearchSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
+ const selectedRowsData = projectData.filter((row: any) =>
+ newSelectionModel.includes(row.id),
+ );
+ const teamIdList = []
+ for (var i=0; i {
+ const selectedRowsData = teamProjectResult.filter((row:any) =>
+ newSelectionModel.includes(row.id),
+ );
+ console.log(selectedRowsData);
+ const projectArray = [];
+ const pieChartColorArray = [];
+ let totalSpent = 0;
+ let totalBudgetManhour = 0;
+ const percentageArray = [];
+ for (let i = 0; i <= selectedRowsData.length; i++) {
+ if (i === selectedRowsData.length && i > 0) {
+ projectArray.push("Remained");
+ } else if (selectedRowsData.length > 0) {
+ projectArray.push(selectedRowsData[i].projectName);
+ totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour);
+ totalSpent += Number(selectedRowsData[i].spentManhour);
+ pieChartColorArray.push(selectedRowsData[i].color);
+ }
+ }
+ for (let i = 0; i <= selectedRowsData.length; i++) {
+ if (i === selectedRowsData.length && i > 0) {
+ const remainedManhour = totalBudgetManhour - totalSpent;
+ percentageArray.push(
+ Number(((remainedManhour / totalBudgetManhour) * 100).toFixed(1)),
+ );
+ } else if (selectedRowsData.length > 0) {
+ const percentage = (
+ (Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) *
+ 100
+ ).toFixed(1);
+ percentageArray.push(Number(percentage));
+ }
+ }
+ setProjectBudgetManhour(totalBudgetManhour.toFixed(2));
+ setActualManhourSpent(totalSpent.toFixed(2));
+ setRemainedManhour((totalBudgetManhour - totalSpent).toFixed(2));
+ setLastUpdate(new Date().toLocaleDateString("en-GB"));
+ setSelectionModel(newSelectionModel);
+ console.log(projectArray);
+ setProjectArray(projectArray);
+ setPercentageArray(percentageArray);
+ console.log(percentageArray);
+ setTotalSpentPercentage(
+ ((totalSpent / totalBudgetManhour) * 100).toFixed(1),
+ );
+ if (projectArray.length > 0 && projectArray.includes("Remained")) {
+ const nonLastRecordColors = pieChartColorArray;
+ setColorArray([
+ ...nonLastRecordColors.slice(0, projectArray.length - 1),
+ "#a3a3a3",
+ ]);
+ } else {
+ setColorArray(pieChartColorArray);
+ }
+ };
+
+ const startIndex = (currentPage - 1) * recordsPerPage;
+ const endIndex = startIndex + recordsPerPage;
+ useEffect(() => {
+ console.log(chartManhourConsumptionPercentage)
+ const currentPageProjectData = chartProjectName.slice(startIndex, endIndex)
+ const currentPageProjectName = chartProjectDisplayName.slice(startIndex, endIndex)
+ const currentPageProjectBudgetedManhour = chartProjectBudgetedHour.slice(startIndex, endIndex)
+ const currentPageProjectSpentManhour = chartProjectSpentHour.slice(startIndex, endIndex)
+ const currentPageData = chartManhourConsumptionPercentage.slice(startIndex, endIndex);
+ const colorArray = color.slice(startIndex, endIndex);
+ console.log(currentPage)
+ console.log(Math.ceil(chartManhourConsumptionPercentage.length / recordsPerPage))
+ setCurrentPageProjectList(currentPageProjectData)
+ setCurrentPageProjectNameList(currentPageProjectName)
+ setCurrentPageProjectBudgetedManhourList(currentPageProjectBudgetedManhour)
+ setCurrentPageProjectSpentManhourList(currentPageProjectSpentManhour)
+ setCurrentPagePercentage(currentPageData)
+ setCurrentPageColor(colorArray)
+ }, [chartManhourConsumptionPercentage,currentPage]);
+
+ const handlePrevPage = () => {
+ if (currentPage > 1) {
+ setCurrentPage(currentPage - 1);
+ }
+ };
+
+ const handleNextPage = () => {
+ if (endIndex < chartManhourConsumptionPercentage.length) {
+ setCurrentPage(currentPage + 1);
+ }
+ };
+
+ const applySearch = (data: any) => {
+ console.log(data);
+ setSearchCriteria(data);
+ };
+ return (
+ <>
+ {
+ setFilteredResult(
+ projectData.filter(
+ (cp:any) =>
+ cp.teamCode.toLowerCase().includes(query.teamCode.toLowerCase()) &&
+ cp.teamName.toLowerCase().includes(query.teamName.toLowerCase())
+ ),
+ );
+ }}
+ />
+
+
+
+
+
+
+
+
+
+ Sorting:
+
+
+
+
+
+
+
+
+
+ {currentPage === 1 && (
+
+ )}
+ {currentPage !== 1 && (
+
+ )}
+ {endIndex >= chartManhourConsumptionPercentage.length && (
+
+ )}
+ {endIndex < chartManhourConsumptionPercentage.length && (
+
+ )}
+ Page
+ {chartManhourConsumptionPercentage.length === 0 && (
+ 0
+ )}
+ {chartManhourConsumptionPercentage.length > 0 && (
+ currentPage
+ )}
+ of
+ {Math.ceil(chartManhourConsumptionPercentage.length / recordsPerPage)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {percentageArray.length === 0 && (
+
+ Please select the project you want to check.
+
+ )}
+ {percentageArray.length > 0 && (
+
+ )}
+
+
+
+
+
+
+ Project Budget Manhour
+
+
+ {projectBudgetManhour}
+
+
+
+
+
+ Actual Manhour Spent
+
+
+ {actualManhourSpent}
+
+
+
+
+
+ Remained Manhour
+
+
+ {remainedManhour}
+
+
+
+
+
+ Last Update
+
+
+ {lastUpdate}
+
+
+
+
+
+
+ >
+ );
+};
+
+export default ProjectResourceConsumptionRanking;
diff --git a/src/components/ProjectResourceConsumptionRanking/index.ts b/src/components/ProjectResourceConsumptionRanking/index.ts
new file mode 100644
index 0000000..6259675
--- /dev/null
+++ b/src/components/ProjectResourceConsumptionRanking/index.ts
@@ -0,0 +1 @@
+export { default } from "./ProjectResourceConsumptionRanking";
diff --git a/src/components/ProjectResourceSummary/ProjectResourceSummary.tsx b/src/components/ProjectResourceSummary/ProjectResourceSummary.tsx
index 5050323..7826bc3 100644
--- a/src/components/ProjectResourceSummary/ProjectResourceSummary.tsx
+++ b/src/components/ProjectResourceSummary/ProjectResourceSummary.tsx
@@ -33,6 +33,7 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { useSearchParams } from 'next/navigation';
import {fetchResourceSummaryDetailResult} from "@/app/api/resourcesummary/actions";
+import { set } from "lodash";
const ProjectResourceSummary: React.FC = () => {
@@ -43,6 +44,9 @@ const ProjectResourceSummary: React.FC = () => {
const [selectionModel, setSelectionModel]: any[] = React.useState([]);
const [projectName, setProjectName]:any = React.useState("NA");
const [projectFee, setProjectFee]:any = React.useState(0);
+ const [projectBudget, setProjectBudget]:any = React.useState(0);
+ const [expenditure, setExpenditure]:any = React.useState(0);
+ const [remainingBudget, setRemainingBudget]:any = React.useState(0);
const [status, setStatus]:any = React.useState("NA");
const [plannedResources, setPlannedResources]:any = React.useState(0);
const [actualResourcesSpent, setActualResourcesSpent]:any = React.useState(0);
@@ -94,6 +98,9 @@ const ProjectResourceSummary: React.FC = () => {
const result = await fetchResourceSummaryDetailResult(intProjectId);
setProjectName(result[0].summaryInformation[0].projectCodeAndName)
setProjectFee(result[0].summaryInformation[0].totalFee)
+ setProjectBudget(result[0].summaryInformation[0].totalBudget)
+ setExpenditure(result[0].summaryInformation[0].expenditure)
+ setRemainingBudget(result[0].summaryInformation[0].remainingBudget)
setStatus(result[0].summaryInformation[0].status)
setPlannedResources(result[0].summaryInformation[0].plannedResources)
setActualResourcesSpent(result[0].summaryInformation[0].resourcesSpent)
@@ -233,8 +240,8 @@ const ProjectResourceSummary: React.FC = () => {
return (
- *': { borderBottom: 'unset' } }}>
-
+ *': { borderBottom: 'unset' } }} className="border-t-2 border-b-0 border-l-0 border-r-0 border-solid border-slate-300">
+
{row.task.length > 0 && (
{
{row.stage}
{row.taskCount}
- {row.g1Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g1Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g2Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g2Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g3Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g3Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g4Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g4Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g5Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.g5Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.totalPlanned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {row.totalActual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g1Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g1Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g2Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g2Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g3Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g3Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g4Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g4Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g5Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.g5Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.totalPlanned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {row.totalActual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
{row.task.map((taskRow:any) => (
-
+
@@ -307,7 +314,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[4].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[4].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -320,7 +327,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[5].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[5].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -333,7 +340,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[6].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[6].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -346,7 +353,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[7].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[7].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -359,7 +366,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[8].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[8].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -372,7 +379,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[9].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[9].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -385,7 +392,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[10].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[10].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -398,7 +405,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[11].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[11].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -411,7 +418,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[12].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[12].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -424,7 +431,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[13].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[13].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -437,7 +444,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[2].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[2].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -450,7 +457,7 @@ const ProjectResourceSummary: React.FC = () => {
- {taskRow[3].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+ {taskRow[3].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
@@ -497,6 +504,9 @@ const columns2 = [
field: 'g1Planned',
headerName: "Planned",
flex: 0.7,
+ renderCell: (params: any) => {
+ return {params.row.g1Planned};
+ },
},
{
id: 'g1Actual',
@@ -631,6 +641,36 @@ const columns2 = [
HKD ${projectFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}