From 1b12a18e3a9e15e81d279a7803d1a72e3a850de8 Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Wed, 22 May 2024 16:25:41 +0800 Subject: [PATCH] Add PandL Report navigation --- .../analytics/ProjectPandLReport/page.tsx | 30 +++++++++ .../GenerateProjectPandLReport.tsx | 63 +++++++++++++++++++ .../GenerateProjectPandLReportLoading.tsx | 38 +++++++++++ .../GenerateProjectPandLReportWrapper.tsx | 18 ++++++ .../GenerateProjectPandLReport/index.ts | 1 + .../NavigationContent/NavigationContent.tsx | 2 +- 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/app/(main)/analytics/ProjectPandLReport/page.tsx create mode 100644 src/components/GenerateProjectPandLReport/GenerateProjectPandLReport.tsx create mode 100644 src/components/GenerateProjectPandLReport/GenerateProjectPandLReportLoading.tsx create mode 100644 src/components/GenerateProjectPandLReport/GenerateProjectPandLReportWrapper.tsx create mode 100644 src/components/GenerateProjectPandLReport/index.ts diff --git a/src/app/(main)/analytics/ProjectPandLReport/page.tsx b/src/app/(main)/analytics/ProjectPandLReport/page.tsx new file mode 100644 index 0000000..156cc3d --- /dev/null +++ b/src/app/(main)/analytics/ProjectPandLReport/page.tsx @@ -0,0 +1,30 @@ +import { Metadata } from "next"; +import { Suspense } from "react"; +import { I18nProvider, getServerI18n } from "@/i18n"; +import { fetchProjects } from "@/app/api/projects"; +import GenerateProjectPandLReport from "@/components/GenerateProjectPandLReport"; +import { Typography } from "@mui/material"; + +export const metadata: Metadata = { + title: "Project Cash Flow Report", +}; + +const ProjectPandLReport: React.FC = async () => { + const { t } = await getServerI18n("reports"); + fetchProjects(); + + return ( + <> + + {t("Project P&L Report")} + + + }> + + + + + ); +}; + +export default ProjectPandLReport; diff --git a/src/components/GenerateProjectPandLReport/GenerateProjectPandLReport.tsx b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReport.tsx new file mode 100644 index 0000000..2fb5d63 --- /dev/null +++ b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReport.tsx @@ -0,0 +1,63 @@ +"use client"; + +import React, { useMemo } from "react"; +import SearchBox, { Criterion } from "../SearchBox"; +import { useTranslation } from "react-i18next"; +import { ProjectResult } from "@/app/api/projects"; +import { ProjectPandLReportFilter } from "@/app/api/reports"; +import { fetchProjectPandLReport } from "@/app/api/reports/actions"; +import { downloadFile } from "@/app/utils/commonUtil"; +import { dateTypeCombo } from "@/app/utils/comboUtil"; +import { FormHelperText } from "@mui/material"; +import { errorDialog, errorDialogWithContent } from "../Swal/CustomAlerts"; + +interface Props { + projects: ProjectResult[]; +} + +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const GenerateProjectPandLReport: React.FC = ({ projects }) => { + const { t } = useTranslation("report"); + const projectCombo = projects.map(project => `${project.code} - ${project.name}`) + + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: t("Project *"), paramName: "project", type: "select", options: projectCombo, needAll: false}, + { label: t("Start Month *"), label2: t("End Month *"), paramName: "startMonth", type: "dateRange", needMonth: true }, + + ], + [t], + ); + + return ( + <> + { + + if (query.project.length > 0 && query.project.toLocaleLowerCase() !== "all") { + const projectIndex = projectCombo.findIndex(project => project === query.project) + console.log(projects[projectIndex].id, query.startMonth, query.startMonthTo) + if(projects[projectIndex].id != null && query.startMonth != "" && query.startMonthTo != undefined){ + const response = await fetchProjectPandLReport({ projectId: projects[projectIndex].id, startMonth: query.startMonth, endMonth: query.startMonthTo }) + if (response) { + downloadFile(new Uint8Array(response.blobValue), response.filename!!) + } + }else{ + errorDialogWithContent(t("Download Fail"), + t(`Please check the required field`), t) + .then(() => { + window.location.reload() + }) + } + } + }} + formType={"download"} + /> + + ); +}; + +export default GenerateProjectPandLReport; \ No newline at end of file diff --git a/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportLoading.tsx b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportLoading.tsx new file mode 100644 index 0000000..04826a4 --- /dev/null +++ b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportLoading.tsx @@ -0,0 +1,38 @@ +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Skeleton from "@mui/material/Skeleton"; +import Stack from "@mui/material/Stack"; +import React from "react"; + +// Can make this nicer +export const GenerateProjectPandLReportLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + ); +}; + +export default GenerateProjectPandLReportLoading; \ No newline at end of file diff --git a/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportWrapper.tsx b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportWrapper.tsx new file mode 100644 index 0000000..00ca669 --- /dev/null +++ b/src/components/GenerateProjectPandLReport/GenerateProjectPandLReportWrapper.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import GenerateProjectPandLReportLoading from "./GenerateProjectPandLReportLoading"; +import { fetchProjects } from "@/app/api/projects"; +import GenerateProjectPandLReport from "./GenerateProjectPandLReport"; + +interface SubComponents { + Loading: typeof GenerateProjectPandLReportLoading; +} + +const GenerateProjectPandLReportWrapper: React.FC & SubComponents = async () => { + const projects = await fetchProjects(); + + return ; +}; + +GenerateProjectPandLReportWrapper.Loading = GenerateProjectPandLReportLoading; + +export default GenerateProjectPandLReportWrapper; \ No newline at end of file diff --git a/src/components/GenerateProjectPandLReport/index.ts b/src/components/GenerateProjectPandLReport/index.ts new file mode 100644 index 0000000..b56feba --- /dev/null +++ b/src/components/GenerateProjectPandLReport/index.ts @@ -0,0 +1 @@ +export { default } from "./GenerateProjectPandLReportWrapper"; \ No newline at end of file diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index a50b3a0..0ed436c 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -175,7 +175,7 @@ const NavigationContent: React.FC = ({ abilities }) => { { icon: , label: "Project P&L Report", - path: "/analytics/ProjectPLReport", + path: "/analytics/ProjectPandLReport", }, { icon: ,