"use client"; import { useState, useCallback, useEffect, useMemo, useRef } from "react"; import { apiClient } from "@/lib/api/client"; import { ItemRoutingConfig, ItemData, RoutingVersionData, RoutingDetailData } from "../types"; import { defaultConfig } from "../config"; const API_BASE = "/process-work-standard"; export function useItemRouting(configPartial: Partial) { const configKey = useMemo( () => JSON.stringify(configPartial), [configPartial] ); const config: ItemRoutingConfig = useMemo(() => ({ ...defaultConfig, ...configPartial, dataSource: { ...defaultConfig.dataSource, ...configPartial?.dataSource }, modals: { ...defaultConfig.modals, ...configPartial?.modals }, processColumns: configPartial?.processColumns?.length ? configPartial.processColumns : defaultConfig.processColumns, }), [configKey]); const configRef = useRef(config); configRef.current = config; const [items, setItems] = useState([]); const [versions, setVersions] = useState([]); const [details, setDetails] = useState([]); const [loading, setLoading] = useState(false); // 선택 상태 const [selectedItemCode, setSelectedItemCode] = useState(null); const [selectedItemName, setSelectedItemName] = useState(null); const [selectedVersionId, setSelectedVersionId] = useState(null); // 품목 목록 조회 const fetchItems = useCallback( async (search?: string) => { try { setLoading(true); const ds = configRef.current.dataSource; const params = new URLSearchParams({ tableName: ds.itemTable, nameColumn: ds.itemNameColumn, codeColumn: ds.itemCodeColumn, routingTable: ds.routingVersionTable, routingFkColumn: ds.routingVersionFkColumn, ...(search ? { search } : {}), }); const res = await apiClient.get(`${API_BASE}/items?${params}`); if (res.data?.success) { setItems(res.data.data || []); } } catch (err) { console.error("품목 조회 실패", err); } finally { setLoading(false); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [configKey] ); // 라우팅 버전 목록 조회 const fetchVersions = useCallback( async (itemCode: string) => { try { const ds = configRef.current.dataSource; const params = new URLSearchParams({ routingVersionTable: ds.routingVersionTable, routingDetailTable: ds.routingDetailTable, routingFkColumn: ds.routingVersionFkColumn, processTable: ds.processTable, processNameColumn: ds.processNameColumn, processCodeColumn: ds.processCodeColumn, }); const res = await apiClient.get( `${API_BASE}/items/${encodeURIComponent(itemCode)}/routings?${params}` ); if (res.data?.success) { const routingData = res.data.data || []; setVersions(routingData); return routingData; } } catch (err) { console.error("라우팅 버전 조회 실패", err); } return []; }, // eslint-disable-next-line react-hooks/exhaustive-deps [configKey] ); // 공정 상세 목록 조회 (특정 버전의 공정들) const fetchDetails = useCallback( async (versionId: string) => { try { setLoading(true); const ds = configRef.current.dataSource; const res = await apiClient.get("/table-data/entity-join-api/data-with-joins", { params: { tableName: ds.routingDetailTable, searchConditions: JSON.stringify({ [ds.routingDetailFkColumn]: { value: versionId, operator: "equals", }, }), sortColumn: "seq_no", sortDirection: "ASC", }, }); if (res.data?.success) { setDetails(res.data.data || []); } } catch (err) { console.error("공정 상세 조회 실패", err); } finally { setLoading(false); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [configKey] ); // 품목 선택 const selectItem = useCallback( async (itemCode: string, itemName: string) => { setSelectedItemCode(itemCode); setSelectedItemName(itemName); setSelectedVersionId(null); setDetails([]); const versionList = await fetchVersions(itemCode); // 첫번째 버전 자동 선택 if (config.autoSelectFirstVersion && versionList.length > 0) { const firstVersion = versionList[0]; setSelectedVersionId(firstVersion.id); await fetchDetails(firstVersion.id); } }, [fetchVersions, fetchDetails, config.autoSelectFirstVersion] ); // 버전 선택 const selectVersion = useCallback( async (versionId: string) => { setSelectedVersionId(versionId); await fetchDetails(versionId); }, [fetchDetails] ); // 모달에서 데이터 변경 후 새로고침 const refreshVersions = useCallback(async () => { if (selectedItemCode) { const versionList = await fetchVersions(selectedItemCode); if (selectedVersionId) { await fetchDetails(selectedVersionId); } else if (versionList.length > 0) { const lastVersion = versionList[versionList.length - 1]; setSelectedVersionId(lastVersion.id); await fetchDetails(lastVersion.id); } } }, [selectedItemCode, selectedVersionId, fetchVersions, fetchDetails]); const refreshDetails = useCallback(async () => { if (selectedVersionId) { await fetchDetails(selectedVersionId); } }, [selectedVersionId, fetchDetails]); // 공정 삭제 const deleteDetail = useCallback( async (detailId: string) => { try { const ds = configRef.current.dataSource; const res = await apiClient.delete( `/table-data/${ds.routingDetailTable}/${detailId}` ); if (res.data?.success) { await refreshDetails(); return true; } } catch (err) { console.error("공정 삭제 실패", err); } return false; }, [refreshDetails] ); // 버전 삭제 const deleteVersion = useCallback( async (versionId: string) => { try { const ds = configRef.current.dataSource; const res = await apiClient.delete( `/table-data/${ds.routingVersionTable}/${versionId}` ); if (res.data?.success) { if (selectedVersionId === versionId) { setSelectedVersionId(null); setDetails([]); } await refreshVersions(); return true; } } catch (err) { console.error("버전 삭제 실패", err); } return false; }, [selectedVersionId, refreshVersions] ); return { config, items, versions, details, loading, selectedItemCode, selectedItemName, selectedVersionId, fetchItems, selectItem, selectVersion, refreshVersions, refreshDetails, deleteDetail, deleteVersion, }; }