From 6ee3a96bacbb5bfbcb63c9d794f972fdbacd3b9e Mon Sep 17 00:00:00 2001 From: "MSI\\derek" Date: Tue, 17 Jun 2025 17:34:16 +0800 Subject: [PATCH] UPDATE --- src/app/api/po/actions.ts | 15 +++ src/components/PoDetail/PoDetail.tsx | 2 +- src/components/PoDetail/PoInputGrid.tsx | 28 ++--- src/components/PoDetail/PutawayForm.tsx | 20 +++- src/components/PoDetail/QrModal.tsx | 102 +++++++++------- src/components/PoSearch/PoSearch.tsx | 148 ++++++++++++++---------- src/i18n/zh/purchaseOrder.json | 1 + 7 files changed, 195 insertions(+), 121 deletions(-) diff --git a/src/app/api/po/actions.ts b/src/app/api/po/actions.ts index 6dab3f3..fbc48a6 100644 --- a/src/app/api/po/actions.ts +++ b/src/app/api/po/actions.ts @@ -140,3 +140,18 @@ export const fetchPoInClient = cache(async (id: number) => { } }); + export const testing = cache(async (queryParams?: Record) => { + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + return serverFetchJson>(`${BASE_API_URL}/po/testing?${queryString}`, { + method: 'GET', + next: { tags: ["po"] }, + }); + } else { + return serverFetchJson>(`${BASE_API_URL}/po/testing`, { + method: 'GET', + next: { tags: ["po"] }, + }); + } + }); + diff --git a/src/components/PoDetail/PoDetail.tsx b/src/components/PoDetail/PoDetail.tsx index eba9ef7..8721824 100644 --- a/src/components/PoDetail/PoDetail.tsx +++ b/src/components/PoDetail/PoDetail.tsx @@ -295,7 +295,7 @@ const PoDetail: React.FC = ({ po, qc, warehouse }) => { color={buttonData.buttonColor as ButtonProps["color"]} startIcon={buttonData.buttonIcon} > - {t(buttonData.buttonText)} + {buttonData.buttonText} {/* {purchaseOrder.status.toLowerCase() === "pending" && ( diff --git a/src/components/PoDetail/PoInputGrid.tsx b/src/components/PoDetail/PoInputGrid.tsx index baa44d9..68e1a59 100644 --- a/src/components/PoDetail/PoInputGrid.tsx +++ b/src/components/PoDetail/PoInputGrid.tsx @@ -510,20 +510,20 @@ function PoInputGrid({ color="inherit" key="edit" />, - } - label="putaway" - sx={{ - color: "primary.main", - // marginRight: 1, - }} - disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] !== 8} - // set _isNew to false after posting - // or check status - onClick={handleQrCode(params.row.id, params)} - color="inherit" - key="edit" - />, + // } + // label="putaway" + // sx={{ + // color: "primary.main", + // // marginRight: 1, + // }} + // disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] !== 8} + // // set _isNew to false after posting + // // or check status + // onClick={handleQrCode(params.row.id, params)} + // color="inherit" + // key="edit" + // />, = 1 ? ( diff --git a/src/components/PoDetail/PutawayForm.tsx b/src/components/PoDetail/PutawayForm.tsx index 71a0bb8..8884c5f 100644 --- a/src/components/PoDetail/PutawayForm.tsx +++ b/src/components/PoDetail/PutawayForm.tsx @@ -237,6 +237,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { useEffect(() => { setValue("status", "completed"); + setValue("warehouseId", options[0].value); }, []); useEffect(() => { @@ -245,7 +246,16 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { clearErrors("warehouseId") } }, [warehouseId]); - + + const getWarningTextHardcode = useCallback((): string | undefined => { + const defaultWarehouseId = options[0].value + const currWarehouseId = watch("warehouseId") + if (defaultWarehouseId !== currWarehouseId) { + return t("not default warehosue") + } + return undefined + }, [options]) + return ( @@ -331,7 +341,7 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { disableClearable disabled fullWidth - defaultValue={options.find((o) => o.value === 1)} /// modify this later + defaultValue={options[0]} /// modify this later // onChange={onChange} getOptionLabel={(option) => option.label} options={options} @@ -396,6 +406,8 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { // value={warehouseId > 0 // ? options.find((o) => o.value === warehouseId) // : undefined} + defaultValue={options[0]} + // defaultValue={options.find((o) => o.value === 1)} value={currentValue} onChange={onChange} getOptionLabel={(option) => option.label} @@ -406,7 +418,9 @@ const PutawayForm: React.FC = ({ itemDetail, warehouse, disabled }) => { // label={"Select warehouse"} disabled={disabled} error={Boolean(errors.warehouseId?.message)} - helperText={errors.warehouseId?.message} + helperText={errors.warehouseId?.message ?? + getWarningTextHardcode() + } // helperText={warehouseHelperText} /> )} diff --git a/src/components/PoDetail/QrModal.tsx b/src/components/PoDetail/QrModal.tsx index bd72ab8..6c43612 100644 --- a/src/components/PoDetail/QrModal.tsx +++ b/src/components/PoDetail/QrModal.tsx @@ -1,6 +1,14 @@ "use client"; -import { Box, Button, Grid, Modal, ModalProps, Stack, Typography } from "@mui/material"; +import { + Box, + Button, + Grid, + Modal, + ModalProps, + Stack, + Typography, +} from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; import ReactQrCodeScanner, { ScannerConfig, @@ -74,18 +82,18 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { ); // QR Code Scanner - const scanner = useQcCodeScanner() + const scanner = useQcCodeScanner(); useEffect(() => { if (open && !scanner.isScanning) { - scanner.startScan() + scanner.startScan(); } else if (!open && scanner.isScanning) { - scanner.stopScan() + scanner.stopScan(); } - }, [open]) + }, [open]); useEffect(() => { if (scanner.values.length > 0 && !Boolean(itemDetail)) { - console.log(scanner.values[0]) + console.log(scanner.values[0]); const data: QrCodeInfo = JSON.parse(scanner.values[0]); console.log(data); if (data.stockInLineId) { @@ -93,28 +101,29 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { console.log(data.stockInLineId); setStockInLineId(data.stockInLineId); } - scanner.resetScan() + scanner.resetScan(); } - }, [scanner.values]) + }, [scanner.values]); const [itemDetail, setItemDetail] = useState(); const [disabledSubmit, setDisabledSubmit] = useState(false); - const [unavailableText, setUnavailableText] = useState(undefined) + const [unavailableText, setUnavailableText] = useState(undefined); + const fetchStockInLine = useCallback( async (stockInLineId: number) => { - setUnavailableText(undefined) + setUnavailableText(undefined); const res = await fetchStockInLineInfo(stockInLineId); if (res.status.toLowerCase() === "received") { - console.log(res.acceptedQty) - formProps.setValue("acceptedQty", res.acceptedQty) - setDisabledSubmit(false) + console.log(res.acceptedQty); + formProps.setValue("acceptedQty", res.acceptedQty); + setDisabledSubmit(false); setItemDetail(res); } else if (res.status.toLowerCase() === "completed") { - setDisabledSubmit(true) + setDisabledSubmit(true); } else { // - setUnavailableText("Item Not Available") - setDisabledSubmit(true) + setUnavailableText("Item Not Available"); + setDisabledSubmit(true); } // return }, @@ -156,13 +165,13 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { setServerError(t("An error has occurred. Please try again later.")); return false; } - return; + // return; const res = await updateStockInLine(args); if (Boolean(res.id)) { // update entries console.log(res); // add loading - // closeHandler({}, "backdropClick"); + closeHandler({}, "backdropClick"); } console.log(res); // if (res) @@ -185,32 +194,39 @@ const QrModal: React.FC = ({ open, onClose, warehouse }) => { > - { - itemDetail != undefined ? ( - unavailableText != undefined ? {unavailableText} - : ( - <> - - - - - - - ) + {itemDetail != undefined ? ( + unavailableText != undefined ? ( + + {unavailableText} + + ) : ( + <> + + + + + ) - : ( - // - {t("Will start binding procedure after scanning item qr code.")} - ) - } + ) : ( + // + + {t( + "Will start binding procedure after scanning item qr code." + )} + + )} diff --git a/src/components/PoSearch/PoSearch.tsx b/src/components/PoSearch/PoSearch.tsx index 965f3b3..b9f95fd 100644 --- a/src/components/PoSearch/PoSearch.tsx +++ b/src/components/PoSearch/PoSearch.tsx @@ -10,10 +10,14 @@ import { EditNote } from "@mui/icons-material"; import { Button, Grid, Tab, Tabs, TabsProps, Typography } from "@mui/material"; import QrModal from "../PoDetail/QrModal"; import { WarehouseResult } from "@/app/api/warehouse"; -import NotificationIcon from '@mui/icons-material/NotificationImportant'; +import NotificationIcon from "@mui/icons-material/NotificationImportant"; import { useSession } from "next-auth/react"; import { defaultPagingController } from "../SearchResults/SearchResults"; -import { fetchPoListClient } from "@/app/api/po/actions"; +import { fetchPoListClient, testing } from "@/app/api/po/actions"; +import dayjs from "dayjs"; +import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; +import arraySupport from "dayjs/plugin/arraySupport"; +dayjs.extend(arraySupport); type Props = { po: PoResult[]; @@ -24,23 +28,39 @@ type SearchQuery = Partial>; type SearchParamNames = keyof SearchQuery; // cal offset (pageSize) -// cal limit (pageSize) -const PoSearch: React.FC = ({ po, warehouse, totalCount: initTotalCount }) => { +// cal limit (pageSize) +const PoSearch: React.FC = ({ + po, + warehouse, + totalCount: initTotalCount, +}) => { const [filteredPo, setFilteredPo] = useState(po); + const [filterArgs, setFilterArgs] = useState>({}); const { t } = useTranslation("purchaseOrder"); const router = useRouter(); - const [pagingController, setPagingController] = useState(defaultPagingController) - const [totalCount, setTotalCount] = useState(initTotalCount) + const [pagingController, setPagingController] = useState( + defaultPagingController + ); + const [totalCount, setTotalCount] = useState(initTotalCount); const searchCriteria: Criterion[] = useMemo(() => { var searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, - { label: t("Status"), paramName: "status", type: "select", options: ["PENDING", "RECEIVING", "COMPLETED"] }, - { label: t("Escalated"), paramName: "escalated", type: "select", options: [t("Escalated"), t("NotEscalated")] }, + { + label: t("Status"), + paramName: "status", + type: "select", + options: [t(`pending`), t(`receiving`), t(`completed`)], + }, + { + label: t("Escalated"), + paramName: "escalated", + type: "select", + options: [t("Escalated"), t("NotEscalated")], + }, ]; return searchCriteria; }, [t, po]); - const onDetailClick = useCallback( (po: PoResult) => { router.push(`/po/edit?id=${po.id}`); @@ -65,6 +85,11 @@ const PoSearch: React.FC = ({ po, warehouse, totalCount: initTotalCount } { name: "orderDate", label: t("OrderDate"), + renderCell: (params) => { + return dayjs(params.orderDate) + .add(-1, "month") + .format(OUTPUT_DATE_FORMAT); + }, }, { name: "supplier", @@ -73,13 +98,18 @@ const PoSearch: React.FC = ({ po, warehouse, totalCount: initTotalCount } { name: "status", label: t("Status"), + renderCell: (params) => { + return t(`${params.status.toLowerCase()}`); + }, }, { name: "escalated", label: t("Escalated"), renderCell: (params) => { - return params.escalated ? : undefined - } + return params.escalated ? ( + + ) : undefined; + }, }, // { // name: "name", @@ -108,17 +138,30 @@ const PoSearch: React.FC = ({ po, warehouse, totalCount: initTotalCount } setOpenScanner(false); }, []); - const newPageFetch = useCallback(async (pagingController: Record) => { - const res = await fetchPoListClient(pagingController) - if (res) { - setFilteredPo(res.records) - setTotalCount(res.total) - } - }, [fetchPoListClient, pagingController]) + const newPageFetch = useCallback( + async ( + pagingController: Record, + filterArgs: Record + ) => { + console.log(pagingController); + const params = { + ...pagingController, + ...filterArgs, + }; + // const res = await fetchPoListClient(params); + const res = await testing(params); + if (res) { + console.log(res.records); + setFilteredPo(res.records); + setTotalCount(res.total); + } + }, + [fetchPoListClient, pagingController] + ); useEffect(() => { - newPageFetch(pagingController) - }, [newPageFetch, pagingController]) + newPageFetch(pagingController, filterArgs); + }, [newPageFetch, pagingController, filterArgs]); return ( <> @@ -127,47 +170,32 @@ const PoSearch: React.FC = ({ po, warehouse, totalCount: initTotalCount } {t("Purchase Order")} - - - - - - <> - { - setFilteredPo((prev) => - prev.filter((p) => { - return ( - p.code.toLowerCase().includes(query.code.toLowerCase()) && - (query.status === "All" || p.status === query.status) && - (query.escalated === "All" || p.escalated === (query.escalated === t("Escalated"))) - ) - }) - ); - }} - onReset={onReset} + + - - items={filteredPo} - columns={columns} - pagingController={pagingController} - setPagingController={setPagingController} - totalCount={totalCount} - isAutoPaging={false} - /> - - + + + + <> + { + setFilterArgs({ ...query }); + }} + onReset={onReset} + /> + + items={filteredPo} + columns={columns} + pagingController={pagingController} + setPagingController={setPagingController} + totalCount={totalCount} + isAutoPaging={false} + /> + ); }; diff --git a/src/i18n/zh/purchaseOrder.json b/src/i18n/zh/purchaseOrder.json index d01501b..ffe8283 100644 --- a/src/i18n/zh/purchaseOrder.json +++ b/src/i18n/zh/purchaseOrder.json @@ -6,6 +6,7 @@ "Supplier": "供應商", "Status": "狀態", "Escalated": "已上報", + "NotEscalated": "無上報", "Do you want to start?": "確定開始嗎?", "Start": "開始",