From 4df034fbb0e1799be8687c20bc5ac7b3c31da66a Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Tue, 23 Apr 2024 14:17:18 +0800 Subject: [PATCH 1/6] reset date range & update search results --- src/components/SearchBox/SearchBox.tsx | 2 ++ src/components/SearchResults/SearchResults.tsx | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index fe058f7..13b03ee 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -154,6 +154,7 @@ function SearchBox({ ({ diff --git a/src/components/SearchResults/SearchResults.tsx b/src/components/SearchResults/SearchResults.tsx index 4c82280..bfecd36 100644 --- a/src/components/SearchResults/SearchResults.tsx +++ b/src/components/SearchResults/SearchResults.tsx @@ -11,7 +11,7 @@ import TablePagination, { TablePaginationProps, } from "@mui/material/TablePagination"; import TableRow from "@mui/material/TableRow"; -import IconButton from "@mui/material/IconButton"; +import IconButton, { IconButtonOwnProps, IconButtonPropsColorOverrides } from "@mui/material/IconButton"; export interface ResultWithId { id: string | number; @@ -20,6 +20,7 @@ export interface ResultWithId { interface BaseColumn { name: keyof T; label: string; + color?: IconButtonOwnProps["color"]; } interface ColumnWithAction extends BaseColumn { @@ -91,7 +92,7 @@ function SearchResults({ {isActionColumn(column) ? ( column.onClick(item)} > {column.buttonIcon} From 48541ba33b635abd9f3481aa8a0641a2e27e2fa4 Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Tue, 23 Apr 2024 14:36:04 +0800 Subject: [PATCH 2/6] add report ar03 --- .../temp/AR03_Resource Overconsumption.xlsx | Bin 0 -> 12888 bytes .../ResourceOverconsumptionReport/page.tsx | 24 ++ src/app/api/report3/index.ts | 42 +++ .../ResourceOverconsumptionReport.tsx | 17 + .../ResourceOverconsumptionReport/index.ts | 2 + .../ResourceOverconsumptionReportGen.tsx | 45 +++ ...esourceOverconsumptionReportGenLoading.tsx | 41 +++ ...esourceOverconsumptionReportGenWrapper.tsx | 19 ++ .../ResourceOverconsumptionReportGen/index.ts | 2 + .../ReportSearchBox3/SearchBox3.tsx | 300 ++++++++++++++++++ src/components/ReportSearchBox3/index.ts | 3 + 11 files changed, 495 insertions(+) create mode 100644 public/temp/AR03_Resource Overconsumption.xlsx create mode 100644 src/app/(main)/analytics/ResourceOverconsumptionReport/page.tsx create mode 100644 src/app/api/report3/index.ts create mode 100644 src/components/Report/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx create mode 100644 src/components/Report/ResourceOverconsumptionReport/index.ts create mode 100644 src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx create mode 100644 src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenLoading.tsx create mode 100644 src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenWrapper.tsx create mode 100644 src/components/Report/ResourceOverconsumptionReportGen/index.ts create mode 100644 src/components/ReportSearchBox3/SearchBox3.tsx create mode 100644 src/components/ReportSearchBox3/index.ts diff --git a/public/temp/AR03_Resource Overconsumption.xlsx b/public/temp/AR03_Resource Overconsumption.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f021fbc8c3cd8889fb1108c97c7d9d9089bdcdc9 GIT binary patch literal 12888 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 { + return ( + + + Resource Overconsumption Report + + {/* }> + + */} + + + ); +}; +export default ResourceOverconsumptionReport; diff --git a/src/app/api/report3/index.ts b/src/app/api/report3/index.ts new file mode 100644 index 0000000..b2c8751 --- /dev/null +++ b/src/app/api/report3/index.ts @@ -0,0 +1,42 @@ +//src\app\api\report\index.ts +import { cache } from "react"; + +export interface ResourceOverconsumption { + id: number; + projectCode: string; + projectName: string; + team: string; + teamLeader: string; + startDate: string; + startDateFrom: string; + startDateTo: string; + targetEndDate: string; + client: string; + subsidiary: string; + status: string; +} + +export const preloadProjects = () => { + fetchProjectsResourceOverconsumption(); +}; + +export const fetchProjectsResourceOverconsumption = cache(async () => { + return mockProjects; +}); + +const mockProjects: ResourceOverconsumption[] = [ + { + id: 1, + projectCode: "CUST-001", + projectName: "Client A", + team: "N/A", + teamLeader: "N/A", + startDate: "1/2/2024", + startDateFrom: "1/2/2024", + startDateTo: "1/2/2024", + targetEndDate: "30/3/2024", + client: "ss", + subsidiary: "sus", + status: "1", + }, +]; diff --git a/src/components/Report/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx b/src/components/Report/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx new file mode 100644 index 0000000..345b2f2 --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx @@ -0,0 +1,17 @@ +//src\components\DelayReport\DelayReport.tsx +"use client"; +import * as React from "react"; +import "../../../app/global.css"; +import { Suspense } from "react"; +import ResourceOverconsumptionReportGen from "@/components/Report/ResourceOverconsumptionReportGen"; + +const ResourceOverconsumptionReport: React.FC = () => { + + return ( + }> + + + ); +}; + +export default ResourceOverconsumptionReport; \ No newline at end of file diff --git a/src/components/Report/ResourceOverconsumptionReport/index.ts b/src/components/Report/ResourceOverconsumptionReport/index.ts new file mode 100644 index 0000000..ce20324 --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReport/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReport\index.ts +export { default } from "./ResourceOverconsumptionReport"; diff --git a/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx new file mode 100644 index 0000000..9d527a3 --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx @@ -0,0 +1,45 @@ +//src\components\LateStartReportGen\LateStartReportGen.tsx +"use client"; +import React, { useMemo, useState } from "react"; +import SearchBox, { Criterion } from "../../ReportSearchBox3"; +import { useTranslation } from "react-i18next"; +import { ResourceOverconsumption } from "@/app/api/report3"; + +interface Props { + projects: ResourceOverconsumption[]; +} +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const ProgressByClientSearch: React.FC = ({ projects }) => { + const { t } = useTranslation("projects"); + + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: "Team", paramName: "team", type: "text" }, + { label: "Client", paramName: "client", type: "text" }, + { label: "Status", paramName: "status", type: "select", options: ["Overconsumption", "Potential Overconsumption"] }, + // { + // label: "Status", + // label2: "Remained Date To", + // paramName: "targetEndDate", + // type: "dateRange", + // }, + ], + [t], + ); + + return ( + <> + { + console.log(query); + }} + /> + {/* */} + + ); +}; + +export default ProgressByClientSearch; diff --git a/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenLoading.tsx b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenLoading.tsx new file mode 100644 index 0000000..9ae7417 --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenLoading.tsx @@ -0,0 +1,41 @@ +//src\components\LateStartReportGen\LateStartReportGenLoading.tsx +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 ResourceOvercomsumptionReportGenLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ResourceOvercomsumptionReportGenLoading; diff --git a/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenWrapper.tsx b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenWrapper.tsx new file mode 100644 index 0000000..a93f64b --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGenWrapper.tsx @@ -0,0 +1,19 @@ +//src\components\LateStartReportGen\LateStartReportGenWrapper.tsx +import { fetchProjectsResourceOverconsumption } from "@/app/api/report3"; +import React from "react"; +import ResourceOvercomsumptionReportGen from "./ResourceOverconsumptionReportGen"; +import ResourceOvercomsumptionReportGenLoading from "./ResourceOverconsumptionReportGenLoading"; + +interface SubComponents { + Loading: typeof ResourceOvercomsumptionReportGenLoading; +} + +const ResourceOvercomsumptionReportGenWrapper: React.FC & SubComponents = async () => { + const clentprojects = await fetchProjectsResourceOverconsumption(); + + return ; +}; + +ResourceOvercomsumptionReportGenWrapper.Loading = ResourceOvercomsumptionReportGenLoading; + +export default ResourceOvercomsumptionReportGenWrapper; \ No newline at end of file diff --git a/src/components/Report/ResourceOverconsumptionReportGen/index.ts b/src/components/Report/ResourceOverconsumptionReportGen/index.ts new file mode 100644 index 0000000..82fb633 --- /dev/null +++ b/src/components/Report/ResourceOverconsumptionReportGen/index.ts @@ -0,0 +1,2 @@ +//src\components\DelayReportGen\index.ts +export { default } from "./ResourceOverconsumptionReportGenWrapper"; diff --git a/src/components/ReportSearchBox3/SearchBox3.tsx b/src/components/ReportSearchBox3/SearchBox3.tsx new file mode 100644 index 0000000..b01032b --- /dev/null +++ b/src/components/ReportSearchBox3/SearchBox3.tsx @@ -0,0 +1,300 @@ +//src\components\ReportSearchBox3\SearchBox3.tsx +"use client"; + +import Grid from "@mui/material/Grid"; +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Typography from "@mui/material/Typography"; +import React, { useCallback, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import TextField from "@mui/material/TextField"; +import FormControl from "@mui/material/FormControl"; +import InputLabel from "@mui/material/InputLabel"; +import Select, { SelectChangeEvent } from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; +import CardActions from "@mui/material/CardActions"; +import Button from "@mui/material/Button"; +import RestartAlt from "@mui/icons-material/RestartAlt"; +import Search from "@mui/icons-material/Search"; +import dayjs from "dayjs"; +import "dayjs/locale/zh-hk"; +import { DatePicker } from "@mui/x-date-pickers/DatePicker"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { Box } from "@mui/material"; +import * as XLSX from 'xlsx-js-style'; +//import { DownloadReportButton } from '../LateStartReportGen/DownloadReportButton'; + +interface BaseCriterion { + label: string; + label2?: string; + paramName: T; + paramName2?: T; +} + +interface TextCriterion extends BaseCriterion { + type: "text"; +} + +interface SelectCriterion extends BaseCriterion { + type: "select"; + options: string[]; +} + +interface DateRangeCriterion extends BaseCriterion { + type: "dateRange"; +} + +export type Criterion = + | TextCriterion + | SelectCriterion + | DateRangeCriterion; + +interface Props { + criteria: Criterion[]; + onSearch: (inputs: Record) => void; + onReset?: () => void; +} + +function SearchBox({ + criteria, + onSearch, + onReset, +}: Props) { + const { t } = useTranslation("common"); + const defaultInputs = useMemo( + () => + criteria.reduce>( + (acc, c) => { + return { ...acc, [c.paramName]: c.type === "select" ? "All" : "" }; + }, + {} as Record, + ), + [criteria], + ); + const [inputs, setInputs] = useState(defaultInputs); + + const makeInputChangeHandler = useCallback( + (paramName: T): React.ChangeEventHandler => { + return (e) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, + [], + ); + + const makeSelectChangeHandler = useCallback((paramName: T) => { + return (e: SelectChangeEvent) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, []); + + const makeDateChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ ...i, [paramName]: dayjs(e).format("YYYY-MM-DD") })); + }; + }, []); + + const makeDateToChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ + ...i, + [paramName + "To"]: dayjs(e).format("YYYY-MM-DD"), + })); + }; + }, []); + + const handleReset = () => { + setInputs(defaultInputs); + onReset?.(); + }; + + const handleSearch = () => { + onSearch(inputs); + + }; + + const handleDownload = async () => { + //setIsLoading(true); + + try { + const response = await fetch('/temp/AR03_Resource Overconsumption.xlsx', { + headers: { + 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + }, + }); + if (!response.ok) throw new Error('Network response was not ok.'); + + const data = await response.blob(); + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target && e.target.result) { + const ab = e.target.result as ArrayBuffer; + const workbook = XLSX.read(ab, { type: 'array' }); + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + + // Add the current date to cell C2 + const cellAddress = 'C2'; + const date = new Date().toISOString().split('T')[0]; // Format YYYY-MM-DD + const formattedDate = date.replace(/-/g, '/'); // Change format to YYYY/MM/DD + XLSX.utils.sheet_add_aoa(worksheet, [[formattedDate]], { origin: cellAddress }); + + // Calculate the maximum length of content in each column and set column width + const colWidths: number[] = []; + + const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: "", blankrows: true }) as (string | number)[][]; + jsonData.forEach((row: (string | number)[]) => { + row.forEach((cell: string | number, index: number) => { + const valueLength = cell.toString().length; + colWidths[index] = Math.max(colWidths[index] || 0, valueLength); + }); + }); + + // Apply calculated widths to each column, skipping column A + worksheet['!cols'] = colWidths.map((width, index) => { + if (index === 0) { + return { wch: 8 }; // Set default or specific width for column A if needed + } + return { wch: width + 2 }; // Add padding to width + }); + + // Style for cell A1: Font size 16 and bold + if (worksheet['A1']) { + worksheet['A1'].s = { + font: { + bold: true, + sz: 16, // Font size 16 + //name: 'Times New Roman' // Specify font + } + }; + } + + // Apply styles from A2 to A4 (bold) + ['A2', 'A3', 'A4'].forEach(cell => { + if (worksheet[cell]) { + worksheet[cell].s = { font: { bold: true } }; + } + }); + + // Formatting from A6 to L6 + // Apply styles from A6 to L6 (bold, bottom border, center alignment) + for (let col = 0; col < 12; col++) { // Columns A to K + const cellRef = XLSX.utils.encode_col(col) + '6'; + if (worksheet[cellRef]) { + worksheet[cellRef].s = { + font: { bold: true }, + alignment: { horizontal: 'center' }, + border: { + bottom: { style: 'thin', color: { auto: 1 } } + } + }; + } + } + + // Format filename with date + const today = new Date().toISOString().split('T')[0].replace(/-/g, '_'); // Get current date and format as YYYY_MM_DD + const filename = `AR03_Resource_Overconsumption_${today}.xlsx`; // Append formatted date to the filename + + // Convert workbook back to XLSX file + XLSX.writeFile(workbook, filename); + } else { + throw new Error('Failed to load file'); + } + }; + reader.readAsArrayBuffer(data); + } catch (error) { + console.error('Error downloading the file: ', error); + } + + //setIsLoading(false); + }; + return ( + + + {t("Search Criteria")} + + {criteria.map((c) => { + return ( + + {c.type === "text" && ( + + )} + {c.type === "select" && ( + + {c.label} + + + )} + {c.type === "dateRange" && ( + + + + + + + {"-"} + + + + + + + )} + + ); + })} + + + + + + + + ); +} + +export default SearchBox; diff --git a/src/components/ReportSearchBox3/index.ts b/src/components/ReportSearchBox3/index.ts new file mode 100644 index 0000000..d481fbd --- /dev/null +++ b/src/components/ReportSearchBox3/index.ts @@ -0,0 +1,3 @@ +//src\components\SearchBox\index.ts +export { default } from "./SearchBox3"; +export type { Criterion } from "./SearchBox3"; From c046a15dea0438e53cbc59ff7fa11fc41987968e Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Tue, 23 Apr 2024 14:45:11 +0800 Subject: [PATCH 3/6] reset date range --- src/components/ReportSearchBox/SearchBox.tsx | 6 ++++-- src/components/ReportSearchBox2/SearchBox2.tsx | 6 ++++-- src/components/ReportSearchBox3/SearchBox3.tsx | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/components/ReportSearchBox/SearchBox.tsx b/src/components/ReportSearchBox/SearchBox.tsx index 6ca34f1..c629ad4 100644 --- a/src/components/ReportSearchBox/SearchBox.tsx +++ b/src/components/ReportSearchBox/SearchBox.tsx @@ -253,6 +253,7 @@ function SearchBox({ ({ @@ -287,9 +289,9 @@ function SearchBox({ diff --git a/src/components/ReportSearchBox2/SearchBox2.tsx b/src/components/ReportSearchBox2/SearchBox2.tsx index 16b72df..37d65ba 100644 --- a/src/components/ReportSearchBox2/SearchBox2.tsx +++ b/src/components/ReportSearchBox2/SearchBox2.tsx @@ -253,6 +253,7 @@ function SearchBox({ ({ @@ -287,9 +289,9 @@ function SearchBox({ diff --git a/src/components/ReportSearchBox3/SearchBox3.tsx b/src/components/ReportSearchBox3/SearchBox3.tsx index b01032b..8bf2fea 100644 --- a/src/components/ReportSearchBox3/SearchBox3.tsx +++ b/src/components/ReportSearchBox3/SearchBox3.tsx @@ -253,6 +253,7 @@ function SearchBox({ ({ @@ -287,9 +289,9 @@ function SearchBox({ From 50366617436ca3eff57653c431b4fd2f8478cde9 Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Tue, 23 Apr 2024 16:31:05 +0800 Subject: [PATCH 4/6] bug fix --- public/temp/AR01_Late Start Report.xlsx | Bin 12958 -> 12554 bytes public/temp/AR02_Delay Report.xlsx | Bin 13358 -> 13279 bytes .../temp/AR03_Resource Overconsumption.xlsx | Bin 12888 -> 12894 bytes .../NavigationContent/NavigationContent.tsx | 4 ++-- .../Report/DelayReportGen/DelayReportGen.tsx | 4 ++-- .../LateStartReportGen/LateStartReportGen.tsx | 17 ++++++++++++++--- .../ResourceOverconsumptionReportGen.tsx | 4 ++-- 7 files changed, 20 insertions(+), 9 deletions(-) diff --git a/public/temp/AR01_Late Start Report.xlsx b/public/temp/AR01_Late Start Report.xlsx index 24da97fdaf261701fcfd8b1110216245b4c543b3..f93a8e842ea0da6248e63191919f85f9df773f62 100644 GIT binary patch delta 3029 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 delta 2635 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 Z;4u{exRdrVJ^?+GH8LXx94`O>008GTP_qC4 diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index db5b544..53dbb5c 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -103,8 +103,8 @@ const navigationItems: NavigationItem[] = [ {icon: , label:"Delay Report", path: "/analytics/DelayReport"}, {icon: , label:"Resource Overconsumption Report", path: "/analytics/ResourceOverconsumptionReport"}, {icon: , label:"Cost and Expense Report", path: "/analytics/CostandExpenseReport"}, - {icon: , label:"Completion Report", path: "/analytics/CompletionReport"}, - {icon: , label:"Completion Report with Outstanding Un-billed Hours Report", path: "/analytics/CompletionReportWO"}, + {icon: , label:"Completion Report", path: "/analytics/ProjectCompletionReport"}, + {icon: , label:"Completion Report with Outstanding Un-billed Hours Report", path: "/analytics/ProjectCompletionReportWO"}, ], }, { diff --git a/src/components/Report/DelayReportGen/DelayReportGen.tsx b/src/components/Report/DelayReportGen/DelayReportGen.tsx index 4155613..8f8b10d 100644 --- a/src/components/Report/DelayReportGen/DelayReportGen.tsx +++ b/src/components/Report/DelayReportGen/DelayReportGen.tsx @@ -16,8 +16,8 @@ const ProgressByClientSearch: React.FC = ({ projects }) => { const searchCriteria: Criterion[] = useMemo( () => [ - { label: "Team", paramName: "team", type: "text" }, - { label: "Client", paramName: "client", type: "text" }, + { label: "Team", paramName: "team", type: "select", options: ["AAA", "BBB", "CCC"] }, + { label: "Client", paramName: "client", type: "select", options: ["Cust A", "Cust B", "Cust C"] }, { label: "Status", paramName: "status", type: "select", options: ["Delayed", "Potential Delay"] }, // { // label: "Status", diff --git a/src/components/Report/LateStartReportGen/LateStartReportGen.tsx b/src/components/Report/LateStartReportGen/LateStartReportGen.tsx index 81ff1a0..2fca827 100644 --- a/src/components/Report/LateStartReportGen/LateStartReportGen.tsx +++ b/src/components/Report/LateStartReportGen/LateStartReportGen.tsx @@ -5,6 +5,9 @@ import SearchBox, { Criterion } from "../../ReportSearchBox"; import { useTranslation } from "react-i18next"; import { LateStart } from "@/app/api/report"; //import { DownloadReportButton } from './DownloadReportButton'; +import axios from 'axios'; +import { apiPath } from '../../../auth/utils'; +//import { GET_QC_CATEGORY_COMBO } from 'utils/ApiPathConst'; interface Props { projects: LateStart[]; } @@ -13,11 +16,19 @@ type SearchParamNames = keyof SearchQuery; const ProgressByClientSearch: React.FC = ({ projects }) => { const { t } = useTranslation("projects"); - + // const [teamCombo, setteamCombo] = useState([]); + // const getteamCombo = () => { + // axios.get(`${apiPath}${GET_QC_CATEGORY_COMBO}`) + // .then(response => { + // setteamCombo(response.data.records)}) + // .catch(error => { + // console.error('Error fetching data: ', error); + // }); + // } const searchCriteria: Criterion[] = useMemo( () => [ - { label: "Team", paramName: "team", type: "text" }, - { label: "Client", paramName: "client", type: "text" }, + { label: "Team", paramName: "team", type: "select", options: ["AAA", "BBB", "CCC"] }, + { label: "Client", paramName: "client", type: "select", options: ["Cust A", "Cust B", "Cust C"] }, { label: "Remained Date From", label2: "Remained Date To", diff --git a/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx index 9d527a3..0faf37e 100644 --- a/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx +++ b/src/components/Report/ResourceOverconsumptionReportGen/ResourceOverconsumptionReportGen.tsx @@ -16,8 +16,8 @@ const ProgressByClientSearch: React.FC = ({ projects }) => { const searchCriteria: Criterion[] = useMemo( () => [ - { label: "Team", paramName: "team", type: "text" }, - { label: "Client", paramName: "client", type: "text" }, + { label: "Team", paramName: "team", type: "select", options: ["AAA", "BBB", "CCC"] }, + { label: "Client", paramName: "client", type: "select", options: ["Cust A", "Cust B", "Cust C"] }, { label: "Status", paramName: "status", type: "select", options: ["Overconsumption", "Potential Overconsumption"] }, // { // label: "Status", From 2e0d69e80444612f4b02c32867b10ce83e4f0b10 Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Tue, 23 Apr 2024 18:07:43 +0800 Subject: [PATCH 5/6] add report ar04 --- public/temp/AR04_Cost and Expense Report.xlsx | Bin 0 -> 12817 bytes .../analytics/CostandExpenseReport/page.tsx | 10 +- src/app/api/report4/index.ts | 42 +++ .../CostandExpenseReport.tsx | 17 + .../Report/CostandExpenseReport/index.ts | 2 + .../CostandExpenseReportGen.tsx | 45 +++ .../CostandExpenseReportGenLoading.tsx | 41 +++ .../CostandExpenseReportGenWrapper.tsx | 19 ++ .../Report/CostandExpenseReportGen/index.ts | 2 + .../ReportSearchBox4/SearchBox4.tsx | 302 ++++++++++++++++++ src/components/ReportSearchBox4/index.ts | 3 + 11 files changed, 478 insertions(+), 5 deletions(-) create mode 100644 public/temp/AR04_Cost and Expense Report.xlsx create mode 100644 src/app/api/report4/index.ts create mode 100644 src/components/Report/CostandExpenseReport/CostandExpenseReport.tsx create mode 100644 src/components/Report/CostandExpenseReport/index.ts create mode 100644 src/components/Report/CostandExpenseReportGen/CostandExpenseReportGen.tsx create mode 100644 src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenLoading.tsx create mode 100644 src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenWrapper.tsx create mode 100644 src/components/Report/CostandExpenseReportGen/index.ts create mode 100644 src/components/ReportSearchBox4/SearchBox4.tsx create mode 100644 src/components/ReportSearchBox4/index.ts diff --git a/public/temp/AR04_Cost and Expense Report.xlsx b/public/temp/AR04_Cost and Expense Report.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a414e1afcda8192ce80e8ffcf809f49378b80ceb GIT binary patch literal 12817 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 K{PV1T-2Fd_QUOo^ literal 0 HcmV?d00001 diff --git a/src/app/(main)/analytics/CostandExpenseReport/page.tsx b/src/app/(main)/analytics/CostandExpenseReport/page.tsx index 2f046c3..5cd328b 100644 --- a/src/app/(main)/analytics/CostandExpenseReport/page.tsx +++ b/src/app/(main)/analytics/CostandExpenseReport/page.tsx @@ -1,14 +1,14 @@ -//src\app\(main)\analytics\LateStartReport\page.tsx +//src\app\(main)\analytics\CostandExpenseReport\page.tsx import { Metadata } from "next"; import { I18nProvider } from "@/i18n"; import Typography from "@mui/material/Typography"; -import LateStartReportComponent from "@/components/LateStartReport"; +import CostandExpenseReportComponent from "@/components/Report/CostandExpenseReport"; export const metadata: Metadata = { title: "Project Status by Client", }; -const ProjectLateReport: React.FC = () => { +const CostandExpenseReport: React.FC = () => { return ( @@ -17,8 +17,8 @@ const ProjectLateReport: React.FC = () => { {/* }> */} - + ); }; -export default ProjectLateReport; +export default CostandExpenseReport; diff --git a/src/app/api/report4/index.ts b/src/app/api/report4/index.ts new file mode 100644 index 0000000..5117519 --- /dev/null +++ b/src/app/api/report4/index.ts @@ -0,0 +1,42 @@ +//src\app\api\report\index.ts +import { cache } from "react"; + +export interface CostandExpense { + id: number; + projectCode: string; + projectName: string; + team: string; + teamLeader: string; + startDate: string; + startDateFrom: string; + startDateTo: string; + targetEndDate: string; + client: string; + subsidiary: string; + remainPercent: string; +} + +export const preloadProjects = () => { + fetchProjectsCostandExpense(); +}; + +export const fetchProjectsCostandExpense = cache(async () => { + return mockProjects; +}); + +const mockProjects: CostandExpense[] = [ + { + id: 1, + projectCode: "CUST-001", + projectName: "Client A", + team: "N/A", + teamLeader: "N/A", + startDate: "1/2/2024", + startDateFrom: "1/2/2024", + startDateTo: "1/2/2024", + targetEndDate: "30/3/2024", + client: "ss", + subsidiary: "sus", + remainPercent: "1", + }, +]; diff --git a/src/components/Report/CostandExpenseReport/CostandExpenseReport.tsx b/src/components/Report/CostandExpenseReport/CostandExpenseReport.tsx new file mode 100644 index 0000000..6c43a0a --- /dev/null +++ b/src/components/Report/CostandExpenseReport/CostandExpenseReport.tsx @@ -0,0 +1,17 @@ +//src\components\DelayReport\DelayReport.tsx +"use client"; +import * as React from "react"; +import "../../../app/global.css"; +import { Suspense } from "react"; +import CostandExpenseReportGen from "@/components/Report/CostandExpenseReportGen"; + +const CostandExpenseReport: React.FC = () => { + + return ( + }> + + + ); +}; + +export default CostandExpenseReport; \ No newline at end of file diff --git a/src/components/Report/CostandExpenseReport/index.ts b/src/components/Report/CostandExpenseReport/index.ts new file mode 100644 index 0000000..0dd1e51 --- /dev/null +++ b/src/components/Report/CostandExpenseReport/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReport\index.ts +export { default } from "./CostandExpenseReport"; diff --git a/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGen.tsx b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGen.tsx new file mode 100644 index 0000000..eea61cf --- /dev/null +++ b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGen.tsx @@ -0,0 +1,45 @@ +//src\components\LateStartReportGen\LateStartReportGen.tsx +"use client"; +import React, { useMemo, useState } from "react"; +import SearchBox, { Criterion } from "../../ReportSearchBox4"; +import { useTranslation } from "react-i18next"; +import { CostandExpense } from "@/app/api/report4"; + +interface Props { + projects: CostandExpense[]; +} +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const ProgressByClientSearch: React.FC = ({ projects }) => { + const { t } = useTranslation("projects"); + + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: "Team", paramName: "team", type: "select", options: ["AAA", "BBB", "CCC"] }, + { label: "Client", paramName: "client", type: "select", options: ["Cust A", "Cust B", "Cust C"] }, + { label: "Remaining Percentage", paramName: "remainPercent", type: "select", options: ["<50%", "50%-70%", ">70%"] }, + // { + // label: "Status", + // label2: "Remained Date To", + // paramName: "targetEndDate", + // type: "dateRange", + // }, + ], + [t], + ); + + return ( + <> + { + console.log(query); + }} + /> + {/* */} + + ); +}; + +export default ProgressByClientSearch; diff --git a/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenLoading.tsx b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenLoading.tsx new file mode 100644 index 0000000..9b0341d --- /dev/null +++ b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenLoading.tsx @@ -0,0 +1,41 @@ +//src\components\LateStartReportGen\LateStartReportGenLoading.tsx +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 DelayReportGenLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default DelayReportGenLoading; diff --git a/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenWrapper.tsx b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenWrapper.tsx new file mode 100644 index 0000000..b11b808 --- /dev/null +++ b/src/components/Report/CostandExpenseReportGen/CostandExpenseReportGenWrapper.tsx @@ -0,0 +1,19 @@ +//src\components\LateStartReportGen\LateStartReportGenWrapper.tsx +import { fetchProjectsCostandExpense } from "@/app/api/report4"; +import React from "react"; +import CostandExpenseReportGen from "./CostandExpenseReportGen"; +import CostandExpenseReportGenLoading from "./CostandExpenseReportGenLoading"; + +interface SubComponents { + Loading: typeof CostandExpenseReportGenLoading; +} + +const CostandExpenseReportGenWrapper: React.FC & SubComponents = async () => { + const clentprojects = await fetchProjectsCostandExpense(); + + return ; +}; + +CostandExpenseReportGenWrapper.Loading = CostandExpenseReportGenLoading; + +export default CostandExpenseReportGenWrapper; \ No newline at end of file diff --git a/src/components/Report/CostandExpenseReportGen/index.ts b/src/components/Report/CostandExpenseReportGen/index.ts new file mode 100644 index 0000000..0ef6085 --- /dev/null +++ b/src/components/Report/CostandExpenseReportGen/index.ts @@ -0,0 +1,2 @@ +//src\components\DelayReportGen\index.ts +export { default } from "./CostandExpenseReportGenWrapper"; diff --git a/src/components/ReportSearchBox4/SearchBox4.tsx b/src/components/ReportSearchBox4/SearchBox4.tsx new file mode 100644 index 0000000..8b9dd4d --- /dev/null +++ b/src/components/ReportSearchBox4/SearchBox4.tsx @@ -0,0 +1,302 @@ +//src\components\ReportSearchBox3\SearchBox3.tsx +"use client"; + +import Grid from "@mui/material/Grid"; +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Typography from "@mui/material/Typography"; +import React, { useCallback, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import TextField from "@mui/material/TextField"; +import FormControl from "@mui/material/FormControl"; +import InputLabel from "@mui/material/InputLabel"; +import Select, { SelectChangeEvent } from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; +import CardActions from "@mui/material/CardActions"; +import Button from "@mui/material/Button"; +import RestartAlt from "@mui/icons-material/RestartAlt"; +import Search from "@mui/icons-material/Search"; +import dayjs from "dayjs"; +import "dayjs/locale/zh-hk"; +import { DatePicker } from "@mui/x-date-pickers/DatePicker"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { Box } from "@mui/material"; +import * as XLSX from 'xlsx-js-style'; +//import { DownloadReportButton } from '../LateStartReportGen/DownloadReportButton'; + +interface BaseCriterion { + label: string; + label2?: string; + paramName: T; + paramName2?: T; +} + +interface TextCriterion extends BaseCriterion { + type: "text"; +} + +interface SelectCriterion extends BaseCriterion { + type: "select"; + options: string[]; +} + +interface DateRangeCriterion extends BaseCriterion { + type: "dateRange"; +} + +export type Criterion = + | TextCriterion + | SelectCriterion + | DateRangeCriterion; + +interface Props { + criteria: Criterion[]; + onSearch: (inputs: Record) => void; + onReset?: () => void; +} + +function SearchBox({ + criteria, + onSearch, + onReset, +}: Props) { + const { t } = useTranslation("common"); + const defaultInputs = useMemo( + () => + criteria.reduce>( + (acc, c) => { + return { ...acc, [c.paramName]: c.type === "select" ? "All" : "" }; + }, + {} as Record, + ), + [criteria], + ); + const [inputs, setInputs] = useState(defaultInputs); + + const makeInputChangeHandler = useCallback( + (paramName: T): React.ChangeEventHandler => { + return (e) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, + [], + ); + + const makeSelectChangeHandler = useCallback((paramName: T) => { + return (e: SelectChangeEvent) => { + setInputs((i) => ({ ...i, [paramName]: e.target.value })); + }; + }, []); + + const makeDateChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ ...i, [paramName]: dayjs(e).format("YYYY-MM-DD") })); + }; + }, []); + + const makeDateToChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ + ...i, + [paramName + "To"]: dayjs(e).format("YYYY-MM-DD"), + })); + }; + }, []); + + const handleReset = () => { + setInputs(defaultInputs); + onReset?.(); + }; + + const handleSearch = () => { + onSearch(inputs); + + }; + + const handleDownload = async () => { + //setIsLoading(true); + + try { + const response = await fetch('/temp/AR04_Cost and Expense Report.xlsx', { + headers: { + 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + }, + }); + if (!response.ok) throw new Error('Network response was not ok.'); + + const data = await response.blob(); + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target && e.target.result) { + const ab = e.target.result as ArrayBuffer; + const workbook = XLSX.read(ab, { type: 'array' }); + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + + // Add the current date to cell C2 + const cellAddress = 'C2'; + const date = new Date().toISOString().split('T')[0]; // Format YYYY-MM-DD + const formattedDate = date.replace(/-/g, '/'); // Change format to YYYY/MM/DD + XLSX.utils.sheet_add_aoa(worksheet, [[formattedDate]], { origin: cellAddress }); + + // Calculate the maximum length of content in each column and set column width + const colWidths: number[] = []; + + const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: "", blankrows: true }) as (string | number)[][]; + jsonData.forEach((row: (string | number)[]) => { + row.forEach((cell: string | number, index: number) => { + const valueLength = cell.toString().length; + colWidths[index] = Math.max(colWidths[index] || 0, valueLength); + }); + }); + + // Apply calculated widths to each column, skipping column A + worksheet['!cols'] = colWidths.map((width, index) => { + if (index === 0) { + return { wch: 8 }; // Set default or specific width for column A if needed + } + return { wch: width + 2 }; // Add padding to width + }); + + // Style for cell A1: Font size 16 and bold + if (worksheet['A1']) { + worksheet['A1'].s = { + font: { + bold: true, + sz: 16, // Font size 16 + //name: 'Times New Roman' // Specify font + } + }; + } + + // Apply styles from A2 to A4 (bold) + ['A2', 'A3', 'A4'].forEach(cell => { + if (worksheet[cell]) { + worksheet[cell].s = { font: { bold: true } }; + } + }); + + // Formatting from A6 to J6 + // Apply styles from A6 to J6 (bold, bottom border, center alignment) + for (let col = 0; col < 10; col++) { // Columns A to K + const cellRef = XLSX.utils.encode_col(col) + '6'; + if (worksheet[cellRef]) { + worksheet[cellRef].s = { + font: { bold: true }, + alignment: { horizontal: 'center' }, + border: { + bottom: { style: 'thin', color: { auto: 1 } } + } + }; + } + } + + // Format filename with date + const today = new Date().toISOString().split('T')[0].replace(/-/g, '_'); // Get current date and format as YYYY_MM_DD + const filename = `AR04_Cost_and_Expense_Report_${today}.xlsx`; // Append formatted date to the filename + + // Convert workbook back to XLSX file + XLSX.writeFile(workbook, filename); + } else { + throw new Error('Failed to load file'); + } + }; + reader.readAsArrayBuffer(data); + } catch (error) { + console.error('Error downloading the file: ', error); + } + + //setIsLoading(false); + }; + return ( + + + {t("Search Criteria")} + + {criteria.map((c) => { + return ( + + {c.type === "text" && ( + + )} + {c.type === "select" && ( + + {c.label} + + + )} + {c.type === "dateRange" && ( + + + + + + + {"-"} + + + + + + + )} + + ); + })} + + + + + + + + ); +} + +export default SearchBox; diff --git a/src/components/ReportSearchBox4/index.ts b/src/components/ReportSearchBox4/index.ts new file mode 100644 index 0000000..0e518ff --- /dev/null +++ b/src/components/ReportSearchBox4/index.ts @@ -0,0 +1,3 @@ +//src\components\SearchBox\index.ts +export { default } from "./SearchBox4"; +export type { Criterion } from "./SearchBox4"; From ab876f35f69cb9a7cd5f2755c890c89bc68421e4 Mon Sep 17 00:00:00 2001 From: Wayne Date: Tue, 23 Apr 2024 23:49:43 +0900 Subject: [PATCH 6/6] Small fixes --- src/app/utils/formatUtil.ts | 2 +- src/components/CreateProject/CreateProject.tsx | 11 ++++++++--- src/components/CreateProject/MilestoneSection.tsx | 8 ++++---- src/components/TimesheetTable/EntryInputTable.tsx | 3 +++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts index 14d2ed1..4f364e8 100644 --- a/src/app/utils/formatUtil.ts +++ b/src/app/utils/formatUtil.ts @@ -39,7 +39,7 @@ export const shortDateFormatter = (locale?: string) => { } }; -export function convertLocaleStringToNumber(numberString: String): number { +export function convertLocaleStringToNumber(numberString: string): number { const numberWithoutCommas = numberString.replace(/,/g, ""); return parseFloat(numberWithoutCommas); } diff --git a/src/components/CreateProject/CreateProject.tsx b/src/components/CreateProject/CreateProject.tsx index 61409b0..b8faa5e 100644 --- a/src/components/CreateProject/CreateProject.tsx +++ b/src/components/CreateProject/CreateProject.tsx @@ -61,7 +61,9 @@ const hasErrorsInTab = ( ) => { switch (tabIndex) { case 0: - return errors.projectName; + return ( + errors.projectName || errors.projectCode || errors.projectDescription + ); default: false; } @@ -101,7 +103,6 @@ const CreateProject: React.FC = ({ const onSubmit = useCallback>( async (data) => { try { - console.log(data); setServerError(""); await saveProject(data); router.replace("/projects"); @@ -115,7 +116,11 @@ const CreateProject: React.FC = ({ const onSubmitError = useCallback>( (errors) => { // Set the tab so that the focus will go there - if (errors.projectName) { + if ( + errors.projectName || + errors.projectDescription || + errors.projectCode + ) { setTabIndex(0); } }, diff --git a/src/components/CreateProject/MilestoneSection.tsx b/src/components/CreateProject/MilestoneSection.tsx index 9d18717..68a35a2 100644 --- a/src/components/CreateProject/MilestoneSection.tsx +++ b/src/components/CreateProject/MilestoneSection.tsx @@ -29,7 +29,7 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; import StyledDataGrid from "../StyledDataGrid"; -import { moneyFormatter } from "@/app/utils/formatUtil"; +import { INPUT_DATE_FORMAT, moneyFormatter } from "@/app/utils/formatUtil"; import isDate from "lodash/isDate"; interface Props { @@ -206,7 +206,7 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => { description: p.description!, id: p.id!, amount: p.amount!, - date: dayjs(p.date!).toISOString(), + date: dayjs(p.date!).format(INPUT_DATE_FORMAT), })), }, }); @@ -245,7 +245,7 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => { ...milestones, [taskGroupId]: { ...milestones[taskGroupId], - startDate: date.toISOString(), + startDate: date.format(INPUT_DATE_FORMAT), }, }); }} @@ -264,7 +264,7 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => { ...milestones, [taskGroupId]: { ...milestones[taskGroupId], - endDate: date.toISOString(), + endDate: date.format(INPUT_DATE_FORMAT), }, }); }} diff --git a/src/components/TimesheetTable/EntryInputTable.tsx b/src/components/TimesheetTable/EntryInputTable.tsx index 57a18b3..7d9e9de 100644 --- a/src/components/TimesheetTable/EntryInputTable.tsx +++ b/src/components/TimesheetTable/EntryInputTable.tsx @@ -22,6 +22,9 @@ import { AssignedProject } from "@/app/api/projects"; import uniqBy from "lodash/uniqBy"; import { TaskGroup } from "@/app/api/tasks"; import dayjs from "dayjs"; +import isBetween from "dayjs/plugin/isBetween"; + +dayjs.extend(isBetween); const mockProjects: AssignedProject[] = [ {