From a443a00f3bb7e446fac6f61abab6a126af695899 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Thu, 16 Oct 2025 11:44:35 +0800 Subject: [PATCH] update --- .../FGPickOrderInfoCard.tsx | 101 +++++ .../FinishedGoodSearch/FinishedGoodSearch.tsx | 357 ++++++++---------- .../FinishedGoodSearch/GoodPickExecution.tsx | 294 ++------------- .../GoodPickExecutionRecord.tsx | 104 ++--- 4 files changed, 345 insertions(+), 511 deletions(-) create mode 100644 src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx diff --git a/src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx b/src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx new file mode 100644 index 0000000..3335e57 --- /dev/null +++ b/src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx @@ -0,0 +1,101 @@ +"use client"; + +import { Box, Card, CardContent, Grid, TextField, Stack } from "@mui/material"; +import { useTranslation } from "react-i18next"; +import { FGPickOrderResponse } from "@/app/api/pickOrder/actions"; + +interface Props { + fgOrder: FGPickOrderResponse; +} + +const FGPickOrderInfoCard: React.FC = ({ fgOrder }) => { + const { t } = useTranslation("pickOrder"); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default FGPickOrderInfoCard; \ No newline at end of file diff --git a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx index 2bfc6a3..1186aa3 100644 --- a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx +++ b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx @@ -63,8 +63,8 @@ const PickOrderSearch: React.FC = ({ pickOrders }) => { const [tabIndex, setTabIndex] = useState(0); const [totalCount, setTotalCount] = useState(); const [isAssigning, setIsAssigning] = useState(false); - const [summary2F, setSummary2F] = useState(null); - const [summary4F, setSummary4F] = useState(null); + // const [summary2F, setSummary2F] = useState(null); + // const [summary4F, setSummary4F] = useState(null); const [isLoadingSummary, setIsLoadingSummary] = useState(false); const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState( typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' @@ -83,6 +83,7 @@ const PickOrderSearch: React.FC = ({ pickOrders }) => { setReleasedOrderCount(0); } }, []); + /* const loadSummaries = useCallback(async () => { setIsLoadingSummary(true); try { @@ -104,6 +105,7 @@ const PickOrderSearch: React.FC = ({ pickOrders }) => { // 每30秒刷新一次 }, [loadSummaries]); + */ const handleDraft = useCallback(async () =>{ try{ if (fgPickOrdersData.length === 0) { @@ -446,11 +448,11 @@ const PickOrderSearch: React.FC = ({ pickOrders }) => { const onAssigned = () => { localStorage.removeItem('hideCompletedUntilNext'); setHideCompletedUntilNext(false); - loadSummaries(); + // loadSummaries(); }; window.addEventListener('pickOrderAssigned', onAssigned); return () => window.removeEventListener('pickOrderAssigned', onAssigned); - }, [loadSummaries]); + }, []); // ... existing code ... useEffect(() => { @@ -479,7 +481,7 @@ const PickOrderSearch: React.FC = ({ pickOrders }) => { console.log("Reset print buttons for Pick Execution Record tab"); } }, [tabIndex]); - +/* // ... existing code ... const handleAssignByLane = useCallback(async ( storeId: string, @@ -533,7 +535,7 @@ const handleAssignByLane = useCallback(async ( } }, [currentUserId, t, loadSummaries]); // ✅ Manual assignment handler - uses the action function - +*/ const handleTabChange = useCallback>( (_e, newValue) => { setTabIndex(newValue); @@ -731,216 +733,159 @@ const handleAssignByLane = useCallback(async ( return ( + {/* Header section */} - - - - - - - {t("Finished Good Order")} - - - - - {/* Last 2 buttons aligned right */} - - - {/* 2/F 楼层面板 */} - - + + + - - 2/F - - {isLoadingSummary ? ( - Loading... - ) : ( - - {summary2F?.rows.map((row, rowIdx) => ( - - - {row.truckDepartureTime} - - - {row.lanes.map((lane, laneIdx) => ( - - ))} - - - ))} - - )} - + {t("Finished Good Order")} + - {/* 4/F 楼层面板 */} - - - - 4/F - - {isLoadingSummary ? ( - Loading... - ) : ( - - {summary4F?.rows.map((row, rowIdx) => ( - - - {row.truckDepartureTime} - - - {row.lanes.map((lane, laneIdx) => ( - - ))} - - - ))} - - )} + + + + + + + + + + - {/* ✅ Updated print buttons with completion status */} - - - - - - - - - - - - - - - - + + {/* Tabs section - ✅ Move the click handler here */} ; onFgPickOrdersChange?: (fgPickOrders: FGPickOrderResponse[]) => void; @@ -963,16 +965,24 @@ const PickExecution: React.FC = ({ filterArgs, onFgPickOrdersChange }) => return ( - - {/* Search Box */} - + {/* ✅ 条件渲染:没有活动订单时显示楼层选择面板 */} + {!combinedDataLoading && fgPickOrders.length === 0 ? ( + { + if (currentUserId) { + fetchAllCombinedLotData(currentUserId); + } + }} + /> + ) : ( + // ✅ 有活动订单时,显示 FG 订单信息卡片 {fgPickOrdersLoading ? ( ) : ( - + {fgPickOrders.length === 0 ? ( @@ -980,276 +990,40 @@ const PickExecution: React.FC = ({ filterArgs, onFgPickOrdersChange }) => ) : ( + // ✅ 使用新的 FGPickOrderInfoCard 组件(类似 DoInfoCard 的格式) fgPickOrders.map((fgOrder) => ( - )) )} )} - - - - {/* - - - - - {t("All Pick Order Lots")} - - - - - - - - - - {t("Index")} - {t("Route")} - {t("Item Name")} - {t("Lot#")} - - {t("Lot Required Pick Qty")} - - {t("Lot Actual Pick Qty")} - - {t("Action")} - - - - {paginatedData.length === 0 ? ( - - - - {t("No data available")} - - - - ) : ( - paginatedData.map((lot, index) => ( - - - - {lot.routerIndex || index + 1} - - - - - {lot.routerRoute || '-'} - - - {lot.itemName} - - - - {lot.lotNo} - - - - - - {(() => { - const inQty = lot.inQty || 0; - const outQty = lot.outQty || 0; - const result = inQty - outQty; - return result.toLocaleString(); - })()} - - - - {!lot.stockOutLineId ? ( - - ) : ( - // ✅ When stockOutLineId exists, show TextField + Issue button - - { - const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; - handlePickQtyChange(lotKey, parseFloat(e.target.value) || 0); - }} - disabled={ - (lot.lotAvailability === 'expired' || - lot.lotAvailability === 'status_unavailable' || - lot.lotAvailability === 'rejected') || - lot.stockOutLineStatus === 'completed' - } - inputProps={{ - min: 0, - max: calculateRemainingRequiredQty(lot), - step: 0.01 - }} - sx={{ - width: '60px', - height: '28px', - '& .MuiInputBase-input': { - fontSize: '0.7rem', - textAlign: 'center', - padding: '6px 8px' - } - }} - placeholder="0" - /> - - - - )} - - - - - - - - - - )) - )} - - -
-
-*/} - {/* - - `${from}-${to} of ${count !== -1 ? count : `more than ${to}`}` - } - /> -
- - - + )} + + {/* Modals */} setQrModalOpen(false)} + lot={selectedLotForQr} + onQrCodeSubmit={handleQrCodeSubmit} + combinedLotData={combinedLotData} + /> + + { - setQrModalOpen(false); - setSelectedLotForQr(null); - stopScan(); - resetScan(); + setPickExecutionFormOpen(false); + setSelectedLotForExecutionForm(null); }} - lot={selectedLotForQr} - combinedLotData={combinedLotData} // ✅ Add this prop - onQrCodeSubmit={handleQrCodeSubmitFromModal} + onSubmit={handlePickExecutionFormSubmit} + selectedLot={selectedLotForExecutionForm} + selectedPickOrderLine={null} + pickOrderId={selectedLotForExecutionForm?.pickOrderId} + pickOrderCreateDate={null} /> - - - {pickExecutionFormOpen && selectedLotForExecutionForm && ( - { - setPickExecutionFormOpen(false); - setSelectedLotForExecutionForm(null); - }} - onSubmit={handlePickExecutionFormSubmit} - selectedLot={selectedLotForExecutionForm} - selectedPickOrderLine={{ - id: selectedLotForExecutionForm.pickOrderLineId, - itemId: selectedLotForExecutionForm.itemId, - itemCode: selectedLotForExecutionForm.itemCode, - itemName: selectedLotForExecutionForm.itemName, - pickOrderCode: selectedLotForExecutionForm.pickOrderCode, - // ✅ Add missing required properties from GetPickOrderLineInfo interface - availableQty: selectedLotForExecutionForm.availableQty || 0, - requiredQty: selectedLotForExecutionForm.requiredQty || 0, - uomCode: selectedLotForExecutionForm.uomCode || '', - uomDesc: selectedLotForExecutionForm.uomDesc || '', - pickedQty: selectedLotForExecutionForm.actualPickQty || 0, // ✅ Use pickedQty instead of actualPickQty - suggestedList: [] // ✅ Add required suggestedList property - }} - pickOrderId={selectedLotForExecutionForm.pickOrderId} - pickOrderCreateDate={new Date()} - /> - )} - */}
); }; diff --git a/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx b/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx index 28d0d14..5b02999 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecutionRecord.tsx @@ -270,54 +270,68 @@ const GoodPickExecutionRecord: React.FC = ({ filterArgs }) => {
- {/* FG Pick Orders 信息 */} - - {selectedDoPickOrder.fgPickOrders.map((fgOrder, index) => ( - {}} // 只读模式 - /> - ))} + {/* 订单基本信息 */} + + + {t("Order Information")} + + + {t("Shop Name")}: {selectedDoPickOrder.shopName} + + + {t("Delivery No")}: {selectedDoPickOrder.deliveryNo} + + + {t("Completed Date")}: {dayjs(selectedDoPickOrder.completedDate).format(OUTPUT_DATE_FORMAT)} + - {/* 类似 GoodPickExecution 的表格 */} - - - - - {t("Pick Order Code")} - {t("Item Code")} - {t("Item Name")} - {t("Lot No")} - {t("Location")} - {t("Required Qty")} - {t("Actual Pick Qty")} - {t("Submitted Status")} - - - - {detailLotData.map((lot, index) => ( - - {lot.pickOrderCode} - {lot.itemCode} - {lot.itemName} - {lot.lotNo} - {lot.location} - {lot.requiredQty} - {lot.actualPickQty} - - - + {/* ✅ 添加数据检查 */} + {detailLotData.length === 0 ? ( + + + {t("No lot details found for this order")} + + + ) : ( + /* 显示完成数据的表格 */ + +
+ + + {t("Pick Order Code")} + {t("Item Code")} + {t("Item Name")} + {t("Lot No")} + {t("Location")} + {t("Required Qty")} + {t("Actual Pick Qty")} + {t("Submitted Status")} - ))} - -
-
+ + + {detailLotData.map((lot, index) => ( + + {lot.pickOrderCode || 'N/A'} + {lot.itemCode || 'N/A'} + {lot.itemName || 'N/A'} + {lot.lotNo || 'N/A'} + {lot.location || 'N/A'} + {lot.requiredQty || 0} + {lot.actualPickQty || 0} + + + + + ))} + + + + )}
);