From cef15cef561dc1cb36b12921cd0e2395da57754f Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Wed, 24 Apr 2024 14:33:33 +0800 Subject: [PATCH] add report ar05 --- .../temp/AR05_Project Completion Report.xlsx | Bin 0 -> 12445 bytes .../ProjectCompletionReport/page.tsx | 10 +- src/app/api/report5/index.ts | 42 +++ .../ProjectCompletionReport.tsx | 17 + .../Report/ProjectCompletionReport/index.ts | 2 + .../ProjectCompletionReportGen.tsx | 44 +++ .../ProjectCompletionReportGenLoading.tsx | 41 +++ .../ProjectCompletionReportGenWrapper.tsx | 19 ++ .../ProjectCompletionReportGen/index.ts | 2 + .../ReportSearchBox5/SearchBox5.tsx | 302 ++++++++++++++++++ src/components/ReportSearchBox5/index.ts | 3 + 11 files changed, 477 insertions(+), 5 deletions(-) create mode 100644 public/temp/AR05_Project Completion Report.xlsx create mode 100644 src/app/api/report5/index.ts create mode 100644 src/components/Report/ProjectCompletionReport/ProjectCompletionReport.tsx create mode 100644 src/components/Report/ProjectCompletionReport/index.ts create mode 100644 src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGen.tsx create mode 100644 src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenLoading.tsx create mode 100644 src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenWrapper.tsx create mode 100644 src/components/Report/ProjectCompletionReportGen/index.ts create mode 100644 src/components/ReportSearchBox5/SearchBox5.tsx create mode 100644 src/components/ReportSearchBox5/index.ts diff --git a/public/temp/AR05_Project Completion Report.xlsx b/public/temp/AR05_Project Completion Report.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..60deae81b83a6bf0bc05771a2318ceaa9f4a6f0b GIT binary patch literal 12445 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 { +const ProjectCompletionReport: React.FC = () => { return ( @@ -17,8 +17,8 @@ const ProjectLateReport: React.FC = () => { {/* }> */} - + ); }; -export default ProjectLateReport; +export default ProjectCompletionReport; diff --git a/src/app/api/report5/index.ts b/src/app/api/report5/index.ts new file mode 100644 index 0000000..f0ed563 --- /dev/null +++ b/src/app/api/report5/index.ts @@ -0,0 +1,42 @@ +//src\app\api\report\index.ts +import { cache } from "react"; + +export interface ProjectCompletion { + id: number; + projectCode: string; + projectName: string; + team: string; + teamLeader: string; + startDate: string; + startDateFrom: string; + startDateTo: string; + targetEndDate: string; + client: string; + subsidiary: string; + completeDate: string; +} + +export const preloadProjects = () => { + fetchProjectsProjectCompletion(); +}; + +export const fetchProjectsProjectCompletion = cache(async () => { + return mockProjects; +}); + +const mockProjects: ProjectCompletion[] = [ + { + 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", + completeDate:"30/2/2024", + }, +]; diff --git a/src/components/Report/ProjectCompletionReport/ProjectCompletionReport.tsx b/src/components/Report/ProjectCompletionReport/ProjectCompletionReport.tsx new file mode 100644 index 0000000..dbd2e2d --- /dev/null +++ b/src/components/Report/ProjectCompletionReport/ProjectCompletionReport.tsx @@ -0,0 +1,17 @@ +//src\components\LateStartReport\LateStartReport.tsx +"use client"; +import * as React from "react"; +import "../../../app/global.css"; +import { Suspense } from "react"; +import ProjectCompletionReportGen from "@/components/Report/ProjectCompletionReportGen"; + +const ProjectCompletionReport: React.FC = () => { + + return ( + }> + + + ); +}; + +export default ProjectCompletionReport; \ No newline at end of file diff --git a/src/components/Report/ProjectCompletionReport/index.ts b/src/components/Report/ProjectCompletionReport/index.ts new file mode 100644 index 0000000..a5233e6 --- /dev/null +++ b/src/components/Report/ProjectCompletionReport/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReport\index.ts +export { default } from "./ProjectCompletionReport"; diff --git a/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGen.tsx b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGen.tsx new file mode 100644 index 0000000..75b12ac --- /dev/null +++ b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGen.tsx @@ -0,0 +1,44 @@ +//src\components\LateStartReportGen\LateStartReportGen.tsx +"use client"; +import React, { useMemo, useState } from "react"; +import SearchBox, { Criterion } from "../../ReportSearchBox5"; +import { useTranslation } from "react-i18next"; +import { ProjectCompletion } from "@/app/api/report5"; +//import { DownloadReportButton } from './DownloadReportButton'; +interface Props { + projects: ProjectCompletion[]; +} +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: "Report Period From", + label2: "Report Period To", + paramName: "targetEndDate", + type: "dateRange", + }, + ], + [t], + ); + + return ( + <> + { + console.log(query); + }} + /> + {/* */} + + ); +}; + +export default ProgressByClientSearch; diff --git a/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenLoading.tsx b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenLoading.tsx new file mode 100644 index 0000000..466b74d --- /dev/null +++ b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenLoading.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 ProjectCompletionReportGenLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ProjectCompletionReportGenLoading; diff --git a/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenWrapper.tsx b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenWrapper.tsx new file mode 100644 index 0000000..02f9624 --- /dev/null +++ b/src/components/Report/ProjectCompletionReportGen/ProjectCompletionReportGenWrapper.tsx @@ -0,0 +1,19 @@ +//src\components\LateStartReportGen\LateStartReportGenWrapper.tsx +import { fetchProjectsProjectCompletion } from "@/app/api/report5"; +import React from "react"; +import ProjectCompletionReportGen from "./ProjectCompletionReportGen"; +import ProjectCompletionReportGenLoading from "./ProjectCompletionReportGenLoading"; + +interface SubComponents { + Loading: typeof ProjectCompletionReportGenLoading; +} + +const ProjectCompletionReportGenWrapper: React.FC & SubComponents = async () => { + const clentprojects = await fetchProjectsProjectCompletion(); + + return ; +}; + +ProjectCompletionReportGenWrapper.Loading = ProjectCompletionReportGenLoading; + +export default ProjectCompletionReportGenWrapper; \ No newline at end of file diff --git a/src/components/Report/ProjectCompletionReportGen/index.ts b/src/components/Report/ProjectCompletionReportGen/index.ts new file mode 100644 index 0000000..269443a --- /dev/null +++ b/src/components/Report/ProjectCompletionReportGen/index.ts @@ -0,0 +1,2 @@ +//src\components\LateStartReportGen\index.ts +export { default } from "./ProjectCompletionReportGenWrapper"; diff --git a/src/components/ReportSearchBox5/SearchBox5.tsx b/src/components/ReportSearchBox5/SearchBox5.tsx new file mode 100644 index 0000000..b252103 --- /dev/null +++ b/src/components/ReportSearchBox5/SearchBox5.tsx @@ -0,0 +1,302 @@ +//src\components\ReportSearchBox\SearchBox.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/AR05_Project Completion 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 A3 (bold) + ['A2', 'A3'].forEach(cell => { + if (worksheet[cell]) { + worksheet[cell].s = { font: { bold: true } }; + } + }); + + // Formatting from A5 to F5 + // Apply styles from A5 to F5 (bold, bottom border, center alignment) + for (let col = 0; col < 6; col++) { // Columns A to F + const cellRef = XLSX.utils.encode_col(col) + '5'; + 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 = `AR05_Project_Completion_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/ReportSearchBox5/index.ts b/src/components/ReportSearchBox5/index.ts new file mode 100644 index 0000000..493ae58 --- /dev/null +++ b/src/components/ReportSearchBox5/index.ts @@ -0,0 +1,3 @@ +//src\components\SearchBox\index.ts +export { default } from "./SearchBox5"; +export type { Criterion } from "./SearchBox5";