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