"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] ); // 공정 상세 목록 조회 (특정 버전의 공정들) - entity join 포함 const fetchDetails = useCallback( async (versionId: string) => { try { setLoading(true); const ds = configRef.current.dataSource; const searchConditions = { [ds.routingDetailFkColumn]: { value: versionId, operator: "equals" }, }; const params = new URLSearchParams({ page: "1", size: "1000", search: JSON.stringify(searchConditions), sortBy: "seq_no", sortOrder: "ASC", enableEntityJoin: "true", }); const res = await apiClient.get( `/table-management/tables/${ds.routingDetailTable}/data-with-joins?${params}` ); if (res.data?.success) { const result = res.data.data; setDetails(Array.isArray(result) ? result : result?.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 (versionList.length > 0) { // 기본 버전 우선, 없으면 첫번째 버전 선택 const defaultVersion = versionList.find((v: RoutingVersionData) => v.is_default); const targetVersion = defaultVersion || (configRef.current.autoSelectFirstVersion ? versionList[0] : null); if (targetVersion) { setSelectedVersionId(targetVersion.id); await fetchDetails(targetVersion.id); } } }, [fetchVersions, fetchDetails] ); // 버전 선택 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-management/tables/${ds.routingDetailTable}/delete`, { data: [{ id: 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-management/tables/${ds.routingVersionTable}/delete`, { data: [{ id: versionId }] } ); if (res.data?.success) { if (selectedVersionId === versionId) { setSelectedVersionId(null); setDetails([]); } await refreshVersions(); return true; } } catch (err) { console.error("버전 삭제 실패", err); } return false; }, [selectedVersionId, refreshVersions] ); // 기본 버전 설정 const setDefaultVersion = useCallback( async (versionId: string) => { try { const ds = configRef.current.dataSource; const res = await apiClient.put(`${API_BASE}/versions/${versionId}/set-default`, { routingVersionTable: ds.routingVersionTable, routingFkColumn: ds.routingVersionFkColumn, }); if (res.data?.success) { if (selectedItemCode) { await fetchVersions(selectedItemCode); } return true; } } catch (err) { console.error("기본 버전 설정 실패", err); } return false; }, [selectedItemCode, fetchVersions] ); // 기본 버전 해제 const unsetDefaultVersion = useCallback( async (versionId: string) => { try { const ds = configRef.current.dataSource; const res = await apiClient.put(`${API_BASE}/versions/${versionId}/unset-default`, { routingVersionTable: ds.routingVersionTable, }); if (res.data?.success) { if (selectedItemCode) { await fetchVersions(selectedItemCode); } return true; } } catch (err) { console.error("기본 버전 해제 실패", err); } return false; }, [selectedItemCode, fetchVersions] ); return { config, items, versions, details, loading, selectedItemCode, selectedItemName, selectedVersionId, fetchItems, selectItem, selectVersion, refreshVersions, refreshDetails, deleteDetail, deleteVersion, setDefaultVersion, unsetDefaultVersion, }; }