Sfoglia il codice sorgente

use financial summary api

tags/Baseline_30082024_FRONTEND_UAT
Mac\David 1 anno fa
parent
commit
6e20b03c6d
10 ha cambiato i file con 324 aggiunte e 363 eliminazioni
  1. +0
    -62
      src/app/api/clientprojects/index.ts
  2. +54
    -0
      src/app/api/financialsummary/actions.ts
  3. +27
    -0
      src/app/api/financialsummary/index.ts
  4. +29
    -0
      src/app/api/teamprojects/actions.ts
  5. +7
    -28
      src/app/api/teamprojects/index.ts
  6. +0
    -124
      src/components/ProgressByClient/ProgressByClient.tsx
  7. +96
    -12
      src/components/ProgressByTeam/ProgressByTeam.tsx
  8. +31
    -5
      src/components/ProgressByTeamSearch/ProgressByTeamSearch.tsx
  9. +13
    -13
      src/components/ProjectFinancialSummary/ProjectFinancialCard.tsx
  10. +67
    -119
      src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx

+ 0
- 62
src/app/api/clientprojects/index.ts Vedi File

@@ -15,72 +15,10 @@ export interface ClientProjectResult {
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 = () => {
fetchAllClientProjects();
};

// export const fetchClientProjects = cache(async () => {
// return mockProjects;
// });

export const fetchAllClientProjects = cache(async () => {
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,
// },
// ];

+ 54
- 0
src/app/api/financialsummary/actions.ts Vedi File

@@ -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}`
);
});

+ 27
- 0
src/app/api/financialsummary/index.ts Vedi File

@@ -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`);
});

+ 29
- 0
src/app/api/teamprojects/actions.ts Vedi File

