ERP-node/frontend/lib/registry/components/v2-process-work-standard/hooks/useProcessWorkStandard.ts

337 lines
9.3 KiB
TypeScript
Raw Normal View History

"use client";
import { useState, useCallback } from "react";
import { apiClient } from "@/lib/api/client";
import {
ProcessWorkStandardConfig,
ItemData,
RoutingVersion,
WorkItem,
WorkItemDetail,
SelectionState,
} from "../types";
const API_BASE = "/api/process-work-standard";
export function useProcessWorkStandard(config: ProcessWorkStandardConfig) {
const [items, setItems] = useState<ItemData[]>([]);
const [routings, setRoutings] = useState<RoutingVersion[]>([]);
const [workItems, setWorkItems] = useState<WorkItem[]>([]);
const [selectedWorkItemDetails, setSelectedWorkItemDetails] = useState<WorkItemDetail[]>([]);
const [selectedWorkItemId, setSelectedWorkItemId] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const [saving, setSaving] = useState(false);
const [selection, setSelection] = useState<SelectionState>({
itemCode: null,
itemName: null,
routingVersionId: null,
routingVersionName: null,
routingDetailId: null,
processName: null,
});
// 품목 목록 조회
const fetchItems = useCallback(
async (search?: string) => {
try {
setLoading(true);
const ds = config.dataSource;
const params = new URLSearchParams({
tableName: ds.itemTable,
nameColumn: ds.itemNameColumn,
codeColumn: ds.itemCodeColumn,
routingTable: ds.routingVersionTable,
routingFkColumn: ds.routingFkColumn,
...(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);
}
},
[config.dataSource]
);
// 라우팅 + 공정 조회
const fetchRoutings = useCallback(
async (itemCode: string) => {
try {
const ds = config.dataSource;
const params = new URLSearchParams({
routingVersionTable: ds.routingVersionTable,
routingDetailTable: ds.routingDetailTable,
routingFkColumn: ds.routingFkColumn,
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) {
setRoutings(res.data.data);
}
} catch (err) {
console.error("라우팅 조회 실패", err);
}
},
[config.dataSource]
);
// 작업 항목 조회
const fetchWorkItems = useCallback(async (routingDetailId: string) => {
try {
setLoading(true);
const res = await apiClient.get(
`${API_BASE}/routing-detail/${routingDetailId}/work-items`
);
if (res.data?.success) {
setWorkItems(res.data.items || []);
}
} catch (err) {
console.error("작업 항목 조회 실패", err);
} finally {
setLoading(false);
}
}, []);
// 작업 항목 상세 조회
const fetchWorkItemDetails = useCallback(async (workItemId: string) => {
try {
const res = await apiClient.get(
`${API_BASE}/work-items/${workItemId}/details`
);
if (res.data?.success) {
setSelectedWorkItemDetails(res.data.data);
setSelectedWorkItemId(workItemId);
}
} catch (err) {
console.error("상세 조회 실패", err);
}
}, []);
// 품목 선택
const selectItem = useCallback(
async (itemCode: string, itemName: string) => {
setSelection((prev) => ({
...prev,
itemCode,
itemName,
routingVersionId: null,
routingVersionName: null,
routingDetailId: null,
processName: null,
}));
setWorkItems([]);
setSelectedWorkItemDetails([]);
setSelectedWorkItemId(null);
await fetchRoutings(itemCode);
},
[fetchRoutings]
);
// 공정 선택
const selectProcess = useCallback(
async (
routingDetailId: string,
processName: string,
routingVersionId: string,
routingVersionName: string
) => {
setSelection((prev) => ({
...prev,
routingVersionId,
routingVersionName,
routingDetailId,
processName,
}));
setSelectedWorkItemDetails([]);
setSelectedWorkItemId(null);
await fetchWorkItems(routingDetailId);
},
[fetchWorkItems]
);
// 작업 항목 추가
const createWorkItem = useCallback(
async (data: {
work_phase: string;
title: string;
is_required: string;
description?: string;
details?: Array<{
detail_type?: string;
content: string;
is_required: string;
sort_order: number;
}>;
}) => {
if (!selection.routingDetailId) return null;
try {
const nextOrder =
workItems.filter((wi) => wi.work_phase === data.work_phase).length + 1;
const res = await apiClient.post(`${API_BASE}/work-items`, {
routing_detail_id: selection.routingDetailId,
work_phase: data.work_phase,
title: data.title,
is_required: data.is_required,
sort_order: nextOrder,
description: data.description,
});
if (res.data?.success && res.data.data) {
const newItem = res.data.data;
// 상세 항목도 함께 생성
if (data.details && data.details.length > 0) {
for (const detail of data.details) {
await apiClient.post(`${API_BASE}/work-item-details`, {
work_item_id: newItem.id,
...detail,
});
}
}
await fetchWorkItems(selection.routingDetailId);
return newItem;
}
} catch (err) {
console.error("작업 항목 생성 실패", err);
}
return null;
},
[selection.routingDetailId, workItems, fetchWorkItems]
);
// 작업 항목 수정
const updateWorkItem = useCallback(
async (id: string, data: Partial<WorkItem>) => {
try {
const res = await apiClient.put(`${API_BASE}/work-items/${id}`, data);
if (res.data?.success && selection.routingDetailId) {
await fetchWorkItems(selection.routingDetailId);
}
} catch (err) {
console.error("작업 항목 수정 실패", err);
}
},
[selection.routingDetailId, fetchWorkItems]
);
// 작업 항목 삭제
const deleteWorkItem = useCallback(
async (id: string) => {
try {
const res = await apiClient.delete(`${API_BASE}/work-items/${id}`);
if (res.data?.success && selection.routingDetailId) {
await fetchWorkItems(selection.routingDetailId);
if (selectedWorkItemId === id) {
setSelectedWorkItemDetails([]);
setSelectedWorkItemId(null);
}
}
} catch (err) {
console.error("작업 항목 삭제 실패", err);
}
},
[selection.routingDetailId, selectedWorkItemId, fetchWorkItems]
);
// 상세 추가
const createDetail = useCallback(
async (workItemId: string, data: Partial<WorkItemDetail>) => {
try {
const res = await apiClient.post(`${API_BASE}/work-item-details`, {
work_item_id: workItemId,
...data,
});
if (res.data?.success) {
await fetchWorkItemDetails(workItemId);
if (selection.routingDetailId) {
await fetchWorkItems(selection.routingDetailId);
}
}
} catch (err) {
console.error("상세 생성 실패", err);
}
},
[fetchWorkItemDetails, fetchWorkItems, selection.routingDetailId]
);
// 상세 수정
const updateDetail = useCallback(
async (id: string, data: Partial<WorkItemDetail>) => {
try {
const res = await apiClient.put(
`${API_BASE}/work-item-details/${id}`,
data
);
if (res.data?.success && selectedWorkItemId) {
await fetchWorkItemDetails(selectedWorkItemId);
}
} catch (err) {
console.error("상세 수정 실패", err);
}
},
[selectedWorkItemId, fetchWorkItemDetails]
);
// 상세 삭제
const deleteDetail = useCallback(
async (id: string) => {
try {
const res = await apiClient.delete(
`${API_BASE}/work-item-details/${id}`
);
if (res.data?.success) {
if (selectedWorkItemId) {
await fetchWorkItemDetails(selectedWorkItemId);
}
if (selection.routingDetailId) {
await fetchWorkItems(selection.routingDetailId);
}
}
} catch (err) {
console.error("상세 삭제 실패", err);
}
},
[
selectedWorkItemId,
selection.routingDetailId,
fetchWorkItemDetails,
fetchWorkItems,
]
);
return {
items,
routings,
workItems,
selectedWorkItemDetails,
selectedWorkItemId,
selection,
loading,
saving,
fetchItems,
selectItem,
selectProcess,
fetchWorkItems,
fetchWorkItemDetails,
setSelectedWorkItemId,
createWorkItem,
updateWorkItem,
deleteWorkItem,
createDetail,
updateDetail,
deleteDetail,
};
}