From ed419e0953869a56273704924ed24878385421c7 Mon Sep 17 00:00:00 2001 From: kelvinsuen Date: Fri, 5 Sep 2025 17:26:20 +0800 Subject: [PATCH] update escalation tab update stock in modal --- .../CollapsibleCard/CollapsibleCard.tsx | 85 ++++--- .../DashboardPage/DashboardPage.tsx | 2 + .../escalation/EscalationLogTable.tsx | 19 +- src/components/PoDetail/PoInputGrid.tsx | 2 +- src/components/PoDetail/PutAwayForm.tsx | 52 +---- src/components/PoDetail/QcComponent.tsx | 33 ++- src/components/PoDetail/QcStockInModal.tsx | 208 ++++++++++-------- src/i18n/zh/dashboard.json | 3 +- src/i18n/zh/purchaseOrder.json | 8 +- 9 files changed, 229 insertions(+), 183 deletions(-) diff --git a/src/components/CollapsibleCard/CollapsibleCard.tsx b/src/components/CollapsibleCard/CollapsibleCard.tsx index c98dd8c..7ea5544 100644 --- a/src/components/CollapsibleCard/CollapsibleCard.tsx +++ b/src/components/CollapsibleCard/CollapsibleCard.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { createContext, useContext, useState, useCallback, Dispatch, SetStateAction } from "react"; import { Card, CardHeader, @@ -7,6 +7,7 @@ import { Collapse, Checkbox, Box, + FormControlLabel, } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandLessIcon from "@mui/icons-material/ExpandLess"; @@ -18,6 +19,19 @@ interface CollapsibleCardProps { showFilter?: boolean; filterText?: string; } +interface CardFilterContextType { + filter: boolean; + onFilterChange: (checked: boolean) => void; + filterText: string; + setOnFilterChange: (override: () => void) => void; +} + +export const CardFilterContext = createContext({ + filter: false, + onFilterChange: (checked: boolean) => {}, + filterText: "FilterText", + setOnFilterChange: () => {}, //Not working yet +}); const CollapsibleCard: React.FC = ({ title, @@ -28,38 +42,51 @@ const CollapsibleCard: React.FC = ({ }) => { const [filter, setFilter] = useState(false); + const [open, setOpen] = useState(defaultOpen); + const [onFilterChange, setOnFilterChange] = useState<() => void>(); - const onFilterChange = (bool : boolean) => { - setFilter(bool); + const handleFilterChange = useCallback((checked : boolean) => { + if (onFilterChange) { + onFilterChange(); + } + + setFilter(checked); setOpen(true); - } - const [open, setOpen] = useState(defaultOpen); + }, [onFilterChange]); return ( - - - {showFilter && ( - <> - {onFilterChange(e.target.checked);}} - // disabled={!isEmpty(pickOrder.consoCode)} - /> {filterText} - )} - setOpen((v) => !v)}> - {open ? : } - - - } - /> - - {children} - - + + + + {showFilter && ( + <> + handleFilterChange(e.target.checked)} + /> + } + label={filterText} // Use filterText as the label + sx={{ marginRight: 2 }} // Optional: Adjust spacing + /> + )} + setOpen((v) => !v)}> + {open ? : } + + + } + /> + + {children} + + + ); }; diff --git a/src/components/DashboardPage/DashboardPage.tsx b/src/components/DashboardPage/DashboardPage.tsx index a143102..c4a8a92 100644 --- a/src/components/DashboardPage/DashboardPage.tsx +++ b/src/components/DashboardPage/DashboardPage.tsx @@ -46,6 +46,8 @@ const DashboardPage: React.FC = ({ 0 ? getPendingLog().length : t("No")})`} + showFilter={true} + filterText={t("show completed logs")} // defaultOpen={getPendingLog().length > 0} // TODO Fix default not opening > diff --git a/src/components/DashboardPage/escalation/EscalationLogTable.tsx b/src/components/DashboardPage/escalation/EscalationLogTable.tsx index 52b47e3..68866f9 100644 --- a/src/components/DashboardPage/escalation/EscalationLogTable.tsx +++ b/src/components/DashboardPage/escalation/EscalationLogTable.tsx @@ -2,13 +2,14 @@ import { Box, Card, CardActionArea, CardContent, CardHeader, Grid, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material"; import { useRouter } from "next/navigation"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { usePathname } from "next/navigation"; import { useTranslation } from "react-i18next"; import { EscalationResult } from "@/app/api/escalation"; import { Column } from "@/components/SearchResults"; import SearchResults from "@/components/SearchResults/SearchResults"; import { arrayToDateString, arrayToDateTimeString } from "@/app/utils/formatUtil"; +import { CardFilterContext } from "@/components/CollapsibleCard/CollapsibleCard"; export type IQCItems = { id: number; @@ -36,6 +37,20 @@ const EscalationLogTable: React.FC = ({ const router = useRouter(); const [selectedId, setSelectedId] = useState(null); + const [escalationLogs, setEscalationLogs] = useState([]); + + const useCardFilter = useContext(CardFilterContext); + const showCompleted = useCardFilter.filter; + + useEffect(() => { + if (showCompleted) { + setEscalationLogs(items); + } else { + const filteredEscLog = items.filter(log => log.status == "pending"); + setEscalationLogs(filteredEscLog); + } + }, [showCompleted, items]) + const navigateTo = useCallback( (item: EscalationResult) => { setSelectedId(item.id); @@ -237,7 +252,7 @@ const EscalationLogTable: React.FC = ({ return ( diff --git a/src/components/PoDetail/PoInputGrid.tsx b/src/components/PoDetail/PoInputGrid.tsx index d218d6d..9f6b5b7 100644 --- a/src/components/PoDetail/PoInputGrid.tsx +++ b/src/components/PoDetail/PoInputGrid.tsx @@ -443,7 +443,7 @@ const closeNewModal = useCallback(() => { const status = sil?.status?.toLowerCase(); let btnSx = {label:"", color:""}; switch (status) { - case "received": btnSx = {label: t("putaway processing"), color:"secondary.main"}; break; + case "received": btnSx = {label: t("view putaway"), color:"secondary.main"}; break; case "escalated": if (sessionToken?.id == sil?.handlerId) { btnSx = {label: t("escalation processing"), color:"warning.main"}; break;} diff --git a/src/components/PoDetail/PutAwayForm.tsx b/src/components/PoDetail/PutAwayForm.tsx index 7f4512d..6e9334f 100644 --- a/src/components/PoDetail/PutAwayForm.tsx +++ b/src/components/PoDetail/PutAwayForm.tsx @@ -198,56 +198,6 @@ const PutAwayForm: React.FC = ({ itemDetail, warehouse, disabled, setRowM [], ); - const onOpenScanner = useCallback(() => { - setOpenScanner(true); - }, []); - - const onCloseScanner = useCallback(() => { - setOpenScanner(false); - }, []); - const scannerConfig = useMemo( - () => ({ - onUpdate: (err, result) => { - console.log(result); - console.log(Boolean(result)); - if (result) { - const data: QrCodeInfo = JSON.parse(result.getText()); - console.log(data); - if (data.warehouseId) { - console.log(data.warehouseId); - setWarehouseId(data.warehouseId); - onCloseScanner(); - } - } else return; - }, - }), - [onCloseScanner], - ); - - // QR Code Scanner - const scanner = useQrCodeScannerContext(); - useEffect(() => { - if (isOpenScanner) { - scanner.startScan(); - } else if (!isOpenScanner) { - scanner.stopScan(); - } - }, [isOpenScanner]); - - useEffect(() => { - if (scanner.values.length > 0) { - console.log(scanner.values[0]); - const data: QrCodeInfo = JSON.parse(scanner.values[0]); - console.log(data); - if (data.warehouseId) { - console.log(data.warehouseId); - setWarehouseId(data.warehouseId); - onCloseScanner(); - } - scanner.resetScan(); - } - }, [scanner.values]); - useEffect(() => { setValue("status", "received"); // setValue("status", "completed"); @@ -536,7 +486,7 @@ const PutAwayForm: React.FC = ({ itemDetail, warehouse, disabled, setRowM {/* */} apiRef={apiRef} - checkboxSelection={true} + checkboxSelection={false} _formKey={"putAwayLines"} columns={columns} validateRow={validation} diff --git a/src/components/PoDetail/QcComponent.tsx b/src/components/PoDetail/QcComponent.tsx index 15cd55f..c9e770e 100644 --- a/src/components/PoDetail/QcComponent.tsx +++ b/src/components/PoDetail/QcComponent.tsx @@ -239,13 +239,19 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { { field: "code", headerName: t("qcItem"), + wrapText: true, flex: 2, renderCell: (params) => { const index = params.api.getRowIndexRelativeToVisibleRows(params.id) + 1; return ( - + {`${index}. ${params.value}`}
- {params.row.name}
+ {params.row.name}
)}, }, @@ -433,7 +439,7 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { const setDefaultQcDecision = (status : string | undefined) => { const param = status?.toLowerCase(); if (param !== undefined && param !== null) { - if (param == "completed" || param == "partially_completed") { + if (param == "received" || param == "completed" || param == "partially_completed") { return 1; } else if (param == "rejected") { return 2; @@ -456,6 +462,13 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { // return row.id || `${row.name}-${Math.random().toString(36).substr(2, 9)}`; }; + const getRowHeight = (row :any) => { // Not used? + console.log("row", row); + if (!row.model.name) { + return (row.model.name.length ?? 10) * 1.2 + 30; + } else { return 60} + }; + return ( <> @@ -504,8 +517,10 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { rows={qcResult} // rows={qcResult && qcResult.length > 0 ? qcResult : qcItems} // rows={disabled? qcResult:qcItems} - autoHeight + // autoHeight sortModel={[]} + // getRowHeight={getRowHeight} + getRowHeight={() => 'auto'} getRowId={getRowId} /> @@ -548,17 +563,13 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { sortModel={[]} />
- {/* { - setRowSelectionModel(newRowSelectionModel); - }} - /> */} )} + + {t("Qc Decision")} + { // setRows: Dispatch>; @@ -95,6 +100,14 @@ const PoQcStockInModalVer2: React.FC = ({ // Select Printer const [selectedPrinter, setSelectedPrinter] = useState(printerCombo[0]); + const [tabIndex, setTabIndex] = useState(0); + + const handleTabChange = useCallback>( + (_e, newValue) => { + setTabIndex(newValue); + }, + [], + ); const defaultNewValue = useMemo(() => { return ( @@ -150,6 +163,8 @@ const [qcItems, setQcItems] = useState(dummyQCData) setViewOnly(isViewOnly) } console.log("Modal ItemDetail updated:", itemDetail); + console.log("%c SHOW PUTAWAY? ", "color:lime", showPutaway); + if (showPutaway) { setTabIndex(1); } else { setTabIndex(0); } }, [itemDetail]); useEffect(() => { @@ -158,8 +173,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) }) setQcItems(dummyQCData); - setOpenPutaway(isPutaway); - + // setOpenPutaway(isPutaway); }, [open]) const [openPutaway, setOpenPutaway] = useState(false); @@ -322,7 +336,9 @@ const [qcItems, setQcItems] = useState(dummyQCData) if (qcData.qcAccept) { // submitDialogWithWarning(onOpenPutaway, t, {title:"Save success, confirm to proceed?", // confirmButtonText: t("confirm putaway"), html: ""}); - onOpenPutaway(); + // onOpenPutaway(); + closeHandler({}, "backdropClick"); + // setTabIndex(1); // Need to go Putaway tab? } else { closeHandler({}, "backdropClick"); } @@ -463,6 +479,11 @@ const [qcItems, setQcItems] = useState(dummyQCData) const acceptQty = formProps.watch("acceptedQty") + const showPutaway = useMemo(() => { + const status = itemDetail.status; + return status !== "pending" && status !== "escalated" && status !== "rejected"; + }, [itemDetail]); + const checkQcIsPassed = useCallback((qcItems: PurchaseQcResult[]) => { const isPassed = qcItems.every((qc) => qc.qcPassed); console.log(isPassed) @@ -492,88 +513,36 @@ const [qcItems, setQcItems] = useState(dummyQCData) overflowY: "auto", marginLeft: 3, marginRight: 3, + // overflow: "hidden", }} > - {openPutaway ? ( - + - - - { - setSelectedPrinter(value) - }} - renderInput={(params) => ( - - )} - /> - - - - - ) : ( - <> - - - - {t("qc processing")} - - - - - + + {showPutaway && } + + + + + {tabIndex === 0 && <> + + + {t("Delivery Detail")} + - {/* - - */} + + - {!viewOnly && ( + {/* */} + + + + } + + diff --git a/src/i18n/zh/dashboard.json b/src/i18n/zh/dashboard.json index 3e8835b..f0a2481 100644 --- a/src/i18n/zh/dashboard.json +++ b/src/i18n/zh/dashboard.json @@ -54,5 +54,6 @@ "escalated datetime": "上報時間", "escalateFrom": "上報同事", "No": "無", - "Responsible Escalation List": "負責的上報列表" + "Responsible Escalation List": "負責的上報列表", + "show completed logs": "顯示已完成上報" } diff --git a/src/i18n/zh/purchaseOrder.json b/src/i18n/zh/purchaseOrder.json index b50c720..79b7835 100644 --- a/src/i18n/zh/purchaseOrder.json +++ b/src/i18n/zh/purchaseOrder.json @@ -100,6 +100,7 @@ "Default Warehouse": "預設倉庫", "Select warehouse": "選擇倉庫", "Putaway Detail": "上架詳情", + "Delivery Detail": "來貨詳情", "LotNo": "批號", "Po Code": "採購訂單編號", "No Warehouse": "沒有倉庫", @@ -109,7 +110,8 @@ "Accept submit": "接受來貨", "qc processing": "處理來貨及品檢", "putaway processing": "處理來貨及上架", - "view stockin": "查看收貨及品檢", + "view stockin": "查看收貨詳情", + "view putaway": "查看上架詳情", "putawayBtn": "上架", "dnNo": "送貨單編號", "dnDate": "送貨單日期", @@ -144,5 +146,7 @@ "No Option": "沒有選項", "receivedTotal": "已來貨總數", "QC Record": "品檢記錄", - "value must be integer": "請輸入整數" + "value must be integer": "請輸入整數", + "dn and qc info": "來貨及品檢詳情", + "Qc Decision": "品檢詳情" }