| @@ -27,7 +27,7 @@ const jo: React.FC = async () => { | |||
| {t("Job Order Pickexcution")} | |||
| </Typography> | |||
| </Stack> | |||
| <I18nProvider namespaces={["jo", "common"]}> | |||
| <I18nProvider namespaces={["jo", "common", "pickOrder"]}> | |||
| <Suspense fallback={<GeneralLoading />}> | |||
| <JodetailSearch pickOrders={[]} /> | |||
| </Suspense> | |||
| @@ -467,7 +467,12 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| setOriginalCombinedData([]); | |||
| return; | |||
| } | |||
| window.dispatchEvent(new CustomEvent('jobOrderDataStatus', { | |||
| detail: { | |||
| hasData: false, | |||
| tabIndex: 0 | |||
| } | |||
| })); | |||
| // ✅ 使用 Job Order API | |||
| const jobOrderData = await fetchJobOrderLotsHierarchical(userIdToUse); | |||
| console.log("✅ Job Order data:", jobOrderData); | |||
| @@ -533,7 +538,13 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| console.log("✅ Transformed flat lot data:", flatLotData); | |||
| setCombinedLotData(flatLotData); | |||
| setOriginalCombinedData(flatLotData); | |||
| const hasData = flatLotData.length > 0; | |||
| window.dispatchEvent(new CustomEvent('jobOrderDataStatus', { | |||
| detail: { | |||
| hasData: hasData, | |||
| tabIndex: 0 | |||
| } | |||
| })); | |||
| // ✅ 计算完成状态并发送事件 | |||
| const allCompleted = flatLotData.length > 0 && flatLotData.every((lot: any) => | |||
| lot.processingStatus === 'completed' | |||
| @@ -1225,7 +1236,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| <Paper sx={{ p: 2 }}> | |||
| <Stack direction="row" spacing={4} useFlexGap flexWrap="wrap"> | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Job Order")}:</strong> {jobOrderData.pickOrder?.jobOrder?.name || '-'} | |||
| <strong>{t("Job Order")}:</strong> {jobOrderData.pickOrder?.jobOrder?.code || '-'} | |||
| </Typography> | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Pick Order Code")}:</strong> {jobOrderData.pickOrder?.code || '-'} | |||
| @@ -1233,9 +1244,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Target Date")}:</strong> {jobOrderData.pickOrder?.targetDate || '-'} | |||
| </Typography> | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Status")}:</strong> {jobOrderData.pickOrder?.status || '-'} | |||
| </Typography> | |||
| </Stack> | |||
| </Paper> | |||
| )} | |||
| @@ -419,7 +419,12 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| setOriginalCombinedData([]); | |||
| return; | |||
| } | |||
| window.dispatchEvent(new CustomEvent('jobOrderDataStatus', { | |||
| detail: { | |||
| hasData: false, | |||
| tabIndex: 1 | |||
| } | |||
| })); | |||
| // ✅ 使用 Job Order API | |||
| const jobOrderData = await fetchCompletedJobOrderPickOrders(userIdToUse); | |||
| console.log("✅ Job Order data:", jobOrderData); | |||
| @@ -485,12 +490,23 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| console.log("✅ Transformed flat lot data:", flatLotData); | |||
| setCombinedLotData(flatLotData); | |||
| setOriginalCombinedData(flatLotData); | |||
| const hasData = flatLotData.length > 0; | |||
| window.dispatchEvent(new CustomEvent('jobOrderDataStatus', { | |||
| detail: { | |||
| hasData: hasData, | |||
| tabIndex: 1 | |||
| } | |||
| })); | |||
| // ✅ 计算完成状态并发送事件 | |||
| const allCompleted = flatLotData.length > 0 && flatLotData.every((lot: any) => | |||
| lot.processingStatus === 'completed' | |||
| ); | |||
| window.dispatchEvent(new CustomEvent('pickOrderCompletionStatus', { | |||
| detail: { | |||
| allLotsCompleted: allCompleted, | |||
| tabIndex: 1 | |||
| } | |||
| })); | |||
| // ✅ 发送完成状态事件,包含标签页信息 | |||
| window.dispatchEvent(new CustomEvent('pickOrderCompletionStatus', { | |||
| detail: { | |||
| @@ -1013,9 +1029,7 @@ const paginatedData = useMemo(() => { | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Target Date")}:</strong> {jobOrderData.pickOrder?.targetDate || '-'} | |||
| </Typography> | |||
| <Typography variant="subtitle1"> | |||
| <strong>{t("Status")}:</strong> {jobOrderData.pickOrder?.status || '-'} | |||
| </Typography> | |||
| </Stack> | |||
| </Paper> | |||
| )} | |||
| @@ -58,9 +58,39 @@ const JodetailSearch: React.FC<Props> = ({ pickOrders }) => { | |||
| const [isAssigning, setIsAssigning] = useState(false); | |||
| const [unassignedOrders, setUnassignedOrders] = useState<any[]>([]); | |||
| const [isLoadingUnassigned, setIsLoadingUnassigned] = useState(false); | |||
| const [hasAssignedJobOrders, setHasAssignedJobOrders] = useState(false); | |||
| const [hasDataTab0, setHasDataTab0] = useState(false); | |||
| const [hasDataTab1, setHasDataTab1] = useState(false); | |||
| const hasAnyAssignedData = hasDataTab0 || hasDataTab1; | |||
| const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState<boolean>( | |||
| typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' | |||
| ); | |||
| useEffect(() => { | |||
| const onJobOrderDataStatus = (e: CustomEvent) => { | |||
| const { hasData, tabIndex: idx } = e.detail || {}; | |||
| if (idx === 0) setHasDataTab0(!!hasData); | |||
| if (idx === 1) setHasDataTab1(!!hasData); | |||
| }; | |||
| window.addEventListener('jobOrderDataStatus', onJobOrderDataStatus as EventListener); | |||
| return () => window.removeEventListener('jobOrderDataStatus', onJobOrderDataStatus as EventListener); | |||
| }, []); | |||
| useEffect(() => { | |||
| const handleJobOrderDataChange = (event: CustomEvent) => { | |||
| const { hasData, tabIndex: eventTabIndex } = event.detail; | |||
| // Update the state based on which tab has data | |||
| if (eventTabIndex === 0 || eventTabIndex === 1) { | |||
| setHasAssignedJobOrders(hasData); | |||
| console.log(`Job order data status for tab ${eventTabIndex}:`, hasData); | |||
| } | |||
| }; | |||
| window.addEventListener('jobOrderDataStatus', handleJobOrderDataChange as EventListener); | |||
| return () => { | |||
| window.removeEventListener('jobOrderDataStatus', handleJobOrderDataChange as EventListener); | |||
| }; | |||
| }, []); | |||
| useEffect(() => { | |||
| const onAssigned = () => { | |||
| localStorage.removeItem('hideCompletedUntilNext'); | |||
| @@ -389,7 +419,7 @@ const [isLoadingUnassigned, setIsLoadingUnassigned] = useState(false); | |||
| {/* Last 2 buttons aligned right */} | |||
| <Grid item xs={6} > | |||
| {/* Unassigned Job Orders */} | |||
| {unassignedOrders.length > 0 && ( | |||
| {!hasAnyAssignedData && unassignedOrders.length > 0 && ( | |||
| <Box sx={{ mt: 2, p: 2, border: '1px solid #e0e0e0', borderRadius: 1 }}> | |||
| <Typography variant="h6" gutterBottom> | |||
| {t("Unassigned Job Orders")} ({unassignedOrders.length}) | |||
| @@ -39,7 +39,7 @@ const LotConfirmationModal: React.FC<LotConfirmationModalProps> = ({ | |||
| scannedLot, | |||
| isLoading = false, | |||
| }) => { | |||
| const { t } = useTranslation("pickOrder"); | |||
| const { t } = useTranslation("jo"); | |||
| return ( | |||
| <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth> | |||
| @@ -26,13 +26,13 @@ | |||
| "Target Production Date" : "預計生產日期", | |||
| "Production Priority" : "生產優先度", | |||
| "Sequence" : "序", | |||
| "Item Code" : "原材料/半成品編號", | |||
| "Item Code" : "物料編號", | |||
| "Stock Available" : "倉庫可用數", | |||
| "Stock Status" : "可提料", | |||
| "Total lines: ": "所需貨品項目數量: ", | |||
| "Lines with sufficient stock: ": "可提料項目數量: ", | |||
| "Lines with insufficient stock: ": "未能提料項目數量: ", | |||
| "Item Name" : "原材料/半成品名稱", | |||
| "Item Name" : "物料名稱", | |||
| "Job Order Pickexcution": "工單提料", | |||
| "Pick Order Detail": "提料單細節", | |||
| "Finished Job Order Record": "已完成工單記錄", | |||
| @@ -80,5 +80,14 @@ | |||
| "Please scan the item qr code": "請掃描物料二維碼", | |||
| "Please make sure the qty is enough": "請確保物料數量是足夠", | |||
| "Please make sure all required items are picked": "請確保所有物料已被提取", | |||
| "Do you want to start job order": "是否開始工單" | |||
| "Do you want to start job order": "是否開始工單", | |||
| "Submit": "提交", | |||
| "issue": "問題", | |||
| "issue remark": "問題描述", | |||
| "handler": "處理者", | |||
| "qty is required": "數量是必需的", | |||
| "qty is not allowed to be greater than remaining available qty": "數量不能大於剩餘可用數量", | |||
| "qty is not allowed to be greater than required qty": "數量不能大於需求數量", | |||
| "qty is not allowed to be greater than picked qty": "數量不能大於已提料數量" | |||
| } | |||
| @@ -223,6 +223,7 @@ | |||
| "No Group": "沒有分組", | |||
| "Selected items will join above created group": "已選擇的貨品將加入以上建立的分組", | |||
| "Issue":"問題", | |||
| "issue":"問題", | |||
| "Pick Execution Issue Form":"提料問題表單", | |||
| "This form is for reporting issues only. You must report either missing items or bad items.":"此表單僅用於報告問題。您必須報告缺少的貨品或不良貨品。", | |||
| "Bad item Qty":"不良貨品數量", | |||