"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import SearchBox, { Criterion } from "../SearchBox"; import { ItemsResult, ItemsResultResponse } from "@/app/api/settings/item"; import { useTranslation } from "react-i18next"; import SearchResults, { Column } from "../SearchResults"; import { EditNote } from "@mui/icons-material"; import { useRouter, useSearchParams } from "next/navigation"; import { Chip } from "@mui/material"; import { TypeEnum } from "@/app/utils/typeEnum"; import axios from "axios"; import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api"; import axiosInstance from "@/app/(main)/axios/axiosInstance"; type Props = { items: ItemsResult[]; }; type SearchQuery = Partial>; type SearchParamNames = keyof SearchQuery; type ItemsResultWithStatus = ItemsResult & { status?: "complete" | "missing"; }; const ItemsSearch: React.FC = ({ items }) => { const [filteredItems, setFilteredItems] = useState(items); const { t } = useTranslation("items"); const router = useRouter(); const [filterObj, setFilterObj] = useState({}); const [pagingController, setPagingController] = useState({ pageNum: 1, pageSize: 10, // totalCount: 0, }); const [totalCount, setTotalCount] = useState(0); const searchCriteria: Criterion[] = useMemo(() => { const searchCriteria: Criterion[] = [ { label: t("Code"), paramName: "code", type: "text" }, { label: t("Name"), paramName: "name", type: "text" }, ]; return searchCriteria; }, [t]); const onDetailClick = useCallback( (item: ItemsResult) => { router.push(`/settings/items/edit?id=${item.id}`); }, [router], ); const checkItemStatus = useCallback((item: ItemsResult): "complete" | "missing" => { // Check if type exists and is not empty const hasType = item.type != null && String(item.type).trim() !== ""; // Check if qcCategory exists (can be object or id) - handle case sensitivity const itemAny = item as any; const hasQcCategory = item.qcCategory != null || itemAny.qcCategoryId != null || itemAny.qcCategoryid != null || itemAny.qccategoryid != null; // Check if LocationCode exists and is not empty - handle case sensitivity const hasLocationCode = (item.LocationCode != null && String(item.LocationCode).trim() !== "") || (itemAny.LocationCode != null && String(itemAny.LocationCode).trim() !== "") || (itemAny.locationCode != null && String(itemAny.locationCode).trim() !== "") || (itemAny.locationcode != null && String(itemAny.locationcode).trim() !== ""); // If all three are present, return "complete", otherwise "missing" if (hasType && hasQcCategory && hasLocationCode) { return "complete"; } return "missing"; }, []); const refetchData = useCallback( async (filterObj: SearchQuery) => { const authHeader = axiosInstance.defaults.headers["Authorization"]; if (!authHeader) { return; // Exit the function if the token is not set } const params = { pageNum: pagingController.pageNum, pageSize: pagingController.pageSize, ...filterObj, }; try { const response = await axiosInstance.get( `${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { params }, ); if (response.status == 200) { // Normalize field names and add status to each item const itemsWithStatus: ItemsResultWithStatus[] = response.data.records.map((item: any) => { // Normalize field names (handle case sensitivity from MySQL) // Check all possible case variations const locationCode = item.LocationCode || item.locationCode || item.locationcode || item.Locationcode || item.Location_Code || item.location_code; const qcCategoryId = item.qcCategoryId || item.qcCategoryid || item.qccategoryid || item.QcCategoryId || item.qc_category_id; const normalizedItem: ItemsResult = { ...item, LocationCode: locationCode, qcCategory: item.qcCategory || (qcCategoryId ? { id: qcCategoryId } : undefined), }; return { ...normalizedItem, status: checkItemStatus(normalizedItem), }; }); console.log("Fetched items data:", itemsWithStatus); setFilteredItems(itemsWithStatus as ItemsResult[]); setTotalCount(response.data.total); return response; // Return the data from the response } else { throw "400"; } } catch (error) { console.error("Error fetching items:", error); throw error; // Rethrow the error for further handling } }, [pagingController.pageNum, pagingController.pageSize, checkItemStatus], ); useEffect(() => { // Only refetch when paging changes AND we have already searched (filterObj has been set by search) if (Object.keys(filterObj).length > 0 || filteredItems.length > 0) { refetchData(filterObj); } }, [ pagingController.pageNum, pagingController.pageSize, ]); const columns = useMemo[]>( () => [ { name: "id", label: t("Details"), onClick: onDetailClick, buttonIcon: , sx: { width: 80 }, }, { name: "code", label: t("Code"), sx: { width: 150 }, }, { name: "name", label: t("Name"), sx: { width: 250 }, }, { name: "LocationCode", label: t("LocationCode"), sx: { width: 150 }, }, { name: "type", label: t("Type"), sx: { width: 120 }, }, { name: "status", label: t("Status"), align: "center", headerAlign: "center", sx: { width: 120 }, renderCell: (item) => { const status = item.status || checkItemStatus(item); if (status === "complete") { return ; } else { return ; } }, }, ], [onDetailClick, t, checkItemStatus], ); const onReset = useCallback(() => { setFilteredItems([]); setFilterObj({}); setTotalCount(0); }, []); return ( <> { setFilterObj({ ...query, }); refetchData(query); }} onReset={onReset} /> items={filteredItems as ItemsResultWithStatus[]} columns={columns} setPagingController={setPagingController} pagingController={pagingController} totalCount={totalCount} isAutoPaging={false} /> ); }; export default ItemsSearch;