"use client"; import React, { useCallback, useEffect, useState } from "react"; import { Box, Button, Card, CardContent, CardActions, Stack, Typography, Chip, CircularProgress, TablePagination, Grid, } from "@mui/material"; import { useTranslation } from "react-i18next"; import QcStockInModal from "../Qc/QcStockInModal"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; import dayjs from "dayjs"; import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; import { fetchAllJoborderProductProcessInfo, AllJoborderProductProcessInfoResponse, updateJo, fetchProductProcessesByJobOrderId, completeProductProcessLine, assignJobOrderPickOrder } from "@/app/api/jo/actions"; import { StockInLineInput } from "@/app/api/stockIn"; import { PrinterCombo } from "@/app/api/settings/printer"; import JobPickExecutionsecondscan from "../Jodetail/JobPickExecutionsecondscan"; interface ProductProcessListProps { onSelectProcess: (jobOrderId: number|undefined, productProcessId: number|undefined) => void; onSelectMatchingStock: (jobOrderId: number|undefined, productProcessId: number|undefined) => void; printerCombo: PrinterCombo[]; } const PER_PAGE = 6; const ProductProcessList: React.FC = ({ onSelectProcess, printerCombo ,onSelectMatchingStock}) => { const { t } = useTranslation( ["common", "production","purchaseOrder"]); const { data: session } = useSession() as { data: SessionWithTokens | null }; const sessionToken = session as SessionWithTokens | null; const [loading, setLoading] = useState(false); const [processes, setProcesses] = useState([]); const [page, setPage] = useState(0); const [openModal, setOpenModal] = useState(false); const [modalInfo, setModalInfo] = useState(); const currentUserId = session?.id ? parseInt(session.id) : undefined; const handleAssignPickOrder = useCallback(async (pickOrderId: number, jobOrderId?: number, productProcessId?: number) => { if (!currentUserId) { alert(t("Unable to get user ID")); return; } try { console.log("🔄 Assigning pick order:", pickOrderId, "to user:", currentUserId); // 调用分配 API 并读取响应 const assignResult = await assignJobOrderPickOrder(pickOrderId, currentUserId); console.log("📦 Assign result:", assignResult); // 检查分配是否成功 if (assignResult.message === "Successfully assigned") { console.log("✅ Successfully assigned pick order"); console.log("✅ Pick order ID:", assignResult.id); console.log("✅ Pick order code:", assignResult.code); // 分配成功后,导航到 second scan 页面 if (onSelectMatchingStock && jobOrderId) { onSelectMatchingStock(jobOrderId, productProcessId); } else { alert(t("Assignment successful")); } } else { // 分配失败 console.error("Assignment failed:", assignResult.message); alert(t(`Assignment failed: ${assignResult.message || "Unknown error"}`)); } } catch (error: any) { console.error(" Error assigning pick order:", error); alert(t(`Unknown error: ${error?.message || "Unknown error"}。Please try again later.`)); } }, [currentUserId, t, onSelectMatchingStock]); const handleViewStockIn = useCallback((process: AllJoborderProductProcessInfoResponse) => { if (!process.stockInLineId) { alert(t("Invalid Stock In Line Id")); return; } setModalInfo({ id: process.stockInLineId, //expiryDate: dayjs().add(1, "month").format(OUTPUT_DATE_FORMAT), // 视需要补 itemId、jobOrderId 等 }); setOpenModal(true); }, [t]); const fetchProcesses = useCallback(async () => { setLoading(true); try { const data = await fetchAllJoborderProductProcessInfo(); setProcesses(data || []); setPage(0); } catch (e) { console.error(e); setProcesses([]); } finally { setLoading(false); } }, []); useEffect(() => { fetchProcesses(); }, [fetchProcesses]); const handleUpdateJo = useCallback(async (process: AllJoborderProductProcessInfoResponse) => { if (!process.jobOrderId) { alert(t("Invalid Job Order Id")); return; } try { setLoading(true); // 可选:已有 loading state 可复用 // 1) 拉取该 JO 的所有 process,取出全部 lineId const processes = await fetchProductProcessesByJobOrderId(process.jobOrderId); const lineIds = (processes ?? []) .flatMap(p => (p as any).productProcessLines ?? []) .map(l => l.id) .filter(Boolean); // 2) 逐个调用 completeProductProcessLine for (const lineId of lineIds) { try { await completeProductProcessLine(lineId); } catch (e) { console.error("completeProductProcessLine failed for lineId:", lineId, e); } } // 3) 更新 JO 状态 // await updateJo({ id: process.jobOrderId, status: "completed" }); // 4) 刷新列表 await fetchProcesses(); } catch (e) { console.error(e); alert(t("An error has occurred. Please try again later.")); } finally { setLoading(false); } }, [t, fetchProcesses]); const closeNewModal = useCallback(() => { // const response = updateJo({ id: 1, status: "storing" }); setOpenModal(false); // Close the modal first fetchProcesses(); // setTimeout(() => { // }, 300); // Add a delay to avoid immediate re-trigger of useEffect }, [fetchProcesses]); const startIdx = page * PER_PAGE; const paged = processes.slice(startIdx, startIdx + PER_PAGE); return ( {loading ? ( ) : ( {t("Total processes")}: {processes.length} {paged.map((process) => { const status = String(process.status || ""); const statusLower = status.toLowerCase(); const statusColor = statusLower === "completed" ? "success" : statusLower === "in_progress" || statusLower === "processing" ? "primary" : "default"; const finishedCount = (process.lines || []).filter( (l) => String(l.status ?? "").trim().toLowerCase() === "completed" ).length; const totalCount = process.productProcessLineCount ?? process.lines?.length ?? 0; const linesWithStatus = (process.lines || []).filter( (l) => String(l.status ?? "").trim() !== "" ); const dateDisplay = process.date ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT) : "-"; const jobOrderCode = (process as any).jobOrderCode ?? (process.jobOrderId ? `JO-${process.jobOrderId}` : "N/A"); const inProgressLines = (process.lines || []) .filter(l => String(l.status ?? "").trim() !== "") .filter(l => String(l.status).toLowerCase() === "in_progress"); return ( {t("Job Order")}: {jobOrderCode} {t("Item Name")}: {process.itemCode} {process.itemName} {t("Production Priority")}: {process.productionPriority} {t("Required Qty")}: {process.requiredQty} ({process.uom}) {t("Production date")}: {process.date ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT) : "-"} {t("Assume Time Need")}: {process.timeNeedToComplete} {t("minutes")} {statusLower !== "pending" && linesWithStatus.length > 0 && ( {t("Finished lines")}: {finishedCount} / {totalCount} {inProgressLines.length > 0 && ( {inProgressLines.map(line => ( {t("Operator")}: {line.operatorName || "-"}
{t("Equipment")}: {line.equipmentName || "-"}
))}
)}
)} {statusLower == "pending" && ( {t("t")} {""} )}
{statusLower !== "completed" && ( )} {statusLower === "completed" && ( )}
); })}
{processes.length > 0 && ( setPage(p)} rowsPerPageOptions={[PER_PAGE]} /> )}
)}
); }; export default ProductProcessList;