"use client"; import { PickOrderResult } from "@/app/api/pickOrder"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import SearchBox, { Criterion } from "../SearchBox"; import { flatten, intersectionWith, isEmpty, sortBy, uniqBy, upperCase, upperFirst, } from "lodash"; import { arrayToDayjs, } from "@/app/utils/formatUtil"; import { Button, Grid, Stack, Tab, Tabs, TabsProps, Typography, Box } from "@mui/material"; import PickOrders from "./FinishedGood"; import ConsolidatedPickOrders from "./ConsolidatedPickOrders"; import PickExecution from "./GoodPickExecution"; import CreatePickOrderModal from "./CreatePickOrderModal"; import NewCreateItem from "./newcreatitem"; import AssignAndRelease from "./AssignAndRelease"; import AssignTo from "./assignTo"; import { fetchAllItemsInClient, ItemCombo } from "@/app/api/settings/item/actions"; import { fetchPickOrderClient, autoAssignAndReleasePickOrder, autoAssignAndReleasePickOrderByStore, fetchReleasedDoPickOrders } from "@/app/api/pickOrder/actions"; import Jobcreatitem from "./Jobcreatitem"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; import PickExecutionDetail from "./GoodPickExecutiondetail"; import GoodPickExecutionRecord from "./GoodPickExecutionRecord"; import Swal from "sweetalert2"; import { printDN, printDNLabels } from "@/app/api/do/actions"; import { FGPickOrderResponse, fetchStoreLaneSummary, assignByLane,type StoreLaneSummary } from "@/app/api/pickOrder/actions"; import FGPickOrderCard from "./FGPickOrderCard"; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import dayjs, { Dayjs } from 'dayjs'; import FGPickOrderTicketReleaseTable from "./FGPickOrderTicketReleaseTable"; interface Props { pickOrders: PickOrderResult[]; } type SearchQuery = Partial< Omit >; type SearchParamNames = keyof SearchQuery; const PickOrderSearch: React.FC = ({ pickOrders }) => { const { t } = useTranslation("pickOrder"); const { data: session } = useSession() as { data: SessionWithTokens | null }; const currentUserId = session?.id ? parseInt(session.id) : undefined; const [isOpenCreateModal, setIsOpenCreateModal] = useState(false) const [items, setItems] = useState([]) const [printButtonsEnabled, setPrintButtonsEnabled] = useState(false); const [filteredPickOrders, setFilteredPickOrders] = useState(pickOrders); const [filterArgs, setFilterArgs] = useState>({}); const [searchQuery, setSearchQuery] = useState>({}); 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 [isLoadingSummary, setIsLoadingSummary] = useState(false); const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState( typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' ); const [fgPickOrdersData, setFgPickOrdersData] = useState([]); const [releasedOrderCount, setReleasedOrderCount] = useState(0); const fetchReleasedOrderCount = useCallback(async () => { try { const releasedOrders = await fetchReleasedDoPickOrders(); const validCount = releasedOrders.length; setReleasedOrderCount(validCount); } catch (error) { console.error("Error fetching released order count:", error); setReleasedOrderCount(0); } }, []); /* const loadSummaries = useCallback(async () => { setIsLoadingSummary(true); try { const [s2, s4] = await Promise.all([ fetchStoreLaneSummary("2/F"), fetchStoreLaneSummary("4/F") ]); setSummary2F(s2); setSummary4F(s4); } catch (error) { console.error("Error loading summaries:", error); } finally { setIsLoadingSummary(false); } }, []); useEffect(() => { loadSummaries(); // 每30秒刷新一次 }, [loadSummaries]); */ const handleDraft = useCallback(async () =>{ try{ if (fgPickOrdersData.length === 0) { console.error("No FG Pick order data available"); Swal.fire({ title: "", text: t("Please take one pick order before printing the draft."), icon: "info" }) return; } const currentFgOrder = fgPickOrdersData[0]; const printRequest = { printerId: 1, printQty: 1, isDraft: true, numOfCarton: 0, doPickOrderId: currentFgOrder.doPickOrderId }; console.log("Printing draft with request: ", printRequest); const response = await printDN(printRequest); console.log("Print Draft response: ", response); if(response.success){ Swal.fire({ position: "bottom-end", icon: "success", text: t("Printed Successfully."), showConfirmButton: false, timer: 1500 }); } else { console.error("Print failed: ", response.message); } } catch(error){ console.error("error: ", error) } },[t, fgPickOrdersData]); const handleAllDraft = useCallback(async () =>{ try { const releasedOrders = await fetchReleasedDoPickOrders(); console.log('fgPickOrdersData length:' + releasedOrders.length) if(releasedOrders.length === 0) { console.log("No released do_pick_order records found"); Swal.fire({ title: "", text: t("No released pick order records found."), icon: "info" }) return; } console.log("Found released orders:", releasedOrders); const confirmResult = await Swal.fire({ title: t("Batch Print"), text: t("Confirm print: (") + releasedOrders.length.toString() + t("piece(s))"), icon: "question", showCancelButton: true, confirmButtonText: t("Confirm"), cancelButtonText: t("Cancel"), confirmButtonColor: "#8dba00", cancelButtonColor: "#F04438" }); if (!confirmResult.isConfirmed) { return; } Swal.fire({ title: t("Printing..."), text: t("Please wait..."), allowOutsideClick: false, allowEscapeKey: false, didOpen: () => { Swal.showLoading(); } }); for (const order of releasedOrders) { const doPickOrderId = order.id console.log(`Processing order - DoPickOrder ID: ${doPickOrderId}, Ticket No: ${order.ticketNo}`); const printRequest = { printerId: 1, printQty: 1, isDraft: true, numOfCarton: 0, doPickOrderId: doPickOrderId }; console.log("Printing draft with request:", printRequest) const response = await printDN(printRequest); if(!response.success) { console.error(`Print failed for order ${order.ticketNo}:`, response.message); } } Swal.fire({ position: "bottom-end", icon: "success", text: t("Printed Successfully."), showConfirmButton: false, timer: 1500 }); } catch(error){ console.error("Error in handleAllDraft:",error); } },[t, fgPickOrdersData]); useEffect(() => { fetchReleasedOrderCount(); }, [fetchReleasedOrderCount]); useEffect(() => { const onAssigned = () => { localStorage.removeItem('hideCompletedUntilNext'); setHideCompletedUntilNext(false); // loadSummaries(); }; window.addEventListener('pickOrderAssigned', onAssigned); return () => window.removeEventListener('pickOrderAssigned', onAssigned); }, []); // ... existing code ... useEffect(() => { const handleCompletionStatusChange = (event: CustomEvent) => { const { allLotsCompleted, tabIndex: eventTabIndex } = event.detail; // ✅ 修复:根据标签页和事件来源决定是否更新打印按钮状态 if (eventTabIndex === undefined || eventTabIndex === tabIndex) { setPrintButtonsEnabled(allLotsCompleted); console.log(`Print buttons enabled for tab ${tabIndex}:`, allLotsCompleted); } }; window.addEventListener('pickOrderCompletionStatus', handleCompletionStatusChange as EventListener); return () => { window.removeEventListener('pickOrderCompletionStatus', handleCompletionStatusChange as EventListener); }; }, [tabIndex]); // ✅ 添加 tabIndex 依赖 // ✅ 新增:处理标签页切换时的打印按钮状态重置 useEffect(() => { // 当切换到标签页 2 (GoodPickExecutionRecord) 时,重置打印按钮状态 if (tabIndex === 2) { setPrintButtonsEnabled(false); console.log("Reset print buttons for Pick Execution Record tab"); } }, [tabIndex]); /* // ... existing code ... const handleAssignByLane = useCallback(async ( storeId: string, truckDepartureTime: string, truckLanceCode: string ) => { if (!currentUserId) { console.error("Missing user id in session"); return; } setIsAssigning(true); try { const res = await assignByLane(currentUserId, storeId, truckLanceCode, truckDepartureTime); if (res.code === "SUCCESS") { console.log("✅ Successfully assigned pick order from lane", truckLanceCode); window.dispatchEvent(new CustomEvent('pickOrderAssigned')); loadSummaries(); // 刷新按钮状态 } else if (res.code === "USER_BUSY") { Swal.fire({ icon: "warning", title: t("Warning"), text: t("You already have a pick order in progess. Please complete it first before taking next pick order."), confirmButtonText: t("Confirm"), confirmButtonColor: "#8dba00" }); window.dispatchEvent(new CustomEvent('pickOrderAssigned')); } else if (res.code === "NO_ORDERS") { Swal.fire({ icon: "info", title: t("Info"), text: t("No available pick order(s) for this lane."), confirmButtonText: t("Confirm"), confirmButtonColor: "#8dba00" }); } else { console.log("ℹ️ Assignment result:", res.message); } } catch (error) { console.error("❌ Error assigning by lane:", error); Swal.fire({ icon: "error", title: t("Error"), text: t("Error occurred during assignment."), confirmButtonText: t("Confirm"), confirmButtonColor: "#8dba00" }); } finally { setIsAssigning(false); } }, [currentUserId, t, loadSummaries]); // ✅ Manual assignment handler - uses the action function */ const handleTabChange = useCallback>( (_e, newValue) => { setTabIndex(newValue); }, [], ); const openCreateModal = useCallback(async () => { console.log("testing") const res = await fetchAllItemsInClient() console.log(res) setItems(res) setIsOpenCreateModal(true) }, []) const closeCreateModal = useCallback(() => { setIsOpenCreateModal(false) }, []) useEffect(() => { if (tabIndex === 3) { const loadItems = async () => { try { const itemsData = await fetchAllItemsInClient(); console.log("PickOrderSearch loaded items:", itemsData.length); setItems(itemsData); } catch (error) { console.error("Error loading items in PickOrderSearch:", error); } }; // 如果还没有数据,则加载 if (items.length === 0) { loadItems(); } } }, [tabIndex, items.length]); useEffect(() => { const handleCompletionStatusChange = (event: CustomEvent) => { const { allLotsCompleted } = event.detail; setPrintButtonsEnabled(allLotsCompleted); console.log("Print buttons enabled:", allLotsCompleted); }; window.addEventListener('pickOrderCompletionStatus', handleCompletionStatusChange as EventListener); return () => { window.removeEventListener('pickOrderCompletionStatus', handleCompletionStatusChange as EventListener); }; }, []); const searchCriteria: Criterion[] = useMemo( () => { const baseCriteria: Criterion[] = [ { label: tabIndex === 3 ? t("Item Code") : t("Code"), paramName: "code", type: "text" }, { label: t("Type"), paramName: "type", type: "autocomplete", options: tabIndex === 3 ? [ { value: "Consumable", label: t("Consumable") }, { value: "Material", label: t("Material") }, { value: "Product", label: t("Product") } ] : sortBy( uniqBy( pickOrders.map((po) => ({ value: po.type, label: t(upperCase(po.type)), })), "value", ), "label", ), }, ]; // Add Job Order search for Create Item tab (tabIndex === 3) if (tabIndex === 3) { baseCriteria.splice(1, 0, { label: t("Job Order"), paramName: "jobOrderCode" as any, // Type assertion for now type: "text", }); baseCriteria.splice(2, 0, { label: t("Target Date"), paramName: "targetDate", type: "date", }); } else { baseCriteria.splice(1, 0, { label: t("Target Date From"), label2: t("Target Date To"), paramName: "targetDate", type: "dateRange", }); } // Add Items/Item Name criteria baseCriteria.push({ label: tabIndex === 3 ? t("Item Name") : t("Items"), paramName: "items", type: tabIndex === 3 ? "text" : "autocomplete", options: tabIndex === 3 ? [] : uniqBy( flatten( sortBy( pickOrders.map((po) => po.items ? po.items.map((item) => ({ value: item.name, label: item.name, })) : [], ), "label", ), ), "value", ), }); // Add Status criteria for non-Create Item tabs if (tabIndex !== 3) { baseCriteria.push({ label: t("Status"), paramName: "status", type: "autocomplete", options: sortBy( uniqBy( pickOrders.map((po) => ({ value: po.status, label: t(upperFirst(po.status)), })), "value", ), "label", ), }); } return baseCriteria; }, [pickOrders, t, tabIndex, items], ); const fetchNewPagePickOrder = useCallback( async ( pagingController: Record, filterArgs: Record, ) => { const params = { ...pagingController, ...filterArgs, }; const res = await fetchPickOrderClient(params); if (res) { console.log(res); setFilteredPickOrders(res.records); setTotalCount(res.total); } }, [], ); const onReset = useCallback(() => { setFilteredPickOrders(pickOrders); }, [pickOrders]); useEffect(() => { if (!isOpenCreateModal) { setTabIndex(1) setTimeout(async () => { setTabIndex(0) }, 200) } }, [isOpenCreateModal]) // 添加处理提料单创建成功的函数 const handlePickOrderCreated = useCallback(() => { // 切换到 Assign & Release 标签页 (tabIndex = 1) setTabIndex(2); }, []); return ( {/* Header section */} {t("Finished Good Order")} {/* Tabs section - ✅ Move the click handler here */} {/* Content section - NO overflow: 'auto' here */} {tabIndex === 0 && } {tabIndex === 1 && } {tabIndex === 2 && } {tabIndex === 3 && } ); }; export default PickOrderSearch;