diff --git a/src/app/api/cashflow/index.ts b/src/app/api/cashflow/index.ts index f71ba74..ed26b3a 100644 --- a/src/app/api/cashflow/index.ts +++ b/src/app/api/cashflow/index.ts @@ -11,12 +11,25 @@ export interface CashFlow { teamLeader: string; startDate: string; startDateFrom: string; - startDateTo: string; + startDateFromTo: string; targetEndDate: string; client: string; subsidiary: string; } +export interface CashFlowByMonthChartResult { + monthInvoice: string; + invoiceMonth: string; + income: number; + cumulativeIncome:number; + monthExpenditure:string; + recordMonth:string; + expenditure:number; + cumulativeExpenditure:number; + incomeList: any[]; + expenditureList: any[]; +} + export const preloadProjects = () => { fetchProjectsCashFlow(); }; @@ -24,3 +37,14 @@ export const preloadProjects = () => { export const fetchProjectsCashFlow = cache(async () => { return serverFetchJson(`${BASE_API_URL}/dashboard/searchCashFlowProject`); }); + +export const fetchProjectsCashFlowMonthlyChart = cache(async (projectIdList: number[], year: number) => { + if (projectIdList.length !== 0) { + const queryParams = new URLSearchParams(); + queryParams.append('projectIdList', projectIdList.join(',')); + return serverFetchJson(`${BASE_API_URL}/dashboard/searchCashFlowByMonth?${queryParams.toString()}&year=${year}`); + } else { + return []; + } + +}); diff --git a/src/components/ProjectCashFlow/ProjectCashFlow.tsx b/src/components/ProjectCashFlow/ProjectCashFlow.tsx index 4a78c62..14b40a0 100644 --- a/src/components/ProjectCashFlow/ProjectCashFlow.tsx +++ b/src/components/ProjectCashFlow/ProjectCashFlow.tsx @@ -19,9 +19,10 @@ import SearchBox, { Criterion } from "../SearchBox"; import ProgressByClientSearch from "@/components/ProgressByClientSearch"; import { Suspense } from "react"; import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; -import { fetchProjectsCashFlow} from "@/app/api/cashflow"; +import { fetchProjectsCashFlow,fetchProjectsCashFlowMonthlyChart} from "@/app/api/cashflow"; import { Input, Label } from "reactstrap"; import { CashFlow } from "@/app/api/cashflow"; +import dayjs from 'dayjs'; interface Props { projects: CashFlow[]; @@ -34,19 +35,78 @@ const ProjectCashFlow: React.FC = () => { const todayDate = new Date(); const [selectionModel, setSelectionModel]: any[] = React.useState([]); const [projectData, setProjectData]: any[] = React.useState([]); + const [filteredResult, setFilteredResult]:any[] = useState([]); + const [selectedProjectIdList, setSelectedProjectIdList]: any[] = React.useState([]); + const [monthlyIncomeList, setMonthlyIncomeList]: any[] = React.useState([]); + const [monthlyCumulativeIncomeList, setMonthlyCumulativeIncomeList]: any[] = React.useState([]); + const [monthlyExpenditureList, setMonthlyExpenditureList]: any[] = React.useState([]); + const [monthlyCumulativeExpenditureList, setMonthlyCumulativeExpenditureList]: any[] = React.useState([]); + const [monthlyChartLeftMax, setMonthlyChartLeftMax]: any[] = React.useState(0); + const [monthlyChartRightMax, setMonthlyChartRightMax]: any[] = React.useState(0); const [cashFlowYear, setCashFlowYear]: any[] = React.useState( todayDate.getFullYear(), ); const [anticipateCashFlowYear, setAnticipateCashFlowYear]: any[] = React.useState( todayDate.getFullYear(), ); + + const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { + const selectedRowsData = projectData.filter((row: any) => + newSelectionModel.includes(row.id), + ); + const projectIdList = [] + for (var i=0; i { const cashFlowProject = await fetchProjectsCashFlow(); + console.log(cashFlowProject) setProjectData(cashFlowProject) + setFilteredResult(cashFlowProject) + } + const fetchChartData = async () => { + const cashFlowMonthlyChartData = await fetchProjectsCashFlowMonthlyChart(selectedProjectIdList,cashFlowYear); + console.log(cashFlowMonthlyChartData) + const monthlyIncome = [] + const cumulativeIncome = [] + const monthlyExpenditure = [] + const cumulativeExpenditure = [] + var leftMax = 0 + var rightMax = 0 + if (cashFlowMonthlyChartData.length !== 0) { + for (var i = 0; i < cashFlowMonthlyChartData[0].incomeList.length; i++) { + if (leftMax < cashFlowMonthlyChartData[0].incomeList[i].income || leftMax < cashFlowMonthlyChartData[0].expenditureList[i].expenditure){ + leftMax = Math.max(cashFlowMonthlyChartData[0].incomeList[i].income,cashFlowMonthlyChartData[0].expenditureList[i].expenditure) + } + monthlyIncome.push(cashFlowMonthlyChartData[0].incomeList[i].income) + cumulativeIncome.push(cashFlowMonthlyChartData[0].incomeList[i].cumulativeIncome) + } + for (var i = 0; i < cashFlowMonthlyChartData[0].expenditureList.length; i++) { + if (rightMax < cashFlowMonthlyChartData[0].incomeList[i].income || rightMax < cashFlowMonthlyChartData[0].expenditureList[i].expenditure){ + rightMax = Math.max(cashFlowMonthlyChartData[0].incomeList[i].income,cashFlowMonthlyChartData[0].expenditureList[i].expenditure) + } + monthlyExpenditure.push(cashFlowMonthlyChartData[0].expenditureList[i].expenditure) + cumulativeExpenditure.push(cashFlowMonthlyChartData[0].expenditureList[i].cumulativeExpenditure) + } + setMonthlyIncomeList(monthlyIncome) + setMonthlyCumulativeIncomeList(cumulativeIncome) + setMonthlyExpenditureList(monthlyExpenditure) + setMonthlyCumulativeExpenditureList(cumulativeExpenditure) + setMonthlyChartLeftMax(leftMax) + setMonthlyChartRightMax(rightMax) + } + } useEffect(() => { fetchData() }, []); + + useEffect(() => { + fetchChartData() + }, [cashFlowYear,selectedProjectIdList]); const columns = [ { id: "projectCode", @@ -170,7 +230,7 @@ const ProjectCashFlow: React.FC = () => { text: "Monthly Income and Expenditure(HKD)", }, min: 0, - max: 350000, + max: monthlyChartLeftMax, tickAmount: 5, labels: { formatter: function (val) { @@ -185,7 +245,7 @@ const ProjectCashFlow: React.FC = () => { text: "Monthly Expenditure (HKD)", }, min: 0, - max: 350000, + max: monthlyChartLeftMax, tickAmount: 5, }, { @@ -195,7 +255,7 @@ const ProjectCashFlow: React.FC = () => { text: "Cumulative Income and Expenditure(HKD)", }, min: 0, - max: 850000, + max: monthlyChartRightMax, tickAmount: 5, labels: { formatter: function (val) { @@ -211,7 +271,7 @@ const ProjectCashFlow: React.FC = () => { text: "Cumulative Expenditure (HKD)", }, min: 0, - max: 850000, + max: monthlyChartRightMax, tickAmount: 5, }, ], @@ -224,34 +284,25 @@ const ProjectCashFlow: React.FC = () => { name: "Monthly_Income", type: "column", color: "#ffde91", - data: [0, 110000, 0, 0, 185000, 0, 0, 189000, 0, 0, 300000, 0], + data: monthlyIncomeList, }, { name: "Monthly_Expenditure", type: "column", color: "#82b59a", - data: [ - 0, 160000, 120000, 120000, 55000, 55000, 55000, 55000, 55000, 70000, - 55000, 55000, - ], + data: monthlyExpenditureList, }, { name: "Cumulative_Income", type: "line", color: "#EE6D7A", - data: [ - 0, 100000, 100000, 100000, 300000, 300000, 300000, 500000, 500000, - 500000, 800000, 800000, - ], + data: monthlyCumulativeIncomeList, }, { name: "Cumulative_Expenditure", type: "line", color: "#7cd3f2", - data: [ - 0, 198000, 240000, 400000, 410000, 430000, 510000, 580000, 600000, - 710000, 730000, 790000, - ], + data: monthlyCumulativeExpenditureList, }, ], }; @@ -295,7 +346,7 @@ const ProjectCashFlow: React.FC = () => { text: "Anticipate Monthly Income and Expenditure(HKD)", }, min: 0, - max: 350000, + max: monthlyChartLeftMax, tickAmount: 5, labels: { formatter: function (val) { @@ -310,7 +361,7 @@ const ProjectCashFlow: React.FC = () => { text: "Monthly Expenditure (HKD)", }, min: 0, - max: 350000, + max: monthlyChartLeftMax, tickAmount: 5, }, { @@ -320,7 +371,7 @@ const ProjectCashFlow: React.FC = () => { text: "Cumulative Income and Expenditure(HKD)", }, min: 0, - max: 850000, + max: monthlyChartRightMax, tickAmount: 5, labels: { formatter: function (val) { @@ -336,7 +387,7 @@ const ProjectCashFlow: React.FC = () => { text: "Cumulative Expenditure (HKD)", }, min: 0, - max: 850000, + max: monthlyChartRightMax, tickAmount: 5, }, ], @@ -548,12 +599,6 @@ const ProjectCashFlow: React.FC = () => { }, ]; const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = projectData.filter((row: any) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - }; const searchCriteria: Criterion[] = useMemo( () => [ @@ -569,6 +614,19 @@ const ProjectCashFlow: React.FC = () => { [t], ); + function isDateInRange(dateToCheck: string, startDate: string, endDate: string): boolean { + console.log(startDate) + console.log(endDate) + if (!startDate || !endDate) { + return false; + } + const dateToCheckObj = new Date(dateToCheck); + const startDateObj = new Date(startDate); + const endDateObj = new Date(endDate); + console.log(dateToCheckObj) + return dateToCheckObj >= startDateObj && dateToCheckObj <= endDateObj; + } + return ( <> {/* }> @@ -577,11 +635,21 @@ const ProjectCashFlow: React.FC = () => { { - console.log(query); + console.log(query) + setFilteredResult( + projectData.filter( + (cp:any) => + cp.projectCode.toLowerCase().includes(query.projectCode.toLowerCase()) && + cp.projectName.toLowerCase().includes(query.projectName.toLowerCase()) && + (query.startDateFrom || query.startDateFromTo + ? isDateInRange(cp.startDate, query.startDateFrom, query.startDateFromTo) + : true) + ), + ); }} />