"use client"; import SearchBox, { Criterion } from "../SearchBox"; import { useCallback, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import SearchResults, { Column } from "../SearchResults/index"; import { SessionWithTokens } from "@/config/authConfig"; import { batchSubmitBadItem, batchSubmitExpiryItem, batchSubmitMissItem, ExpiryItemResult, StockIssueLists, StockIssueResult, submitBadItem, submitExpiryItem, submitMissItem, } from "@/app/api/stockIssue/actions"; import { Box, Button, Tab, Tabs } from "@mui/material"; import { useSession } from "next-auth/react"; interface Props { dataList: StockIssueLists; } type SearchQuery = { lotNo: string; }; type SearchParamNames = keyof SearchQuery; const SearchPage: React.FC = ({ dataList }) => { const { t } = useTranslation("inventory"); const [tab, setTab] = useState<"miss" | "bad" | "expiry">("miss"); const [search, setSearch] = useState({ lotNo: "" }); const { data: session } = useSession() as { data: SessionWithTokens | null }; const currentUserId = session?.id ? parseInt(session.id) : undefined; const [missItems, setMissItems] = useState( dataList.missItems, ); const [badItems, setBadItems] = useState( dataList.badItems, ); const [expiryItems, setExpiryItems] = useState( dataList.expiryItems, ); const [selectedIds, setSelectedIds] = useState<(string | number)[]>([]); const [submittingIds, setSubmittingIds] = useState>(new Set()); const [batchSubmitting, setBatchSubmitting] = useState(false); const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Lot No."), paramName: "lotNo", type: "text", }, ], [t], ); const filterBySearch = useCallback( (items: T[]): T[] => { if (!search.lotNo) return items; const keyword = search.lotNo.toLowerCase(); return items.filter( (i) => i.lotNo && i.lotNo.toLowerCase().includes(keyword), ); }, [search.lotNo], ); const handleSubmitSingle = useCallback( async (id: number) => { if (!currentUserId) { alert(t("User ID is required")); return; } setSubmittingIds((prev) => new Set(prev).add(id)); try { if (tab === "miss") { await submitMissItem(id, currentUserId); setMissItems((prev) => prev.filter((i) => i.id !== id)); } else if (tab === "bad") { await submitBadItem(id, currentUserId); setBadItems((prev) => prev.filter((i) => i.id !== id)); } else { await submitExpiryItem(id, currentUserId); setExpiryItems((prev) => prev.filter((i) => i.id !== id)); } // Remove from selectedIds if it was selected setSelectedIds((prev) => prev.filter((selectedId) => selectedId !== id)); } catch (error) { console.error("Failed to submit item:", error); alert(`Failed to submit: ${error instanceof Error ? error.message : "Unknown error"}`); } finally { setSubmittingIds((prev) => { const newSet = new Set(prev); newSet.delete(id); return newSet; }); } }, [tab, currentUserId, t], ); const handleSubmitSelected = useCallback(async () => { if (!currentUserId) return; // Get all IDs from the current tab's filtered items let allIds: number[] = []; if (tab === "miss") { const items = filterBySearch(missItems); allIds = items.map((item) => item.id); } else if (tab === "bad") { const items = filterBySearch(badItems); allIds = items.map((item) => item.id); } else { const items = filterBySearch(expiryItems); allIds = items.map((item) => item.id); } if (allIds.length === 0) return; setBatchSubmitting(true); try { if (tab === "miss") { await batchSubmitMissItem(allIds, currentUserId); setMissItems((prev) => prev.filter((i) => !allIds.includes(i.id))); } else if (tab === "bad") { await batchSubmitBadItem(allIds, currentUserId); setBadItems((prev) => prev.filter((i) => !allIds.includes(i.id))); } else { await batchSubmitExpiryItem(allIds, currentUserId); setExpiryItems((prev) => prev.filter((i) => !allIds.includes(i.id))); } setSelectedIds([]); } catch (error) { console.error("Failed to submit selected items:", error); alert(`Failed to submit: ${error instanceof Error ? error.message : "Unknown error"}`); } finally { setBatchSubmitting(false); } }, [tab, currentUserId, missItems, badItems, expiryItems, filterBySearch]); const missColumns = useMemo[]>( () => [ { name: "itemCode", label: t("Item Code") }, { name: "itemDescription", label: t("Item") }, { name: "lotNo", label: t("Lot No.") }, { name: "storeLocation", label: t("Location") }, { name: "missQty", label: t("Miss Qty") }, { name: "id", label: t("Action"), renderCell: (item) => ( ), }, ], [t, handleSubmitSingle, submittingIds, currentUserId], ); const badColumns = useMemo[]>( () => [ { name: "itemCode", label: t("Item Code") }, { name: "itemDescription", label: t("Item") }, { name: "lotNo", label: t("Lot No.") }, { name: "storeLocation", label: t("Location") }, { name: "badItemQty", label: t("Defective Qty") }, { name: "id", label: t("Action"), renderCell: (item) => ( ), }, ], [t, handleSubmitSingle, submittingIds, currentUserId], ); const expiryColumns = useMemo[]>( () => [ { name: "itemCode", label: t("Item Code") }, { name: "itemDescription", label: t("Item") }, { name: "lotNo", label: t("Lot No.") }, { name: "storeLocation", label: t("Location") }, { name: "expiryDate", label: t("Expiry Date") }, { name: "remainingQty", label: t("Remaining Qty") }, { name: "id", label: t("Action"), renderCell: (item) => ( ), }, ], [t, handleSubmitSingle, submittingIds, currentUserId], ); const handleSearch = useCallback((query: Record) => { setSearch(query); }, []); const handleTabChange = useCallback( (_: React.SyntheticEvent, value: string) => { setTab(value as "miss" | "bad" | "expiry"); setSelectedIds([]); }, [], ); const renderCurrentTab = () => { if (tab === "miss") { const items = filterBySearch(missItems); return ( items={items} columns={missColumns} pagingController={{ pageNum: 1, pageSize: 10 }} checkboxIds={selectedIds} setCheckboxIds={setSelectedIds} /> ); } if (tab === "bad") { const items = filterBySearch(badItems); return ( items={items} columns={badColumns} pagingController={{ pageNum: 1, pageSize: 10 }} checkboxIds={selectedIds} setCheckboxIds={setSelectedIds} /> ); } const items = filterBySearch(expiryItems); return ( items={items} columns={expiryColumns} pagingController={{ pageNum: 1, pageSize: 10 }} checkboxIds={selectedIds} setCheckboxIds={setSelectedIds} /> ); }; return ( criteria={searchCriteria} onSearch={handleSearch} /> {renderCurrentTab()} ); }; export default SearchPage;