From ee2cc7650773124d1b337c31fa7dc690ab911acc Mon Sep 17 00:00:00 2001 From: kelvinsuen Date: Mon, 27 Oct 2025 17:30:02 +0800 Subject: [PATCH] update qc modal --- src/app/api/stockIn/index.ts | 3 ++- src/components/PoDetail/PutAwayForm.tsx | 2 +- src/components/Qc/QcComponent.tsx | 18 +++++++------- src/components/Qc/QcStockInModal.tsx | 31 ++++++++++++++----------- src/i18n/zh/purchaseOrder.json | 3 ++- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/app/api/stockIn/index.ts b/src/app/api/stockIn/index.ts index 17dda00..2cafaca 100644 --- a/src/app/api/stockIn/index.ts +++ b/src/app/api/stockIn/index.ts @@ -1,5 +1,5 @@ import { cache } from "react"; -import "server-only"; +import "client-only"; // import { serverFetchJson } from "@/app/utils/fetchUtil"; // import { BASE_API_URL } from "@/config/api"; import { serverFetchJson } from "../../utils/fetchUtil"; @@ -14,6 +14,7 @@ export enum StockInStatus { RECEIVED = "received", APPROVED = "escalated", REJECTED = "rejected", + ESCALATED = "escalated", COMPLETED = "completed", PARTIALLY_COMPLETED = "partially_completed", } diff --git a/src/components/PoDetail/PutAwayForm.tsx b/src/components/PoDetail/PutAwayForm.tsx index 58c0ff0..ba0e4a1 100644 --- a/src/components/PoDetail/PutAwayForm.tsx +++ b/src/components/PoDetail/PutAwayForm.tsx @@ -116,7 +116,7 @@ const PutAwayForm: React.FC = ({ itemDetail, warehouse=[], disabled, setR return [ { value: 1, - label: t("W001 - 憶兆 3樓A倉"), + label: t("W201 - 2F-A,B室"), group: "default", }, ...filteredWarehouse.map((w) => ({ diff --git a/src/components/Qc/QcComponent.tsx b/src/components/Qc/QcComponent.tsx index f20a606..041aab4 100644 --- a/src/components/Qc/QcComponent.tsx +++ b/src/components/Qc/QcComponent.tsx @@ -203,13 +203,13 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { // Set initial value for acceptQty - useEffect(() => { - if (itemDetail?.demandQty > 0) { //!== undefined) { - setValue("acceptQty", itemDetail.demandQty); // TODO: THIS NEED TO UPDATE TO NOT USE DEMAND QTY - } else { - setValue("acceptQty", itemDetail?.acceptedQty); - } - }, [itemDetail?.demandQty, itemDetail?.acceptedQty, setValue]); + // useEffect(() => { + // if (itemDetail?.demandQty > 0) { //!== undefined) { + // setValue("acceptQty", itemDetail.demandQty); // TODO: THIS NEED TO UPDATE TO NOT USE DEMAND QTY + // } else { + // setValue("acceptQty", itemDetail?.acceptedQty); + // } + // }, [itemDetail?.demandQty, itemDetail?.acceptedQty, setValue]); // Fetch Qc Data useEffect(() => { @@ -532,6 +532,8 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { if (input) { // Selected Reject in new flow with Error if (value == "1") { // Selected Accept input.value = Number(accQty).toString(); + } else if (value == "3") { + input.value = ""; } else { if (Boolean(errors.acceptQty)) { setValue("acceptQty", 0); @@ -599,7 +601,7 @@ const QcComponent: React.FC = ({ itemDetail, disabled = false }) => { label={t("rejectQty")} sx={{ width: '150px' }} value={ - (!Boolean(errors.acceptQty) && qcDecision !== undefined) ? + (!Boolean(errors.acceptQty) && qcDecision !== undefined && qcDecision != 3) ? (qcDecision == 1 ? itemDetail.acceptedQty - accQty : itemDetail.acceptedQty) : "" } diff --git a/src/components/Qc/QcStockInModal.tsx b/src/components/Qc/QcStockInModal.tsx index 2edd7a6..8c39710 100644 --- a/src/components/Qc/QcStockInModal.tsx +++ b/src/components/Qc/QcStockInModal.tsx @@ -35,7 +35,7 @@ import { GridRowModesModel } from "@mui/x-data-grid"; import { isEmpty } from "lodash"; import { EscalationCombo } from "@/app/api/user"; import { truncateSync } from "fs"; -import { ModalFormInput, StockInLineInput, StockInLine } from "@/app/api/stockIn"; +import { ModalFormInput, StockInLineInput, StockInLine, StockInStatus } from "@/app/api/stockIn"; import { StockInLineEntry, updateStockInLine, printQrCodeForSil, PrintQrCodeForSilRequest } from "@/app/api/stockIn/actions"; import { fetchStockInLineInfo } from "@/app/api/stockIn/actions"; import FgStockInForm from "../StockIn/FgStockInForm"; @@ -83,7 +83,8 @@ const QcStockInModal: React.FC = ({ } = useTranslation("purchaseOrder"); const [stockInLineInfo, setStockInLineInfo] = useState(); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); // const [skipQc, setSkipQc] = useState(false); // const [viewOnly, setViewOnly] = useState(false); @@ -120,6 +121,7 @@ const QcStockInModal: React.FC = ({ // Fetch info if id is input useEffect(() => { setIsLoading(true); + setIsSubmitting(false); if (inputDetail && open) { console.log("%c Opened Modal with input:", "color:yellow", inputDetail); if (inputDetail.id) { @@ -157,7 +159,7 @@ const QcStockInModal: React.FC = ({ expiryDate: d.expiryDate ? arrayToDateString(d.expiryDate, "input") : undefined, receiptDate: d.receiptDate ? arrayToDateString(d.receiptDate, "input") : dayjs().add(0, "month").format(INPUT_DATE_FORMAT), - acceptQty: d.demandQty?? d.acceptedQty, + acceptQty: d.status != StockInStatus.REJECTED ? (d.demandQty?? d.acceptedQty) : 0, // escResult: (d.escResult && d.escResult?.length > 0) ? d.escResult : [], // qcResult: (d.qcResult && d.qcResult?.length > 0) ? d.qcResult : [],//[...dummyQCData], warehouseId: d.defaultWarehouseId ?? 1, @@ -195,7 +197,7 @@ const QcStockInModal: React.FC = ({ const showPutaway = useMemo(() => { if (stockInLineInfo) { const status = stockInLineInfo.status; - return status !== "pending" && status !== "escalated" && status !== "rejected"; + return status !== StockInStatus.PENDING && status !== StockInStatus.ESCALATED && status !== StockInStatus.REJECTED; } return false; }, [stockInLineInfo]); @@ -205,10 +207,10 @@ const QcStockInModal: React.FC = ({ if (stockInLineInfo) { if (stockInLineInfo.status) { const status = stockInLineInfo.status; - const isViewOnly = status.toLowerCase() == "completed" - || status.toLowerCase() == "partially_completed" // TODO update DB - || status.toLowerCase() == "rejected" - || (status.toLowerCase() == "escalated" && session?.id != stockInLineInfo.handlerId) + const isViewOnly = status.toLowerCase() == StockInStatus.COMPLETED + || status.toLowerCase() == StockInStatus.PARTIALLY_COMPLETED // TODO update DB + || status.toLowerCase() == StockInStatus.REJECTED + || (status.toLowerCase() == StockInStatus.ESCALATED && session?.id != stockInLineInfo.handlerId) if (showPutaway) { setTabIndex(1); } else { setTabIndex(0); } return isViewOnly; } @@ -311,7 +313,7 @@ const QcStockInModal: React.FC = ({ alert("請輸入到期日!"); return; } - if (!qcResults.every((qc) => qc.qcPassed) && qcAccept && stockInLineInfo?.status != "escalated") { //TODO: fix it please! + if (!qcResults.every((qc) => qc.qcPassed) && qcAccept && stockInLineInfo?.status != StockInStatus.ESCALATED) { //TODO: fix it please! validationErrors.push("有不合格檢查項目,無法收貨!"); // submitDialogWithWarning(() => postStockInLineWithQc(qcData), t, {title:"有不合格檢查項目,確認接受收貨?", // confirmButtonText: t("confirm putaway"), html: ""}); @@ -321,7 +323,7 @@ const QcStockInModal: React.FC = ({ // Check if all QC items have results const itemsWithoutResult = qcResults.filter(item => item.qcPassed === undefined); - if (itemsWithoutResult.length > 0 && stockInLineInfo?.status != "escalated") { //TODO: fix it please! + if (itemsWithoutResult.length > 0 && stockInLineInfo?.status != StockInStatus.ESCALATED) { //TODO: fix it please! validationErrors.push(`${t("QC items without result")}`); // validationErrors.push(`${t("QC items without result")}: ${itemsWithoutResult.map(item => item.code).join(', ')}`); } @@ -368,9 +370,12 @@ const QcStockInModal: React.FC = ({ handlerId : data.escalationLog?.handlerId, } console.log("Escalation Data for submission", escalationLog); + + setIsSubmitting(true); //TODO improve await postStockInLine({...qcData, escalationLog}); } else { + setIsSubmitting(true); //TODO improve await postStockInLine(qcData); } @@ -383,6 +388,7 @@ const QcStockInModal: React.FC = ({ } else { closeHandler({}, "backdropClick"); } + setIsSubmitting(false); msg("已更新來貨狀態"); return ; @@ -487,8 +493,6 @@ const QcStockInModal: React.FC = ({ // }, [pafRowSelectionModel, printQty, selectedPrinter]); }, [stockInLineInfo?.id, pafRowSelectionModel, printQty, selectedPrinter]); - const acceptQty = formProps.watch("acceptedQty") - // const checkQcIsPassed = useCallback((qcItems: PurchaseQcResult[]) => { // const isPassed = qcItems.every((qc) => qc.qcPassed); // console.log(isPassed) @@ -585,8 +589,9 @@ const QcStockInModal: React.FC = ({ color="primary" sx={{ mt: 1 }} onClick={formProps.handleSubmit(onSubmitQc, onSubmitErrorQc)} + disabled={isSubmitting || isLoading} > - {skipQc ? t("confirm") : t("confirm qc result")} + {isSubmitting ? (t("submitting")) : (skipQc ? t("confirm") : t("confirm qc result"))} )} diff --git a/src/i18n/zh/purchaseOrder.json b/src/i18n/zh/purchaseOrder.json index 6dd7d9c..5320af3 100644 --- a/src/i18n/zh/purchaseOrder.json +++ b/src/i18n/zh/purchaseOrder.json @@ -165,5 +165,6 @@ "Production Date must be earlier than Expiry Date": "生產日期必須早於到期日", "confirm expiry date": "確認到期日", "Invalid Date": "無效日期", - "Missing QC Template, please contact administrator": "找不到品檢模板,請聯絡管理員" + "Missing QC Template, please contact administrator": "找不到品檢模板,請聯絡管理員", + "submitting": "提交中..." }