From bb521ee55dbed3b50d76234f9a1f4cd2803382fd Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Mon, 27 May 2024 16:21:19 +0800 Subject: [PATCH] update project potential delay report --- src/app/api/reports/index.ts | 4 +++ .../GenerateProjectPotentialDelayReport.tsx | 34 +++++++++++++++++-- src/components/SearchBox/SearchBox.tsx | 6 ++++ src/i18n/en/report.json | 3 ++ src/i18n/zh/report.json | 3 ++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/app/api/reports/index.ts b/src/app/api/reports/index.ts index c850dc0..555adbd 100644 --- a/src/app/api/reports/index.ts +++ b/src/app/api/reports/index.ts @@ -32,11 +32,15 @@ export interface ProjectCashFlowReportRequest { export interface ProjectPotentialDelayReportFilter { team: string[]; client: string[]; + numberOfDays: number; + projectCompletion: number; } export interface ProjectPotentialDelayReportRequest { teamId: number | "All"; clientId: number | "All"; + numberOfDays: number; + projectCompletion: number; } // - Monthly Work Hours Report diff --git a/src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx b/src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx index 5d0d34f..faaa66f 100644 --- a/src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx +++ b/src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx @@ -4,7 +4,7 @@ import React, { useMemo } from "react"; import SearchBox, { Criterion } from "../SearchBox"; import { useTranslation } from "react-i18next"; import { ProjectPotentialDelayReportFilter } from "@/app/api/reports"; -import { fetchProjectCashFlowReport, fetchProjectPotentialDelayReport } from "@/app/api/reports/actions"; +import { fetchProjectPotentialDelayReport } from "@/app/api/reports/actions"; import { downloadFile } from "@/app/utils/commonUtil"; import { TeamResult } from "@/app/api/team"; import { Customer } from "@/app/api/customer"; @@ -21,13 +21,19 @@ const GenerateProjectPotentialDelayReport: React.FC = ({ teams, clients } const { t } = useTranslation("report"); const teamCombo = teams.map(team => `${team.code} - ${team.name}`) const clientCombo = clients.map(client => `${client.code} - ${client.name}`) + const [errors, setErrors] = React.useState({ + numberOfDays: false, + projectCompletion: false, + }) const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Team"), paramName: "team", type: "select", options: teamCombo }, { label: t("Client"), paramName: "client", type: "select", options: clientCombo }, + { label: t("Number Of Days"), paramName: "numberOfDays", type: "text", textType: "number", error: errors.numberOfDays, helperText: t("Can not be null and decimal, and should be >= 0") }, + { label: t("Project Completion (<= %)"), paramName: "projectCompletion", type: "text", textType: "number", error: errors.projectCompletion, helperText: t("Can not be null and decimal, and should be in range of 0 - 100") }, ], - [t], + [t, errors], ); return ( @@ -36,10 +42,32 @@ const GenerateProjectPotentialDelayReport: React.FC = ({ teams, clients } criteria={searchCriteria} onSearch={async (query) => { + let hasError = false + if (query.numberOfDays.length === 0 || !Number.isInteger(parseFloat(query.numberOfDays)) || parseInt(query.numberOfDays) < 0) { + setErrors((prev) => ({...prev, numberOfDays: true})) + hasError = true + } else { + setErrors((prev) => ({...prev, numberOfDays: false})) + } + + if (query.projectCompletion.length === 0 || !Number.isInteger(parseFloat(query.projectCompletion)) || parseInt(query.projectCompletion) < 0 || parseInt(query.projectCompletion) > 100) { + setErrors((prev) => ({...prev, projectCompletion: true})) + hasError = true + } else { + setErrors((prev) => ({...prev, projectCompletion: false})) + } + + if (hasError) return false + const teamIndex = teamCombo.findIndex(team => team === query.team) const clientIndex = clientCombo.findIndex(client => client === query.client) - const response = await fetchProjectPotentialDelayReport({ teamId: teams[teamIndex]?.id ?? "All", clientId: clients[clientIndex]?.id ?? "All" }) + const response = await fetchProjectPotentialDelayReport({ + teamId: teams[teamIndex]?.id ?? "All", + clientId: clients[clientIndex]?.id ?? "All", + numberOfDays: parseInt(query.numberOfDays), + projectCompletion: parseInt(query.projectCompletion) + }) if (response) { downloadFile(new Uint8Array(response.blobValue), response.filename!!) } diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index 84aa8a4..e3cf5e8 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -33,6 +33,9 @@ interface BaseCriterion { interface TextCriterion extends BaseCriterion { type: "text"; + textType?: React.HTMLInputTypeAttribute; + error?: boolean; + helperText?: React.ReactNode; } interface SelectCriterion extends BaseCriterion { @@ -175,9 +178,12 @@ function SearchBox({ {c.type === "text" && ( )} {c.type === "select" && ( diff --git a/src/i18n/en/report.json b/src/i18n/en/report.json index 541c75d..df2a3ae 100644 --- a/src/i18n/en/report.json +++ b/src/i18n/en/report.json @@ -1,4 +1,7 @@ { + "Number Of Days": "Number Of Days", + "Project Completion (<= %)": "Project Completion (<= %)", + "Project": "Project", "Date Type": "Date Type" } \ No newline at end of file diff --git a/src/i18n/zh/report.json b/src/i18n/zh/report.json index d15eec9..d85d97b 100644 --- a/src/i18n/zh/report.json +++ b/src/i18n/zh/report.json @@ -2,6 +2,9 @@ "Staff Monthly Work Hours Analysis Report": "Staff Monthly Work Hours Analysis Report", "Project Resource Overconsumption Report": "Project Resource Overconsumption Report", + "Number Of Days": "天數", + "Project Completion (<= %)": "項目完成度 (<= %)", + "Project": "項目", "Date Type": "日期類型", "Date": "日期",