From 48541ba33b635abd9f3481aa8a0641a2e27e2fa4 Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Tue, 23 Apr 2024 14:36:04 +0800 Subject: [PATCH] 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";