Quellcode durchsuchen

update project potential delay report

tags/Baseline_30082024_FRONTEND_UAT
cyril.tsui vor 1 Jahr
Ursprung
Commit
bb521ee55d
5 geänderte Dateien mit 47 neuen und 3 gelöschten Zeilen
  1. +4
    -0
      src/app/api/reports/index.ts
  2. +31
    -3
      src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx
  3. +6
    -0
      src/components/SearchBox/SearchBox.tsx
  4. +3
    -0
      src/i18n/en/report.json
  5. +3
    -0
      src/i18n/zh/report.json

+ 4
- 0
src/app/api/reports/index.ts Datei anzeigen

@@ -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


+ 31
- 3
src/components/GenerateProjectPotentialDelayReport/GenerateProjectPotentialDelayReport.tsx Datei anzeigen

@@ -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<Props> = ({ 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<SearchParamNames>[] = 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<Props> = ({ 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!!)
}


+ 6
- 0
src/components/SearchBox/SearchBox.tsx Datei anzeigen

@@ -33,6 +33,9 @@ interface BaseCriterion<T extends string> {

interface TextCriterion<T extends string> extends BaseCriterion<T> {
type: "text";
textType?: React.HTMLInputTypeAttribute;
error?: boolean;
helperText?: React.ReactNode;
}

interface SelectCriterion<T extends string> extends BaseCriterion<T> {
@@ -175,9 +178,12 @@ function SearchBox<T extends string>({
{c.type === "text" && (
<TextField
label={c.label}
type={c.textType ?? "text"}
fullWidth
onChange={makeInputChangeHandler(c.paramName)}
value={inputs[c.paramName]}
error={Boolean(c.error)}
helperText={Boolean(c.error) && c.helperText}
/>
)}
{c.type === "select" && (


+ 3
- 0
src/i18n/en/report.json Datei anzeigen

@@ -1,4 +1,7 @@
{
"Number Of Days": "Number Of Days",
"Project Completion (<= %)": "Project Completion (<= %)",

"Project": "Project",
"Date Type": "Date Type"
}

+ 3
- 0
src/i18n/zh/report.json Datei anzeigen

@@ -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": "日期",


Laden…
Abbrechen
Speichern