|
- "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<Omit<ItemsResult, "id">>;
- type SearchParamNames = keyof SearchQuery;
-
- type ItemsResultWithStatus = ItemsResult & {
- status?: "complete" | "missing";
- };
-
- const ItemsSearch: React.FC<Props> = ({ items }) => {
- const [filteredItems, setFilteredItems] = useState<ItemsResult[]>(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<SearchParamNames>[] = useMemo(() => {
- const searchCriteria: Criterion<SearchParamNames>[] = [
- { 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<ItemsResultResponse>(
- `${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<Column<ItemsResultWithStatus>[]>(
- () => [
- {
- name: "id",
- label: t("Details"),
- onClick: onDetailClick,
- buttonIcon: <EditNote />,
- 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 <Chip label={t("Complete")} color="success" size="small" />;
- } else {
- return <Chip label={t("Missing Data")} color="warning" size="small" />;
- }
- },
- },
- ],
- [onDetailClick, t, checkItemStatus],
- );
-
- const onReset = useCallback(() => {
- setFilteredItems([]);
- setFilterObj({});
- setTotalCount(0);
- }, []);
-
- return (
- <>
- <SearchBox
- criteria={searchCriteria}
- onSearch={(query) => {
- setFilterObj({
- ...query,
- });
- refetchData(query);
- }}
- onReset={onReset}
- />
- <SearchResults<ItemsResultWithStatus>
- items={filteredItems as ItemsResultWithStatus[]}
- columns={columns}
- setPagingController={setPagingController}
- pagingController={pagingController}
- totalCount={totalCount}
- isAutoPaging={false}
- />
- </>
- );
- };
-
- export default ItemsSearch;
|