@@ -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}`
);

});

+ 7
- 28
src/app/api/teamprojects/index.ts Vedi File

@@ -1,10 +1,15 @@
import { cache } from "react";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import "server-only";

export interface TeamProjectResult {
id: number;
teamId: number;
teamLeadId: number;
teamCode: string;
teamName: string;
NoOfProjects: number;
projectNo: number;
}

export const preloadProjects = () => {
@@ -12,32 +17,6 @@ export const preloadProjects = () => {
};

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,
},
];

+ 0
- 124
src/components/ProgressByClient/ProgressByClient.tsx Vedi File

@@ -303,130 +303,6 @@ const ProgressByClient: React.FC<Props> = () => {
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 = {
chart: {


+ 96
- 12
src/components/ProgressByTeam/ProgressByTeam.tsx Vedi File

@@ -18,9 +18,13 @@ 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} from "@/app/api/teamprojects/actions";
// const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });

const ProgressByTeam: React.FC = () => {
const searchParams = useSearchParams();
const teamLeadId = searchParams.get('teamLeadId');
const [activeTab, setActiveTab] = useState("financialSummary");
const [SearchCriteria, setSearchCriteria] = React.useState({});
const { t } = useTranslation("dashboard");
@@ -44,6 +48,64 @@ const ProgressByTeam: React.FC = () => {
const [receiptFromDate, setReceiptFromDate] = useState(null);
const [receiptToDate, setReceiptToDate] = useState(null);
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 = [
{
id: 1,
@@ -373,7 +435,35 @@ const ProgressByTeam: React.FC = () => {
type: "bar",
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: {
bar: {
horizontal: true,
@@ -384,13 +474,7 @@ const ProgressByTeam: React.FC = () => {
enabled: false,
},
xaxis: {
categories: [
"Consultancy Project 123",
"Consultancy Project 456",
"Construction Project A",
"Construction Project B",
"Construction Project C",
],
categories: chartProjectName,
},
yaxis: {
title: {
@@ -414,7 +498,7 @@ const ProgressByTeam: React.FC = () => {
};

const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
const selectedRowsData = rows2.filter((row) =>
const selectedRowsData = teamProjectResult.filter((row:any) =>
newSelectionModel.includes(row.id),
);
console.log(selectedRowsData);
@@ -427,7 +511,7 @@ const ProgressByTeam: React.FC = () => {
if (i === selectedRowsData.length && i > 0) {
projectArray.push("Remained");
} else if (selectedRowsData.length > 0) {
projectArray.push(selectedRowsData[i].project);
projectArray.push(selectedRowsData[i].projectName);
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour);
totalSpent += Number(selectedRowsData[i].spentManhour);
pieChartColorArray.push(selectedRowsData[i].color);
@@ -485,7 +569,7 @@ const ProgressByTeam: React.FC = () => {
<div style={{ display: "inline-block", width: "99%" }}>
<ReactApexChart
options={options}
series={series}
series={options.series}
type="bar"
height={350}
/>
@@ -507,7 +591,7 @@ const ProgressByTeam: React.FC = () => {
style={{ display: "inline-block", width: "99%", marginLeft: 10 }}
>
<CustomDatagrid
rows={rows2}
rows={teamProjectResult}
columns={columns2}
columnWidth={200}
dataGridHeight={300}


+ 31
- 5
src/components/ProgressByTeamSearch/ProgressByTeamSearch.tsx Vedi File

@@ -1,11 +1,13 @@
"use client";

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 { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults";
import { TeamProjectResult } from "@/app/api/teamprojects";
import VisibilityIcon from '@mui/icons-material/Visibility';
import { useRouter, useSearchParams } from "next/navigation";

interface Props {
projects: TeamProjectResult[];
@@ -15,7 +17,7 @@ type SearchParamNames = keyof SearchQuery;

const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
const { t } = useTranslation("projects");
const router = useRouter();
// If project searching is done on the server-side, then no need for this.
const [filteredProjects, setFilteredProjects] = useState(projects);

@@ -27,13 +29,31 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
[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>[]>(
() => [
{
name: "id",
label: t("Details"),
onClick: onTaskClick,
buttonIcon: <VisibilityIcon />,
},
{ name: "teamCode", label: t("Team Code") },
{ name: "teamName", label: t("Team Name") },
{ name: "NoOfProjects", label: t("No. of Projects") },
{ name: "projectNo", label: t("No. of Projects") },
],
[t],
[onTaskClick, t],
);

return (
@@ -41,7 +61,13 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
<SearchBox
criteria={searchCriteria}
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>


+ 13
- 13
src/components/ProjectFinancialSummary/ProjectFinancialCard.tsx Vedi File

@@ -20,14 +20,14 @@ import { Suspense } from "react";

interface Props {
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;
CostPerformanceIndex: string;
CostPerformanceIndex: number;
ClickedIndex: number;
Index: number;
}
@@ -77,42 +77,42 @@ const ProjectFinancialCard: React.FC<Props> = ({
Total Active Project
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalActiveProjectNumber}
{TotalActiveProjectNumber.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>
Total Fees
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalFees}
{TotalFees.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>
Total Budget
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalBudget}
{TotalBudget.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>
Total Cumulative Expenditure
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalCumulative}
{TotalCumulative.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>
Total Invoiced Amount
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalInvoicedAmount}
{TotalInvoicedAmount.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>
Total Received Amount
</div>
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}>
{TotalReceivedAmount}
{TotalReceivedAmount.toLocaleString()}
</div>
<hr />
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}>


+ 67
- 119
src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx Vedi File

@@ -18,86 +18,32 @@ import { AnyARecord, AnyCnameRecord } from "dns";
import SearchBox, { Criterion } from "../SearchBox";
import ProgressByClientSearch from "@/components/ProgressByClientSearch";
import { Suspense } from "react";
import { fetchFinancialSummaryCard } from "@/app/api/financialsummary";
import { searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions";
import ProjectFinancialCard from "./ProjectFinancialCard";

const ProjectFinancialSummary: React.FC = () => {
const [SearchCriteria, setSearchCriteria] = React.useState({});
const { t } = useTranslation("dashboard");
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"},
{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"}
]

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 [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0);

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 = [
{
id: 'clientCode',
field: 'clientCode',
id: 'customerCode',
field: 'customerCode',
headerName: "Client Code",
flex: 0.7,
},
{
id: 'clientName',
field: 'clientName',
id: 'customerName',
field: 'customerName',
headerName: "Client Name",
flex: 1,
},
{
id: 'totalProjectInvolved',
field: 'totalProjectInvolved',
id: 'projectNo',
field: 'projectNo',
headerName: "Total Project Involved",
flex: 1,
},
@@ -163,6 +110,7 @@ const ProjectFinancialSummary: React.FC = () => {
headerName: "Cash Flow Status",
flex: 1,
renderCell: (params:any) => {
console.log(params.row)
if (params.row.cashFlowStatus === "Positive") {
return (
<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)",
flex: 1,
renderCell: (params:any) => {
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)",
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalCumulativeExpenditure}</span>
<span>${params.row.cumulativeExpenditure}</span>
)
},
},
{
id: 'totalInvoicedAmount',
field: 'totalInvoicedAmount',
id: 'totalInvoiced',
field: 'totalInvoiced',
headerName: "Total Invoiced Amount (HKD)",
flex: 1,
renderCell: (params:any) => {
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)",
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalUnInvoicedAmount}</span>
<span>${params.row.totalUninvoiced}</span>
)
},
},
{
id: 'totalReceivedAmount',
field: 'totalReceivedAmount',
id: 'totalReceived',
field: 'totalReceived',
headerName: "Total Received Amount (HKD)",
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalReceivedAmount}</span>
<span>${params.row.totalReceived}</span>
)
},
},
@@ -322,8 +270,8 @@ const columns2 = [
flex: 1,
},
{
id: 'clientName',
field: 'clientName',
id: 'customerName',
field: 'customerName',
headerName: "Client Name",
flex: 1,
},
@@ -365,7 +313,7 @@ const columns2 = [
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalFees}</span>
<span>${params.row.totalFee}</span>
)
},
},
@@ -387,7 +335,7 @@ const columns2 = [
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalCumulativeExpenditure}</span>
<span>${params.row.cumulativeExpenditure}</span>
)
},
},
@@ -398,7 +346,7 @@ const columns2 = [
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalInvoicedAmount}</span>
<span>${params.row.totalInvoiced}</span>
)
},
},
@@ -409,7 +357,7 @@ const columns2 = [
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalUnInvoicedAmount}</span>
<span>${params.row.totalUninvoiced}</span>
)
},
},
@@ -420,7 +368,7 @@ const columns2 = [
flex: 1,
renderCell: (params:any) => {
return (
<span>${params.row.totalReceivedAmount}</span>
<span>${params.row.totalReceived}</span>
)
},
},
@@ -438,9 +386,9 @@ const columns2 = [
<Card>
<CardHeader className="text-slate-500" title="Active Project Financial Status"/>
<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>


Caricamento…
Annulla
Salva