From f85eeaf7c36b6ced06f9799f7592179cff8eb7b2 Mon Sep 17 00:00:00 2001 From: kelvinsuen Date: Tue, 9 Sep 2025 12:59:55 +0800 Subject: [PATCH] update putaway scan --- src/app/global.css | 4 + src/components/PoDetail/PoDetail.tsx | 2 +- src/components/PoDetail/QcStockInModal.tsx | 3 +- src/components/PoDetail/StockInForm.tsx | 46 +++++--- src/components/PutAwayScan/PutAwayModal.tsx | 115 +++++++++++++++----- src/components/Swal/CustomAlerts.tsx | 3 + src/i18n/zh/purchaseOrder.json | 2 +- src/i18n/zh/putAway.json | 2 +- 8 files changed, 130 insertions(+), 47 deletions(-) diff --git a/src/app/global.css b/src/app/global.css index 7d2ff9a..8410aea 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -4,4 +4,8 @@ html, body { overscroll-behavior: none; +} + +.swal2-custom-zindex { + z-index: 10000 !important; } \ No newline at end of file diff --git a/src/components/PoDetail/PoDetail.tsx b/src/components/PoDetail/PoDetail.tsx index ea3b7d2..6836a78 100644 --- a/src/components/PoDetail/PoDetail.tsx +++ b/src/components/PoDetail/PoDetail.tsx @@ -815,7 +815,7 @@ const PoDetail: React.FC = ({ po, qc, warehouse, printerCombo }) => { {t("itemNo")} {t("itemName")} {t("qty")} - {t("processed")} + {t("processedQty")} {t("uom")} {t("receivedTotal")} {t("Stock UoM")} diff --git a/src/components/PoDetail/QcStockInModal.tsx b/src/components/PoDetail/QcStockInModal.tsx index e689a4d..4232f5d 100644 --- a/src/components/PoDetail/QcStockInModal.tsx +++ b/src/components/PoDetail/QcStockInModal.tsx @@ -26,7 +26,7 @@ import QcComponent from "./QcComponent"; import { dummyPutAwayLine, dummyQCData } from "./dummyQcTemplate"; import PutAwayForm from "./PutAwayForm"; import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; -import {submitDialogWithWarning} from "../Swal/CustomAlerts"; +import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts"; import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToInputDateString } from "@/app/utils/formatUtil"; import dayjs from "dayjs"; import { fetchPoQrcode } from "@/app/api/pdf/actions"; @@ -342,6 +342,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) } else { closeHandler({}, "backdropClick"); } + msg("已更新來貨狀態"); return ; }, diff --git a/src/components/PoDetail/StockInForm.tsx b/src/components/PoDetail/StockInForm.tsx index 96ba846..1a770f5 100644 --- a/src/components/PoDetail/StockInForm.tsx +++ b/src/components/PoDetail/StockInForm.tsx @@ -338,20 +338,38 @@ const StockInForm: React.FC = ({ disabled={true} /> - - - + {putawayMode ? ( + + sum + p.qty, 0) ?? 0} / ${itemDetail.acceptedQty}` + } + // disabled={true} + // disabled={disabled} + // error={Boolean(errors.acceptedQty)} + // helperText={errors.acceptedQty?.message} + /> + + ) : ( + + + + ) + } {/* = ({ open, onClose, warehouse, stockInLineId const [isOpenScanner, setIsOpenScanner] = useState(false); const [itemDetail, setItemDetail] = useState(); + const [putAwayQty, setPutAwayQty] = useState(0); const [unavailableText, setUnavailableText] = useState( undefined, ); const [putQty, setPutQty] = useState(itemDetail?.demandQty ?? 0); + const [verified, setVerified] = useState(false); + const [qtyError, setQtyError] = useState(""); const defaultNewValue = useMemo(() => { // console.log("%c ItemDetail", "color:purple", itemDetail); @@ -121,6 +124,7 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId (...args) => { setVerified(false); setItemDetail(undefined); + setPutAwayQty(0); onClose?.(...args); // reset(); }, @@ -153,11 +157,19 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId if (scanner.isScanning) { setIsOpenScanner(false); setVerified(true); - scanner.stopScan(); - console.log("%c Scanner stopped", "color:cyan"); + msg("貨倉掃瞄成功!") + scanner.resetScan(); + console.log("%c Scanner reset", "color:cyan"); } } }, [warehouseId]) + + // useEffect(() => { // Restart scanner for changing warehouse + // if (warehouseId > 0) { + // scanner.startScan(); + // console.log("%c Scanner restarted", "color:cyan"); + // } + // }, [isOpenScanner]) useLayoutEffect(() => { if (itemDetail !== undefined) { @@ -185,20 +197,25 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId const fetchStockInLine = useCallback( async (stockInLineId: number) => { setUnavailableText(undefined); - const res = await fetchStockInLineInfo(stockInLineId); - console.log("%c Fetched Stock In Line Info:", "color:gold", res); - setItemDetail(res); + try { + const res = await fetchStockInLineInfo(stockInLineId); + console.log("%c Fetched Stock In Line Info:", "color:gold", res); + + const totalPutAwayQty = res.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0; + setPutAwayQty(totalPutAwayQty); + setItemDetail(res); + } catch (e) { + console.log("%c Error when fetching Stock In Line: ", "color:red", e); + alert("錯誤的二維碼"); + closeHandler({}, "backdropClick"); + } }, [formProps, itemDetail, fetchStockInLineInfo], ); useEffect(() => { if (stockInLineId) { fetchStockInLine(stockInLineId); } - }, [stockInLineId]); - - const [verified, setVerified] = useState(false); - - const [qtyError, setQtyError] = useState(""); + }, [stockInLineId]); const validateQty = useCallback((qty : number = putQty) => { // if (isNaN(putQty) || putQty === undefined || putQty === null || typeof(putQty) != "number") { @@ -207,10 +224,14 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId if (!Number.isInteger(qty)) { setQtyError(t("value must be integer")); } - if (qty > itemDetail?.acceptedQty!!) { + if (qty > itemDetail?.acceptedQty!! - putAwayQty) { setQtyError(`${t("putQty must not greater than")} ${ - itemDetail?.acceptedQty}` ); - } else + itemDetail?.acceptedQty!! - putAwayQty}` ); + } else + // if (qty > itemDetail?.acceptedQty!!) { + // setQtyError(`${t("putQty must not greater than")} ${ + // itemDetail?.acceptedQty}` ); + // } else if (qty < 1) { setQtyError(t("minimal value is 1")); } else { @@ -303,7 +324,7 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId - + = ({ open, onClose, warehouse, stockInLineId {verified? ( <> - + 掃瞄完成 ) : ( <> - + 請掃瞄倉庫二維碼 @@ -338,8 +359,8 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId - {`${warehouseId > 0 ? warehouse.find((w) => w.id == warehouseId)?.name - : warehouse.find((w) => w.id == 3)?.name}`} + {warehouseId > 0 ? `${warehouse.find((w) => w.id == warehouseId)?.name}` + : `${warehouse.find((w) => w.id == 1)?.name} (預設)`} @@ -351,13 +372,40 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId type="number" // TODO fix the "e" input label={t("putQty")} fullWidth - sx={{fontSize: "25px", height: "100%"}} - defaultValue={itemDetail.demandQty} + sx={{ + "& .MuiInputBase-input": { + padding: "20px 14px 5px", + fontSize: "50px", + fontWeight: "bold", + }, + "& .MuiInputBase-root": { + height: "100%", + borderColor: "black", + }, + "& .MuiInputLabel-root": { + fontSize: "30px", + top: "-5px", + color: "black", + }, + "& .MuiFormHelperText-root": { + fontSize: "20px", + marginTop: "8px", + lineHeight: "1.2", + }, + }} + defaultValue={itemDetail?.acceptedQty!! - putAwayQty} + // defaultValue={itemDetail.demandQty} onChange={(e) => { const value = e.target.value; validateQty(Number(value)); setPutQty(Number(value)); }} + onKeyDown={(e) => { + // Prevent non-numeric characters + if (["e", "E", "+", "-", "."].includes(e.key)) { + e.preventDefault(); + } + }} // onBlur={(e) => { // const value = e.target.value; // setPutQty(Number(value)); @@ -375,7 +423,7 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId = ({ open, onClose, warehouse, stockInLineId type="submit" variant="contained" startIcon={} - color="primary" - // sx={{ mx: 3, minWidth: "120px", height: "120px", - // padding: "12px 12px", fontSize: "24px"}} + color="secondary" sx={{ + height: "100%", flex: "0 0 auto", padding: "8px 16px", - fontSize: { xs: "16px", sm: "20px", md: "24px" }, + fontSize: { xs: "20px", sm: "24px", md: "30px" }, whiteSpace: "nowrap", - textAlign: "center",}} + textAlign: "center", + border: "3px solid", // Add outline + borderColor: "blue", + "&:hover": { + borderColor: "grey.200", // Slightly different color on hover + backgroundColor: "secondary.dark", // Darker background on hover + }, + "&:disabled": { + borderColor: "grey.400", // Visible outline even when disabled + opacity: 0.7, // Slightly faded but still visible + }, + }} // onClick={formProps.handleSubmit()} - disabled={!verified} + disabled={!verified || qtyError != ""} > {t("confirm putaway")} @@ -435,7 +493,6 @@ const PutAwayModal: React.FC = ({ open, onClose, warehouse, stockInLineId )} - { toast.onmouseenter = Swal.stopTimer; toast.onmouseleave = Swal.resumeTimer; }, + customClass: { + container: 'swal2-custom-zindex', + }, }).fire({ icon: "success", title: title, diff --git a/src/i18n/zh/purchaseOrder.json b/src/i18n/zh/purchaseOrder.json index c4ba915..0b70b33 100644 --- a/src/i18n/zh/purchaseOrder.json +++ b/src/i18n/zh/purchaseOrder.json @@ -43,7 +43,7 @@ "total weight": "總重量", "weight unit": "重量單位", "price": "訂單貨值", - "processed": "已上架數量", + "processedQty": "已上架數量", "expiryDate": "到期日", "acceptedQty": "是次來貨數量", "putawayQty": "上架數量", diff --git a/src/i18n/zh/putAway.json b/src/i18n/zh/putAway.json index 369aee3..3cbb98b 100644 --- a/src/i18n/zh/putAway.json +++ b/src/i18n/zh/putAway.json @@ -9,7 +9,7 @@ "Please scan warehouse qr code": "請掃瞄倉庫二維碼", "scan loading": "載入中,請稍候…", "warehouse": "倉庫", - "putQty": "上架數量", + "putQty": "是次上架數量", "minimal value is 1": "最小為1", "putQty must not greater than": "上架數量不得大於", "value must be integer": "必須是整數",