diff --git a/src/app/api/settings/item/actions.ts b/src/app/api/settings/item/actions.ts index d74c089..1340c6e 100644 --- a/src/app/api/settings/item/actions.ts +++ b/src/app/api/settings/item/actions.ts @@ -4,7 +4,7 @@ import { serverFetchJson, serverFetchWithNoContent, } from "@/app/utils/fetchUtil"; -import { revalidateTag } from "next/cache"; +import { revalidateTag, revalidatePath } from "next/cache"; import { BASE_API_URL } from "@/config/api"; import { CreateItemResponse, RecordsRes } from "../../utils"; import { ItemQc, ItemsResult } from "."; @@ -60,6 +60,21 @@ export const saveItem = async (data: CreateItemInputs) => { return item; }; +export const deleteItem = async (id: number) => { + const response = await serverFetchJson( + `${BASE_API_URL}/items/${id}`, + { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }, + ); + + revalidateTag("items"); + revalidatePath("/(main)/settings/items"); + + return response; +}; + export interface ItemCombo { id: number, label: string, diff --git a/src/app/api/settings/item/index.ts b/src/app/api/settings/item/index.ts index a5bf7de..a30af00 100644 --- a/src/app/api/settings/item/index.ts +++ b/src/app/api/settings/item/index.ts @@ -58,6 +58,7 @@ export type ItemsResult = { area?: string | undefined; slot?: string | undefined; LocationCode?: string | undefined; + locationCode?: string | undefined; // Backend may return lowercase version isEgg?: boolean | undefined; isFee?: boolean | undefined; isBag?: boolean | undefined; diff --git a/src/components/CreateItem/CreateItemWrapper.tsx b/src/components/CreateItem/CreateItemWrapper.tsx index b3e2d6c..095eff8 100644 --- a/src/components/CreateItem/CreateItemWrapper.tsx +++ b/src/components/CreateItem/CreateItemWrapper.tsx @@ -26,7 +26,18 @@ const CreateItemWrapper: React.FC & SubComponents = async ({ id }) => { const item = result.item; qcChecks = result.qcChecks; const activeRows = qcChecks.filter((it) => it.isActive).map((i) => i.id); - console.log(qcChecks); + + // Normalize LocationCode field (handle case sensitivity from MySQL) + const locationCode = item?.LocationCode || item?.locationCode; + + console.log("Fetched item data for edit:", { + id: item?.id, + code: item?.code, + name: item?.name, + LocationCode: locationCode, + rawItem: item + }); + defaultValues = { type: item?.type, id: item?.id, @@ -44,7 +55,7 @@ const CreateItemWrapper: React.FC & SubComponents = async ({ id }) => { warehouse: item?.warehouse, area: item?.area, slot: item?.slot, - LocationCode: item?.LocationCode, + LocationCode: locationCode, isEgg: item?.isEgg, isFee: item?.isFee, isBag: item?.isBag, diff --git a/src/components/CreateItem/ProductDetails.tsx b/src/components/CreateItem/ProductDetails.tsx index 2bdda49..0903a54 100644 --- a/src/components/CreateItem/ProductDetails.tsx +++ b/src/components/CreateItem/ProductDetails.tsx @@ -23,7 +23,7 @@ import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; import InputDataGrid from "../InputDataGrid"; -import { SyntheticEvent, useCallback, useMemo, useState } from "react"; +import { SyntheticEvent, useCallback, useEffect, useMemo, useState } from "react"; import { GridColDef, GridRowModel } from "@mui/x-data-grid"; import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; import { TypeEnum } from "@/app/utils/typeEnum"; @@ -114,6 +114,13 @@ const ProductDetails: React.FC = ({ isEditMode, qcCategoryCombo, warehous onChange(value.id) }, []) + // Ensure LocationCode is set from defaultValues when component mounts + useEffect(() => { + if (initialDefaultValues?.LocationCode && !getValues("LocationCode")) { + setValue("LocationCode", initialDefaultValues.LocationCode); + } + }, [initialDefaultValues, setValue, getValues]); + return ( diff --git a/src/components/ItemsSearch/ItemsSearch.tsx b/src/components/ItemsSearch/ItemsSearch.tsx index a178cd2..f8a2487 100644 --- a/src/components/ItemsSearch/ItemsSearch.tsx +++ b/src/components/ItemsSearch/ItemsSearch.tsx @@ -13,6 +13,8 @@ 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"; +import { deleteItem } from "@/app/api/settings/item/actions"; +import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; type Props = { items: ItemsResult[]; @@ -50,8 +52,6 @@ const ItemsSearch: React.FC = ({ items }) => { [router], ); - const onDeleteClick = useCallback((item: ItemsResult) => {}, [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() !== ""; @@ -76,48 +76,6 @@ const ItemsSearch: React.FC = ({ items }) => { return "missing"; }, []); - const columns = useMemo[]>( - () => [ - { - name: "id", - label: t("Details"), - onClick: onDetailClick, - buttonIcon: , - }, - { - name: "code", - label: t("Code"), - }, - { - name: "name", - label: t("Name"), - }, - { - name: "type", - label: t("Type"), - }, - { - name: "status", - label: t("Status"), - renderCell: (item) => { - const status = item.status || checkItemStatus(item); - if (status === "complete") { - return ; - } else { - return ; - } - }, - }, - { - name: "action", - label: t(""), - buttonIcon: , - onClick: onDeleteClick, - }, - ], - [onDeleteClick, onDetailClick, t, checkItemStatus], - ); - const refetchData = useCallback( async (filterObj: SearchQuery) => { const authHeader = axiosInstance.defaults.headers["Authorization"]; @@ -134,8 +92,6 @@ const ItemsSearch: React.FC = ({ items }) => { `${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { params }, ); - console.log("API Response:", response); - console.log("First record keys:", response.data?.records?.[0] ? Object.keys(response.data.records[0]) : "No records"); if (response.status == 200) { // Normalize field names and add status to each item const itemsWithStatus: ItemsResultWithStatus[] = response.data.records.map((item: any) => { @@ -150,18 +106,12 @@ const ItemsSearch: React.FC = ({ items }) => { qcCategory: item.qcCategory || (qcCategoryId ? { id: qcCategoryId } : undefined), }; - console.log("Normalized item:", { - id: normalizedItem.id, - LocationCode: normalizedItem.LocationCode, - qcCategoryId: qcCategoryId, - qcCategory: normalizedItem.qcCategory - }); - 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 @@ -185,6 +135,64 @@ const ItemsSearch: React.FC = ({ items }) => { refetchData, ]); + const onDeleteClick = useCallback( + (item: ItemsResult) => { + deleteDialog(async () => { + if (item.id) { + const itemId = typeof item.id === "string" ? parseInt(item.id, 10) : item.id; + if (!isNaN(itemId)) { + await deleteItem(itemId); + await refetchData(filterObj); + await successDialog(t("Delete Success"), t); + } + } + }, t); + }, + [refetchData, filterObj, t], + ); + + const columns = useMemo[]>( + () => [ + { + name: "id", + label: t("Details"), + onClick: onDetailClick, + buttonIcon: , + }, + { + name: "code", + label: t("Code"), + }, + { + name: "name", + label: t("Name"), + }, + { + name: "type", + label: t("Type"), + }, + { + name: "status", + label: t("Status"), + renderCell: (item) => { + const status = item.status || checkItemStatus(item); + if (status === "complete") { + return ; + } else { + return ; + } + }, + }, + { + name: "action", + label: t(""), + buttonIcon: , + onClick: onDeleteClick, + }, + ], + [onDeleteClick, onDetailClick, t, checkItemStatus], + ); + const onReset = useCallback(() => { setFilteredItems(items); }, [items]);