240 lines
7.1 KiB
TypeScript
240 lines
7.1 KiB
TypeScript
"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<ItemRoutingConfig>) {
|
|
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<ItemData[]>([]);
|
|
const [versions, setVersions] = useState<RoutingVersionData[]>([]);
|
|
const [details, setDetails] = useState<RoutingDetailData[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
// 선택 상태
|
|
const [selectedItemCode, setSelectedItemCode] = useState<string | null>(null);
|
|
const [selectedItemName, setSelectedItemName] = useState<string | null>(null);
|
|
const [selectedVersionId, setSelectedVersionId] = useState<string | null>(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,
|
|
};
|
|
}
|