"use client"; import { Autocomplete, Box, Button, CircularProgress, FormControl, Grid, Modal, TextField, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Checkbox, TablePagination, } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { newassignPickOrder, AssignPickOrderInputs, releaseAssignedPickOrders, fetchPickOrderWithStockClient, // Add this import } from "@/app/api/pickOrder/actions"; import { fetchNameList, NameList } from "@/app/api/user/actions"; import { FormProvider, useForm, } from "react-hook-form"; import { isEmpty, upperFirst, groupBy } from "lodash"; import { OUTPUT_DATE_FORMAT, arrayToDayjs } from "@/app/utils/formatUtil"; import useUploadContext from "../UploadProvider/useUploadContext"; import dayjs from "dayjs"; import arraySupport from "dayjs/plugin/arraySupport"; import SearchBox, { Criterion } from "../SearchBox"; import { sortBy, uniqBy } from "lodash"; import { createStockOutLine, CreateStockOutLine, fetchPickOrderDetails } from "@/app/api/pickOrder/actions"; dayjs.extend(arraySupport); interface Props { filterArgs: Record; } // Update the interface to match the new API response structure interface PickOrderRow { id: string; code: string; targetDate: string; type: string; status: string; assignTo: number; groupName: string; consoCode?: string; pickOrderLines: PickOrderLineRow[]; } interface PickOrderLineRow { id: number; itemId: number; itemCode: string; itemName: string; availableQty: number | null; requiredQty: number; uomCode: string; uomDesc: string; suggestedList: any[]; } const style = { position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", bgcolor: "background.paper", pt: 5, px: 5, pb: 10, width: { xs: "100%", sm: "100%", md: "100%" }, }; const AssignTo: React.FC = ({ filterArgs }) => { const { t } = useTranslation("pickOrder"); const { setIsUploading } = useUploadContext(); const [isUploading, setIsUploadingLocal] = useState(false); // Update state to use pick order data directly const [selectedPickOrderIds, setSelectedPickOrderIds] = useState([]); const [filteredPickOrders, setFilteredPickOrders] = useState([]); const [isLoadingItems, setIsLoadingItems] = useState(false); const [pagingController, setPagingController] = useState({ pageNum: 1, pageSize: 10, }); const [totalCountItems, setTotalCountItems] = useState(); const [modalOpen, setModalOpen] = useState(false); const [usernameList, setUsernameList] = useState([]); const [searchQuery, setSearchQuery] = useState>({}); const [originalPickOrderData, setOriginalPickOrderData] = useState([]); const formProps = useForm(); const errors = formProps.formState.errors; // Update the handler functions to work with string IDs const handlePickOrderSelect = useCallback((pickOrderId: string, checked: boolean) => { if (checked) { setSelectedPickOrderIds(prev => [...prev, pickOrderId]); } else { setSelectedPickOrderIds(prev => prev.filter(id => id !== pickOrderId)); } }, []); const isPickOrderSelected = useCallback((pickOrderId: string) => { return selectedPickOrderIds.includes(pickOrderId); }, [selectedPickOrderIds]); // Update the fetch function to use the correct endpoint const fetchNewPageItems = useCallback( async (pagingController: Record, filterArgs: Record) => { setIsLoadingItems(true); try { const params = { ...pagingController, ...filterArgs, pageNum: (pagingController.pageNum || 1) - 1, pageSize: pagingController.pageSize || 10, // Filter for assigned status only status: "assigned" }; const res = await fetchPickOrderWithStockClient(params); if (res && res.records) { // Convert pick order data to the expected format const pickOrderRows: PickOrderRow[] = res.records.map((pickOrder: any) => ({ id: pickOrder.id, code: pickOrder.code, targetDate: pickOrder.targetDate, type: pickOrder.type, status: pickOrder.status, assignTo: pickOrder.assignTo, groupName: pickOrder.groupName || "No Group", consoCode: pickOrder.consoCode, pickOrderLines: pickOrder.pickOrderLines || [] })); setOriginalPickOrderData(pickOrderRows); setFilteredPickOrders(pickOrderRows); setTotalCountItems(res.total); } else { setFilteredPickOrders([]); setTotalCountItems(0); } } catch (error) { console.error("Error fetching pick orders:", error); setFilteredPickOrders([]); setTotalCountItems(0); } finally { setIsLoadingItems(false); } }, [], ); // Handle Release operation // Handle Release operation const handleRelease = useCallback(async () => { if (selectedPickOrderIds.length === 0) return; setIsUploading(true); try { // Get the assigned user from the selected pick orders const selectedPickOrders = filteredPickOrders.filter(pickOrder => selectedPickOrderIds.includes(pickOrder.id) ); // Check if all selected pick orders have the same assigned user const assignedUsers = selectedPickOrders.map(po => po.assignTo).filter(Boolean); if (assignedUsers.length === 0) { alert("Selected pick orders are not assigned to any user."); return; } const assignToValue = assignedUsers[0]; // Validate that all pick orders are assigned to the same user const allSameUser = assignedUsers.every(userId => userId === assignToValue); if (!allSameUser) { alert("All selected pick orders must be assigned to the same user."); return; } console.log("Using assigned user:", assignToValue); console.log("selectedPickOrderIds:", selectedPickOrderIds); const releaseRes = await releaseAssignedPickOrders({ pickOrderIds: selectedPickOrderIds.map(id => parseInt(id)), assignTo: assignToValue }); if (releaseRes.code === "SUCCESS") { console.log("Pick orders released successfully"); // Get the consoCode from the response const consoCode = (releaseRes.entity as any)?.consoCode; if (consoCode) { // Create StockOutLine records for each pick order line for (const pickOrder of selectedPickOrders) { for (const line of pickOrder.pickOrderLines) { try { const stockOutLineData = { consoCode: consoCode, pickOrderLineId: line.id, inventoryLotLineId: 0, // This will be set when user scans QR code qty: line.requiredQty, }; console.log("Creating stock out line:", stockOutLineData); await createStockOutLine(stockOutLineData); } catch (error) { console.error("Error creating stock out line for line", line.id, error); } } } } fetchNewPageItems(pagingController, filterArgs); } else { console.error("Release failed:", releaseRes.message); } } catch (error) { console.error("Error releasing pick orders:", error); } finally { setIsUploading(false); } }, [selectedPickOrderIds, filteredPickOrders, setIsUploading, fetchNewPageItems, pagingController, filterArgs]); // Update search criteria to match the new data structure const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Pick Order Code"), paramName: "code", type: "text", }, { label: t("Group Code"), paramName: "groupName", type: "text", }, { label: t("Target Date From"), label2: t("Target Date To"), paramName: "targetDate", type: "dateRange", }, ], [t], ); // Update search function to work with pick order data const handleSearch = useCallback((query: Record) => { setSearchQuery({ ...query }); const filtered = originalPickOrderData.filter((pickOrder) => { const pickOrderTargetDateStr = arrayToDayjs(pickOrder.targetDate); const codeMatch = !query.code || pickOrder.code?.toLowerCase().includes((query.code || "").toLowerCase()); const groupNameMatch = !query.groupName || pickOrder.groupName?.toLowerCase().includes((query.groupName || "").toLowerCase()); // Date range search let dateMatch = true; if (query.targetDate || query.targetDateTo) { try { if (query.targetDate && !query.targetDateTo) { const fromDate = dayjs(query.targetDate); dateMatch = pickOrderTargetDateStr.isSame(fromDate, 'day') || pickOrderTargetDateStr.isAfter(fromDate, 'day'); } else if (!query.targetDate && query.targetDateTo) { const toDate = dayjs(query.targetDateTo); dateMatch = pickOrderTargetDateStr.isSame(toDate, 'day') || pickOrderTargetDateStr.isBefore(toDate, 'day'); } else if (query.targetDate && query.targetDateTo) { const fromDate = dayjs(query.targetDate); const toDate = dayjs(query.targetDateTo); dateMatch = (pickOrderTargetDateStr.isSame(fromDate, 'day') || pickOrderTargetDateStr.isAfter(fromDate, 'day')) && (pickOrderTargetDateStr.isSame(toDate, 'day') || pickOrderTargetDateStr.isBefore(toDate, 'day')); } } catch (error) { console.error("Date parsing error:", error); dateMatch = true; } } return codeMatch && groupNameMatch && dateMatch; }); setFilteredPickOrders(filtered); }, [originalPickOrderData]); const handleReset = useCallback(() => { setSearchQuery({}); setFilteredPickOrders(originalPickOrderData); setTimeout(() => { setSearchQuery({}); }, 0); }, [originalPickOrderData]); // Pagination handlers const handlePageChange = useCallback((event: unknown, newPage: number) => { const newPagingController = { ...pagingController, pageNum: newPage + 1, }; setPagingController(newPagingController); }, [pagingController]); const handlePageSizeChange = useCallback((event: React.ChangeEvent) => { const newPageSize = parseInt(event.target.value, 10); const newPagingController = { pageNum: 1, pageSize: newPageSize, }; setPagingController(newPagingController); }, []); // Component mount effect useEffect(() => { fetchNewPageItems(pagingController, filterArgs || {}); }, []); // Dependencies change effect useEffect(() => { if (pagingController && (filterArgs || {})) { fetchNewPageItems(pagingController, filterArgs || {}); } }, [pagingController, filterArgs, fetchNewPageItems]); useEffect(() => { const loadUsernameList = async () => { try { const res = await fetchNameList(); if (res) { setUsernameList(res); } } catch (error) { console.error("Error loading username list:", error); } }; loadUsernameList(); }, []); // Update the table component to work with pick order data directly const CustomPickOrderTable = () => { // Helper function to get user name const getUserName = useCallback((assignToId: number | null | undefined) => { if (!assignToId) return '-'; const user = usernameList.find(u => u.id === assignToId); return user ? user.name : `User ${assignToId}`; }, [usernameList]); return ( <> {t("Selected")} {t("Pick Order Code")} {t("Group Code")} {t("Item Code")} {t("Item Name")} {t("Order Quantity")} {t("Current Stock")} {t("Stock Unit")} {t("Target Date")} {t("Assigned To")} {filteredPickOrders.length === 0 ? ( {t("No data available")} ) : ( filteredPickOrders.map((pickOrder) => ( pickOrder.pickOrderLines.map((line: PickOrderLineRow, index: number) => ( {/* Checkbox - only show for first line of each pick order */} {index === 0 ? ( handlePickOrderSelect(pickOrder.id, e.target.checked)} disabled={!isEmpty(pickOrder.consoCode)} /> ) : null} {/* Pick Order Code - only show for first line */} {index === 0 ? pickOrder.code : null} {/* Group Name - only show for first line */} {index === 0 ? pickOrder.groupName : null} {/* Item Code */} {line.itemCode} {/* Item Name */} {line.itemName} {/* Order Quantity */} {line.requiredQty} {/* Current Stock */} 0 ? "success.main" : "error.main"} sx={{ fontWeight: line.availableQty && line.availableQty > 0 ? 'bold' : 'normal' }} > {(line.availableQty || 0).toLocaleString()} {/* Unit */} {line.uomDesc} {/* Target Date - only show for first line */} {index === 0 ? ( arrayToDayjs(pickOrder.targetDate) .add(-1, "month") .format(OUTPUT_DATE_FORMAT) ) : null} {/* Assigned To - only show for first line */} {index === 0 ? ( {getUserName(pickOrder.assignTo)} ) : null} )) )) )}
`${from}-${to} of ${count !== -1 ? count : `more than ${to}`}` } /> ); }; return ( <> {isLoadingItems ? ( ) : ( )} ); }; export default AssignTo;