| @@ -15,72 +15,10 @@ export interface ClientProjectResult { | |||||
| projectNo: number; | projectNo: number; | ||||
| } | } | ||||
| // export interface ClientSubsidiaryProjectResult { | |||||
| // projectId: number; | |||||
| // projectCode: string; | |||||
| // projectName: string; | |||||
| // team: string; | |||||
| // teamLead: string; | |||||
| // expectedStage: string; | |||||
| // budgetedManhour: number; | |||||
| // spentManhour: number; | |||||
| // remainedManhour: number; | |||||
| // manhourConsumptionPercentage: number; | |||||
| // comingPaymentMilestone: string; | |||||
| // } | |||||
| export const preloadClientProjects = () => { | export const preloadClientProjects = () => { | ||||
| fetchAllClientProjects(); | fetchAllClientProjects(); | ||||
| }; | }; | ||||
| // export const fetchClientProjects = cache(async () => { | |||||
| // return mockProjects; | |||||
| // }); | |||||
| export const fetchAllClientProjects = cache(async () => { | export const fetchAllClientProjects = cache(async () => { | ||||
| return serverFetchJson<ClientProjectResult[]>(`${BASE_API_URL}/dashboard/searchCustomerSubsidiary`); | return serverFetchJson<ClientProjectResult[]>(`${BASE_API_URL}/dashboard/searchCustomerSubsidiary`); | ||||
| }); | }); | ||||
| // export const fetchAllClientSubsidiaryProjects = cache(async (customerId: number, subsidiaryId: number) => { | |||||
| // return serverFetchJson<ClientSubsidiaryProjectResult>( | |||||
| // `${BASE_API_URL}/dashboard/searchCustomerSubsidiaryProject/?${customerId}&${subsidiaryId}`, | |||||
| // { | |||||
| // next: { tags: [`allClientSubsidiaryProjects`] }, | |||||
| // }, | |||||
| // ); | |||||
| // }); | |||||
| // const mockProjects: ClientProjectResult[] = [ | |||||
| // { | |||||
| // id: 1, | |||||
| // clientCode: "CUST-001", | |||||
| // clientName: "Client A", | |||||
| // SubsidiaryClientCode: "N/A", | |||||
| // SubsidiaryClientName: "N/A", | |||||
| // NoOfProjects: 5, | |||||
| // }, | |||||
| // { | |||||
| // id: 2, | |||||
| // clientCode: "CUST-001", | |||||
| // clientName: "Client A", | |||||
| // SubsidiaryClientCode: "SUBS-001", | |||||
| // SubsidiaryClientName: "Subsidiary A", | |||||
| // NoOfProjects: 5, | |||||
| // }, | |||||
| // { | |||||
| // id: 3, | |||||
| // clientCode: "CUST-001", | |||||
| // clientName: "Client A", | |||||
| // SubsidiaryClientCode: "SUBS-002", | |||||
| // SubsidiaryClientName: "Subsidiary B", | |||||
| // NoOfProjects: 3, | |||||
| // }, | |||||
| // { | |||||
| // id: 4, | |||||
| // clientCode: "CUST-001", | |||||
| // clientName: "Client A", | |||||
| // SubsidiaryClientCode: "SUBS-003", | |||||
| // SubsidiaryClientName: "Subsidiary C", | |||||
| // NoOfProjects: 1, | |||||
| // }, | |||||
| // ]; | |||||
| @@ -0,0 +1,54 @@ | |||||
| "use server"; | |||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| import { Dayjs } from "dayjs"; | |||||
| import { cache } from "react"; | |||||
| export interface FinancialSummaryByClientResult { | |||||
| teamId:number; | |||||
| id:number; | |||||
| customerCode: string; | |||||
| customerName: string; | |||||
| projectNo: number; | |||||
| totalFee: number; | |||||
| totalBudget: number; | |||||
| cumulativeExpenditure: number; | |||||
| totalInvoiced: number; | |||||
| totalReceived: number; | |||||
| cashFlowStatus: string; | |||||
| cpi: number; | |||||
| totalUninvoiced: number; | |||||
| } | |||||
| export interface FinancialSummaryByProjectResult { | |||||
| teamId:number; | |||||
| id:number; | |||||
| projectCode: string; | |||||
| projectName: string; | |||||
| customerName: string; | |||||
| projectNo: number; | |||||
| totalFee: number; | |||||
| totalBudget: number; | |||||
| cumulativeExpenditure: number; | |||||
| totalInvoiced: number; | |||||
| totalReceived: number; | |||||
| cashFlowStatus: string; | |||||
| cpi: number; | |||||
| totalUninvoiced: number; | |||||
| } | |||||
| export const searchFinancialSummaryByClient = cache(async (teamId: number) => { | |||||
| return serverFetchJson<FinancialSummaryByClientResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByClient?teamId=${teamId}` | |||||
| ); | |||||
| }); | |||||
| export const searchFinancialSummaryByProject = cache(async (teamId: number) => { | |||||
| return serverFetchJson<FinancialSummaryByProjectResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByProject?teamId=${teamId}` | |||||
| ); | |||||
| }); | |||||
| @@ -0,0 +1,27 @@ | |||||
| "use server"; | |||||
| import { cache } from "react"; | |||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| // import "server-only"; | |||||
| export interface FinancialSummaryCardResult { | |||||
| teamId: number; | |||||
| teamName: string; | |||||
| projectNo: number; | |||||
| totalFee: number; | |||||
| totalBudget: number; | |||||
| cumulativeExpenditure: number; | |||||
| totalInvoiced: number; | |||||
| totalReceived: number; | |||||
| cashFlowStatus: string; | |||||
| cpi: number; | |||||
| } | |||||
| export const preloadFinancialSummaryCard = () => { | |||||
| fetchFinancialSummaryCard(); | |||||
| }; | |||||
| export const fetchFinancialSummaryCard = cache(async () => { | |||||
| return serverFetchJson<FinancialSummaryCardResult[]>(`${BASE_API_URL}/dashboard/searchFinancialSummaryCard`); | |||||
| }); | |||||
| @@ -0,0 +1,29 @@ | |||||
| "use server"; | |||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| import { Dayjs } from "dayjs"; | |||||
| import { cache } from "react"; | |||||
| export interface ClientSubsidiaryProjectResult { | |||||
| color: string; | |||||
| projectId: number; | |||||
| projectCode: string; | |||||
| projectName: string; | |||||
| team: string; | |||||
| teamLead: string; | |||||
| expectedStage: string; | |||||
| budgetedManhour: number; | |||||
| spentManhour: number; | |||||
| remainedManhour: number; | |||||
| manhourConsumptionPercentage: number; | |||||
| comingPaymentMilestone: string; | |||||
| } | |||||
| export const fetchAllTeamProjects = cache(async (teamLeadId: number) => { | |||||
| return serverFetchJson<ClientSubsidiaryProjectResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchTeamProject?teamLeadId=${teamLeadId}` | |||||
| ); | |||||
| }); | |||||
| @@ -1,10 +1,15 @@ | |||||
| import { cache } from "react"; | import { cache } from "react"; | ||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| import "server-only"; | |||||
| export interface TeamProjectResult { | export interface TeamProjectResult { | ||||
| id: number; | id: number; | ||||
| teamId: number; | |||||
| teamLeadId: number; | |||||
| teamCode: string; | teamCode: string; | ||||
| teamName: string; | teamName: string; | ||||
| NoOfProjects: number; | |||||
| projectNo: number; | |||||
| } | } | ||||
| export const preloadProjects = () => { | export const preloadProjects = () => { | ||||
| @@ -12,32 +17,6 @@ export const preloadProjects = () => { | |||||
| }; | }; | ||||
| export const fetchTeamProjects = cache(async () => { | export const fetchTeamProjects = cache(async () => { | ||||
| return mockProjects; | |||||
| return serverFetchJson<TeamProjectResult[]>(`${BASE_API_URL}/dashboard/searchTeamProjectNo`); | |||||
| }); | }); | ||||
| const mockProjects: TeamProjectResult[] = [ | |||||
| { | |||||
| id: 1, | |||||
| teamCode: "TEAM-001", | |||||
| teamName: "Team A", | |||||
| NoOfProjects: 5, | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| teamCode: "TEAM-002", | |||||
| teamName: "Team B", | |||||
| NoOfProjects: 5, | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| teamCode: "TEAM-003", | |||||
| teamName: "Team C", | |||||
| NoOfProjects: 3, | |||||
| }, | |||||
| { | |||||
| id: 4, | |||||
| teamCode: "TEAM-004", | |||||
| teamName: "Team D", | |||||
| NoOfProjects: 1, | |||||
| }, | |||||
| ]; | |||||
| @@ -303,130 +303,6 @@ const ProgressByClient: React.FC<Props> = () => { | |||||
| flex:0.1 | flex:0.1 | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| const optionstest: ApexOptions = { | |||||
| chart: { | |||||
| height: 350, | |||||
| type: "line", | |||||
| }, | |||||
| stroke: { | |||||
| width: [0, 0, 2, 2], | |||||
| }, | |||||
| plotOptions: { | |||||
| bar: { | |||||
| horizontal: false, | |||||
| distributed: false, | |||||
| }, | |||||
| }, | |||||
| dataLabels: { | |||||
| enabled: false, | |||||
| }, | |||||
| xaxis: { | |||||
| categories: [ | |||||
| "Q1", | |||||
| "Q2", | |||||
| "Q3", | |||||
| "Q4", | |||||
| "Q5", | |||||
| "Q6", | |||||
| "Q7", | |||||
| "Q8", | |||||
| "Q9", | |||||
| "Q10", | |||||
| "Q11", | |||||
| "Q12", | |||||
| ], | |||||
| }, | |||||
| yaxis: [ | |||||
| { | |||||
| title: { | |||||
| text: "Monthly Income and Expenditure(HKD)", | |||||
| }, | |||||
| min: 0, | |||||
| max: 350000, | |||||
| tickAmount: 5, | |||||
| labels: { | |||||
| formatter: function (val) { | |||||
| return val.toLocaleString() | |||||
| } | |||||
| } | |||||
| }, | |||||
| { | |||||
| show: false, | |||||
| seriesName: "Monthly_Expenditure", | |||||
| title: { | |||||
| text: "Monthly Expenditure (HKD)", | |||||
| }, | |||||
| min: 0, | |||||
| max: 350000, | |||||
| tickAmount: 5, | |||||
| }, | |||||
| { | |||||
| seriesName: "Cumulative_Income", | |||||
| opposite: true, | |||||
| title: { | |||||
| text: "Cumulative Income and Expenditure(HKD)", | |||||
| }, | |||||
| min: 0, | |||||
| max: 850000, | |||||
| tickAmount: 5, | |||||
| labels: { | |||||
| formatter: function (val) { | |||||
| return val.toLocaleString() | |||||
| } | |||||
| } | |||||
| }, | |||||
| { | |||||
| show: false, | |||||
| seriesName: "Cumulative_Expenditure", | |||||
| opposite: true, | |||||
| title: { | |||||
| text: "Cumulative Expenditure (HKD)", | |||||
| }, | |||||
| min: 0, | |||||
| max: 850000, | |||||
| tickAmount: 5, | |||||
| }, | |||||
| ], | |||||
| grid: { | |||||
| borderColor: "#f1f1f1", | |||||
| }, | |||||
| annotations: {}, | |||||
| series: [ | |||||
| { | |||||
| name: "Monthly_Income", | |||||
| type: "column", | |||||
| color: "#ffde91", | |||||
| data: [0, 110000, 0, 0, 185000, 0, 0, 189000, 0, 0, 300000, 0], | |||||
| }, | |||||
| { | |||||
| name: "Monthly_Expenditure", | |||||
| type: "column", | |||||
| color: "#82b59a", | |||||
| data: [ | |||||
| 0, 160000, 120000, 120000, 55000, 55000, 55000, 55000, 55000, 70000, | |||||
| 55000, 55000, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| name: "Cumulative_Income", | |||||
| type: "line", | |||||
| color: "#EE6D7A", | |||||
| data: [ | |||||
| 0, 100000, 100000, 100000, 300000, 300000, 300000, 500000, 500000, | |||||
| 500000, 800000, 800000, | |||||
| ], | |||||
| }, | |||||
| { | |||||
| name: "Cumulative_Expenditure", | |||||
| type: "line", | |||||
| color: "#7cd3f2", | |||||
| data: [ | |||||
| 0, 198000, 240000, 400000, 410000, 430000, 510000, 580000, 600000, | |||||
| 710000, 730000, 790000, | |||||
| ], | |||||
| }, | |||||
| ], | |||||
| }; | |||||
| const options2: ApexOptions = { | const options2: ApexOptions = { | ||||
| chart: { | chart: { | ||||
| @@ -18,9 +18,13 @@ import { AnyARecord, AnyCnameRecord } from "dns"; | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
| import ProgressByTeamSearch from "@/components/ProgressByTeamSearch"; | import ProgressByTeamSearch from "@/components/ProgressByTeamSearch"; | ||||
| import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
| import { useSearchParams } from 'next/navigation'; | |||||
| import { fetchAllTeamProjects} from "@/app/api/teamprojects/actions"; | |||||
| // const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false }); | // const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false }); | ||||
| const ProgressByTeam: React.FC = () => { | const ProgressByTeam: React.FC = () => { | ||||
| const searchParams = useSearchParams(); | |||||
| const teamLeadId = searchParams.get('teamLeadId'); | |||||
| const [activeTab, setActiveTab] = useState("financialSummary"); | const [activeTab, setActiveTab] = useState("financialSummary"); | ||||
| const [SearchCriteria, setSearchCriteria] = React.useState({}); | const [SearchCriteria, setSearchCriteria] = React.useState({}); | ||||
| const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
| @@ -44,6 +48,64 @@ const ProgressByTeam: React.FC = () => { | |||||
| const [receiptFromDate, setReceiptFromDate] = useState(null); | const [receiptFromDate, setReceiptFromDate] = useState(null); | ||||
| const [receiptToDate, setReceiptToDate] = useState(null); | const [receiptToDate, setReceiptToDate] = useState(null); | ||||
| const [selectedRows, setSelectedRows] = useState([]); | const [selectedRows, setSelectedRows] = useState([]); | ||||
| const [chartProjectName, setChartProjectName]: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 fetchData = async () => { | |||||
| if (teamLeadId) { | |||||
| try { | |||||
| const clickResult = await fetchAllTeamProjects( | |||||
| Number(teamLeadId)) | |||||
| console.log(clickResult) | |||||
| setTeamProjectResult(clickResult); | |||||
| } catch (error) { | |||||
| console.error('Error fetching team projects:', error); | |||||
| } | |||||
| } | |||||
| } | |||||
| useEffect(() => { | |||||
| const projectName = [] | |||||
| const manhourConsumptionPercentage = [] | |||||
| for (let i = 0; i < teamProjectResult.length; i++){ | |||||
| teamProjectResult[i].color = color[i] | |||||
| projectName.push(teamProjectResult[i].projectName) | |||||
| manhourConsumptionPercentage.push(teamProjectResult[i].manhourConsumptionPercentage) | |||||
| } | |||||
| setChartProjectName(projectName) | |||||
| setChartManhourConsumptionPercentage(manhourConsumptionPercentage) | |||||
| }, [teamProjectResult]); | |||||
| useEffect(() => { | |||||
| fetchData() | |||||
| }, [teamLeadId]); | |||||
| const rows = [ | const rows = [ | ||||
| { | { | ||||
| id: 1, | id: 1, | ||||
| @@ -373,7 +435,35 @@ const ProgressByTeam: React.FC = () => { | |||||
| type: "bar", | type: "bar", | ||||
| height: 350, | height: 350, | ||||
| }, | }, | ||||
| colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"], | |||||
| series: [{ | |||||
| name: "Project Resource Consumption Percentage", | |||||
| data: chartManhourConsumptionPercentage, | |||||
| },], | |||||
| colors: ["#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"], | |||||
| plotOptions: { | plotOptions: { | ||||
| bar: { | bar: { | ||||
| horizontal: true, | horizontal: true, | ||||
| @@ -384,13 +474,7 @@ const ProgressByTeam: React.FC = () => { | |||||
| enabled: false, | enabled: false, | ||||
| }, | }, | ||||
| xaxis: { | xaxis: { | ||||
| categories: [ | |||||
| "Consultancy Project 123", | |||||
| "Consultancy Project 456", | |||||
| "Construction Project A", | |||||
| "Construction Project B", | |||||
| "Construction Project C", | |||||
| ], | |||||
| categories: chartProjectName, | |||||
| }, | }, | ||||
| yaxis: { | yaxis: { | ||||
| title: { | title: { | ||||
| @@ -414,7 +498,7 @@ const ProgressByTeam: React.FC = () => { | |||||
| }; | }; | ||||
| const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
| const selectedRowsData = rows2.filter((row) => | |||||
| const selectedRowsData = teamProjectResult.filter((row:any) => | |||||
| newSelectionModel.includes(row.id), | newSelectionModel.includes(row.id), | ||||
| ); | ); | ||||
| console.log(selectedRowsData); | console.log(selectedRowsData); | ||||
| @@ -427,7 +511,7 @@ const ProgressByTeam: React.FC = () => { | |||||
| if (i === selectedRowsData.length && i > 0) { | if (i === selectedRowsData.length && i > 0) { | ||||
| projectArray.push("Remained"); | projectArray.push("Remained"); | ||||
| } else if (selectedRowsData.length > 0) { | } else if (selectedRowsData.length > 0) { | ||||
| projectArray.push(selectedRowsData[i].project); | |||||
| projectArray.push(selectedRowsData[i].projectName); | |||||
| totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); | totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); | ||||
| totalSpent += Number(selectedRowsData[i].spentManhour); | totalSpent += Number(selectedRowsData[i].spentManhour); | ||||
| pieChartColorArray.push(selectedRowsData[i].color); | pieChartColorArray.push(selectedRowsData[i].color); | ||||
| @@ -485,7 +569,7 @@ const ProgressByTeam: React.FC = () => { | |||||
| <div style={{ display: "inline-block", width: "99%" }}> | <div style={{ display: "inline-block", width: "99%" }}> | ||||
| <ReactApexChart | <ReactApexChart | ||||
| options={options} | options={options} | ||||
| series={series} | |||||
| series={options.series} | |||||
| type="bar" | type="bar" | ||||
| height={350} | height={350} | ||||
| /> | /> | ||||
| @@ -507,7 +591,7 @@ const ProgressByTeam: React.FC = () => { | |||||
| style={{ display: "inline-block", width: "99%", marginLeft: 10 }} | style={{ display: "inline-block", width: "99%", marginLeft: 10 }} | ||||
| > | > | ||||
| <CustomDatagrid | <CustomDatagrid | ||||
| rows={rows2} | |||||
| rows={teamProjectResult} | |||||
| columns={columns2} | columns={columns2} | ||||
| columnWidth={200} | columnWidth={200} | ||||
| dataGridHeight={300} | dataGridHeight={300} | ||||
| @@ -1,11 +1,13 @@ | |||||
| "use client"; | "use client"; | ||||
| import { ProjectResult } from "@/app/api/projects"; | import { ProjectResult } from "@/app/api/projects"; | ||||
| import React, { useMemo, useState } from "react"; | |||||
| import React, { useMemo, useState, useCallback } from "react"; | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
| import { TeamProjectResult } from "@/app/api/teamprojects"; | import { TeamProjectResult } from "@/app/api/teamprojects"; | ||||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||||
| import { useRouter, useSearchParams } from "next/navigation"; | |||||
| interface Props { | interface Props { | ||||
| projects: TeamProjectResult[]; | projects: TeamProjectResult[]; | ||||
| @@ -15,7 +17,7 @@ type SearchParamNames = keyof SearchQuery; | |||||
| const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | ||||
| const { t } = useTranslation("projects"); | const { t } = useTranslation("projects"); | ||||
| const router = useRouter(); | |||||
| // If project searching is done on the server-side, then no need for this. | // If project searching is done on the server-side, then no need for this. | ||||
| const [filteredProjects, setFilteredProjects] = useState(projects); | const [filteredProjects, setFilteredProjects] = useState(projects); | ||||
| @@ -27,13 +29,31 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||||
| [t], | [t], | ||||
| ); | ); | ||||
| const onTaskClick = useCallback(async (teamProjectResult: TeamProjectResult) => { | |||||
| try { | |||||
| console.log(teamProjectResult) | |||||
| router.push( | |||||
| `/dashboard/ProjectStatusByTeam?teamLeadId=${teamProjectResult.teamLeadId}` | |||||
| ); | |||||
| } catch (error) { | |||||
| console.error('Error fetching team projects:', error); | |||||
| } | |||||
| }, []); | |||||
| const columns = useMemo<Column<TeamProjectResult>[]>( | const columns = useMemo<Column<TeamProjectResult>[]>( | ||||
| () => [ | () => [ | ||||
| { | |||||
| name: "id", | |||||
| label: t("Details"), | |||||
| onClick: onTaskClick, | |||||
| buttonIcon: <VisibilityIcon />, | |||||
| }, | |||||
| { name: "teamCode", label: t("Team Code") }, | { name: "teamCode", label: t("Team Code") }, | ||||
| { name: "teamName", label: t("Team Name") }, | { name: "teamName", label: t("Team Name") }, | ||||
| { name: "NoOfProjects", label: t("No. of Projects") }, | |||||
| { name: "projectNo", label: t("No. of Projects") }, | |||||
| ], | ], | ||||
| [t], | |||||
| [onTaskClick, t], | |||||
| ); | ); | ||||
| return ( | return ( | ||||
| @@ -41,7 +61,13 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||||
| <SearchBox | <SearchBox | ||||
| criteria={searchCriteria} | criteria={searchCriteria} | ||||
| onSearch={(query) => { | onSearch={(query) => { | ||||
| console.log(query); | |||||
| setFilteredProjects( | |||||
| projects.filter( | |||||
| (cp) => | |||||
| cp.teamCode.toLowerCase().includes(query.teamCode.toLowerCase()) && | |||||
| cp.teamName.toLowerCase().includes(query.teamName.toLowerCase()) | |||||
| ), | |||||
| ); | |||||
| }} | }} | ||||
| /> | /> | ||||
| <SearchResults<TeamProjectResult> | <SearchResults<TeamProjectResult> | ||||
| @@ -20,14 +20,14 @@ import { Suspense } from "react"; | |||||
| interface Props { | interface Props { | ||||
| Title: string; | Title: string; | ||||
| TotalActiveProjectNumber: string; | |||||
| TotalFees: string; | |||||
| TotalBudget: string; | |||||
| TotalCumulative: string; | |||||
| TotalInvoicedAmount: string; | |||||
| TotalReceivedAmount: string; | |||||
| TotalActiveProjectNumber: number; | |||||
| TotalFees: number; | |||||
| TotalBudget: number; | |||||
| TotalCumulative: number; | |||||
| TotalInvoicedAmount: number; | |||||
| TotalReceivedAmount: number; | |||||
| CashFlowStatus: string; | CashFlowStatus: string; | ||||
| CostPerformanceIndex: string; | |||||
| CostPerformanceIndex: number; | |||||
| ClickedIndex: number; | ClickedIndex: number; | ||||
| Index: number; | Index: number; | ||||
| } | } | ||||
| @@ -77,42 +77,42 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||||
| Total Active Project | Total Active Project | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalActiveProjectNumber} | |||||
| {TotalActiveProjectNumber.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Fees | Total Fees | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalFees} | |||||
| {TotalFees.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Budget | Total Budget | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalBudget} | |||||
| {TotalBudget.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Cumulative Expenditure | Total Cumulative Expenditure | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalCumulative} | |||||
| {TotalCumulative.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Invoiced Amount | Total Invoiced Amount | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalInvoicedAmount} | |||||
| {TotalInvoicedAmount.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Received Amount | Total Received Amount | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalReceivedAmount} | |||||
| {TotalReceivedAmount.toLocaleString()} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| @@ -18,86 +18,32 @@ import { AnyARecord, AnyCnameRecord } from "dns"; | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
| import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
| import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
| import { fetchFinancialSummaryCard } from "@/app/api/financialsummary"; | |||||
| import { searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions"; | |||||
| import ProjectFinancialCard from "./ProjectFinancialCard"; | import ProjectFinancialCard from "./ProjectFinancialCard"; | ||||
| const ProjectFinancialSummary: React.FC = () => { | const ProjectFinancialSummary: React.FC = () => { | ||||
| const [SearchCriteria, setSearchCriteria] = React.useState({}); | const [SearchCriteria, setSearchCriteria] = React.useState({}); | ||||
| const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
| const [selectionModel, setSelectionModel]: any[] = React.useState([]); | const [selectionModel, setSelectionModel]: any[] = React.useState([]); | ||||
| const projectFinancialData = [ | |||||
| { | |||||
| id: 1, | |||||
| title: "All Teams", | |||||
| activeProject: "147", | |||||
| fees: "22,800,000.00", | |||||
| budget: "18,240,000.00", | |||||
| cumulativeExpenditure: "17,950,000.00", | |||||
| invoicedAmount: "18,240,000.00", | |||||
| receivedAmount: "10,900,000.00", | |||||
| cashFlowStatus: "Negative", | |||||
| CPI: "0.69", | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| title: "XXX Team", | |||||
| activeProject: "25", | |||||
| fees: "1,500,000.00", | |||||
| budget: "1,200,000.00", | |||||
| cumulativeExpenditure: "1,250,000.00", | |||||
| invoicedAmount: "900,000.00", | |||||
| receivedAmount: "650,000.00", | |||||
| cashFlowStatus: "Negative", | |||||
| CPI: "0.72", | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| title: "YYY Team", | |||||
| activeProject: "35", | |||||
| fees: "5,000,000.00", | |||||
| budget: "4,000,000.00", | |||||
| cumulativeExpenditure: "3,200,000.00", | |||||
| invoicedAmount: "3,500,000.00", | |||||
| receivedAmount: "3,500,000.00", | |||||
| cashFlowStatus: "Positive", | |||||
| CPI: "1.09", | |||||
| }, | |||||
| { | |||||
| id: 4, | |||||
| title: "ZZZ Team", | |||||
| activeProject: "50", | |||||
| fees: "3,500,000.00", | |||||
| budget: "2,800,000.00", | |||||
| cumulativeExpenditure: "5,600,000.00", | |||||
| invoicedAmount: "2,500,000.00", | |||||
| receivedAmount: "2,200,000.00", | |||||
| cashFlowStatus: "Negative", | |||||
| CPI: "0.45", | |||||
| }, | |||||
| { | |||||
| id: 5, | |||||
| title: "AAA Team", | |||||
| activeProject: "15", | |||||
| fees: "4,800,000.00", | |||||
| budget: "3,840,000.00", | |||||
| cumulativeExpenditure: "2,500,000.00", | |||||
| invoicedAmount: "1,500,000.00", | |||||
| receivedAmount: "750,000.00", | |||||
| cashFlowStatus: "Negative", | |||||
| CPI: "0.60", | |||||
| }, | |||||
| { | |||||
| id: 6, | |||||
| title: "BBB Team", | |||||
| activeProject: "22", | |||||
| fees: "8,000,000.00", | |||||
| budget: "6,400,000.00", | |||||
| cumulativeExpenditure: "5,400,000.00", | |||||
| invoicedAmount: "4,000,000.00", | |||||
| receivedAmount: "3,800,000.00", | |||||
| cashFlowStatus: "Negative", | |||||
| CPI: "0.74", | |||||
| }, | |||||
| ]; | |||||
| const [projectFinancialData, setProjectFinancialData]: any[] = React.useState([]); | |||||
| const [clientFinancialRows, setClientFinancialRows]: any[] = React.useState([]); | |||||
| const [projectFinancialRows, setProjectFinancialRows]: any[] = React.useState([]); | |||||
| const fetchData = async () => { | |||||
| const financialSummaryCard = await fetchFinancialSummaryCard(); | |||||
| setProjectFinancialData(financialSummaryCard) | |||||
| } | |||||
| const fetchTableData = async (teamId:any) => { | |||||
| const financialSummaryByClient = await searchFinancialSummaryByClient(teamId); | |||||
| const financialSummaryByProject = await searchFinancialSummaryByProject(teamId); | |||||
| console.log(financialSummaryByClient) | |||||
| console.log(financialSummaryByProject) | |||||
| setClientFinancialRows(financialSummaryByClient) | |||||
| setProjectFinancialRows(financialSummaryByProject) | |||||
| } | |||||
| useEffect(() => { | |||||
| fetchData() | |||||
| }, []); | |||||
| const rows0 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, | const rows0 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, | ||||
| {id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, | {id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, | ||||
| @@ -115,45 +61,46 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| {id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | {id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | ||||
| ] | ] | ||||
| const projectFinancialRows = [{id: 1,projectCode:"M1354",projectName:"Consultanct Project BBB",clientName:"Client D",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} | |||||
| ] | |||||
| // const projectFinancialRows = [{id: 1,projectCode:"M1354",projectName:"Consultanct Project BBB",clientName:"Client D",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} | |||||
| // ] | |||||
| const clientFinancialRows =[{id: 1,clientCode:"Cust-02",clientName:"Client B",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, | |||||
| {id: 2,clientCode:"Cust-03",clientName:"Client C",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, | |||||
| {id: 3,clientCode:"Cust-04",clientName:"Client D",totalProjectInvolved:"4",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} | |||||
| ] | |||||
| // const clientFinancialRows =[{id: 1,clientCode:"Cust-02",clientName:"Client B",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, | |||||
| // {id: 2,clientCode:"Cust-03",clientName:"Client C",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, | |||||
| // {id: 3,clientCode:"Cust-04",clientName:"Client D",totalProjectInvolved:"4",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} | |||||
| // ] | |||||
| const [isCardClickedIndex, setIsCardClickedIndex] = React.useState(0); | const [isCardClickedIndex, setIsCardClickedIndex] = React.useState(0); | ||||
| const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); | const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); | ||||
| const handleCardClick = (r: any) => { | const handleCardClick = (r: any) => { | ||||
| setIsCardClickedIndex(r); | |||||
| if (r === 0) { | |||||
| setSelectedTeamData(rows0); | |||||
| } else if (r === 1) { | |||||
| setSelectedTeamData(rows1); | |||||
| } else if (r === 2) { | |||||
| setSelectedTeamData(rows2); | |||||
| } | |||||
| fetchTableData(r.teamId) | |||||
| // setIsCardClickedIndex(r); | |||||
| // if (r === 0) { | |||||
| // setSelectedTeamData(rows0); | |||||
| // } else if (r === 1) { | |||||
| // setSelectedTeamData(rows1); | |||||
| // } else if (r === 2) { | |||||
| // setSelectedTeamData(rows2); | |||||
| // } | |||||
| }; | }; | ||||
| const columns = [ | const columns = [ | ||||
| { | { | ||||
| id: 'clientCode', | |||||
| field: 'clientCode', | |||||
| id: 'customerCode', | |||||
| field: 'customerCode', | |||||
| headerName: "Client Code", | headerName: "Client Code", | ||||
| flex: 0.7, | flex: 0.7, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'clientName', | |||||
| field: 'clientName', | |||||
| id: 'customerName', | |||||
| field: 'customerName', | |||||
| headerName: "Client Name", | headerName: "Client Name", | ||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalProjectInvolved', | |||||
| field: 'totalProjectInvolved', | |||||
| id: 'projectNo', | |||||
| field: 'projectNo', | |||||
| headerName: "Total Project Involved", | headerName: "Total Project Involved", | ||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| @@ -163,6 +110,7 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| headerName: "Cash Flow Status", | headerName: "Cash Flow Status", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| console.log(params.row) | |||||
| if (params.row.cashFlowStatus === "Positive") { | if (params.row.cashFlowStatus === "Positive") { | ||||
| return ( | return ( | ||||
| <span className="text-lime-500">{params.row.cashFlowStatus}</span> | <span className="text-lime-500">{params.row.cashFlowStatus}</span> | ||||
| @@ -192,13 +140,13 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalFees', | |||||
| field: 'totalFees', | |||||
| id: 'totalFee', | |||||
| field: 'totalFee', | |||||
| headerName: "Total Fees (HKD)", | headerName: "Total Fees (HKD)", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalFees}</span> | |||||
| <span>${params.row.totalFee}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -214,46 +162,46 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalCumulativeExpenditure', | |||||
| field: 'totalCumulativeExpenditure', | |||||
| id: 'cumulativeExpenditure', | |||||
| field: 'cumulativeExpenditure', | |||||
| headerName: "Total Cumulative Expenditure (HKD)", | headerName: "Total Cumulative Expenditure (HKD)", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalCumulativeExpenditure}</span> | |||||
| <span>${params.row.cumulativeExpenditure}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalInvoicedAmount', | |||||
| field: 'totalInvoicedAmount', | |||||
| id: 'totalInvoiced', | |||||
| field: 'totalInvoiced', | |||||
| headerName: "Total Invoiced Amount (HKD)", | headerName: "Total Invoiced Amount (HKD)", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalInvoicedAmount}</span> | |||||
| <span>${params.row.totalInvoiced}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalUnInvoicedAmount', | |||||
| field: 'totalUnInvoicedAmount', | |||||
| id: 'totalUnInvoiced', | |||||
| field: 'totalUnInvoiced', | |||||
| headerName: "Total Un-invoiced Amount (HKD)", | headerName: "Total Un-invoiced Amount (HKD)", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalUnInvoicedAmount}</span> | |||||
| <span>${params.row.totalUninvoiced}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'totalReceivedAmount', | |||||
| field: 'totalReceivedAmount', | |||||
| id: 'totalReceived', | |||||
| field: 'totalReceived', | |||||
| headerName: "Total Received Amount (HKD)", | headerName: "Total Received Amount (HKD)", | ||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalReceivedAmount}</span> | |||||
| <span>${params.row.totalReceived}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -322,8 +270,8 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| { | { | ||||
| id: 'clientName', | |||||
| field: 'clientName', | |||||
| id: 'customerName', | |||||
| field: 'customerName', | |||||
| headerName: "Client Name", | headerName: "Client Name", | ||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| @@ -365,7 +313,7 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalFees}</span> | |||||
| <span>${params.row.totalFee}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -387,7 +335,7 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalCumulativeExpenditure}</span> | |||||
| <span>${params.row.cumulativeExpenditure}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -398,7 +346,7 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalInvoicedAmount}</span> | |||||
| <span>${params.row.totalInvoiced}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -409,7 +357,7 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalUnInvoicedAmount}</span> | |||||
| <span>${params.row.totalUninvoiced}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -420,7 +368,7 @@ const columns2 = [ | |||||
| flex: 1, | flex: 1, | ||||
| renderCell: (params:any) => { | renderCell: (params:any) => { | ||||
| return ( | return ( | ||||
| <span>${params.row.totalReceivedAmount}</span> | |||||
| <span>${params.row.totalReceived}</span> | |||||
| ) | ) | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -438,9 +386,9 @@ const columns2 = [ | |||||
| <Card> | <Card> | ||||
| <CardHeader className="text-slate-500" title="Active Project Financial Status"/> | <CardHeader className="text-slate-500" title="Active Project Financial Status"/> | ||||
| <div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}> | <div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}> | ||||
| {projectFinancialData.map((record, index) => ( | |||||
| <div className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" key={index} onClick={(r) => handleCardClick(index)}> | |||||
| <ProjectFinancialCard Title={record.title} TotalActiveProjectNumber={record.activeProject} TotalFees={record.fees} TotalBudget={record.budget} TotalCumulative={record.cumulativeExpenditure} TotalInvoicedAmount={record.invoicedAmount} TotalReceivedAmount={record.receivedAmount} CashFlowStatus={record.cashFlowStatus} CostPerformanceIndex={record.CPI} ClickedIndex={isCardClickedIndex} Index={index}/> | |||||
| {projectFinancialData.map((record:any, index:any) => ( | |||||
| <div className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" key={index} onClick={(r) => handleCardClick(record)}> | |||||
| <ProjectFinancialCard Title={record.teamName} TotalActiveProjectNumber={record.projectNo} TotalFees={record.totalFee} TotalBudget={record.totalBudget} TotalCumulative={record.cumulativeExpenditure} TotalInvoicedAmount={record.totalInvoiced} TotalReceivedAmount={record.totalReceived} CashFlowStatus={record.cashFlowStatus} CostPerformanceIndex={record.cpi} ClickedIndex={isCardClickedIndex} Index={index}/> | |||||
| </div> | </div> | ||||
| ))} | ))} | ||||
| </div> | </div> | ||||