"use client"; import React, { useState, useEffect } from "react"; import { Plus, Trash2, GripVertical, Check, ChevronsUpDown } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { cn } from "@/lib/utils"; import { ProcessWorkStandardConfig, WorkPhaseDefinition, DetailTypeDefinition } from "./types"; import { defaultConfig } from "./config"; interface TableInfo { tableName: string; displayName?: string; } interface ColumnInfo { columnName: string; displayName?: string; dataType?: string; } function TableCombobox({ value, onChange, tables, loading }: { value: string; onChange: (v: string) => void; tables: TableInfo[]; loading: boolean; }) { const [open, setOpen] = useState(false); const selected = tables.find((t) => t.tableName === value); return ( 테이블을 찾을 수 없습니다. {tables.map((t) => ( { onChange(t.tableName); setOpen(false); }} className="text-xs">
{t.displayName || t.tableName} {t.displayName && {t.tableName}}
))}
); } function ColumnCombobox({ value, onChange, tableName, placeholder }: { value: string; onChange: (v: string) => void; tableName: string; placeholder?: string; }) { const [open, setOpen] = useState(false); const [columns, setColumns] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { if (!tableName) { setColumns([]); return; } const load = async () => { setLoading(true); try { const { tableManagementApi } = await import("@/lib/api/tableManagement"); const res = await tableManagementApi.getColumnList(tableName); if (res.success && res.data?.columns) setColumns(res.data.columns); } catch { /* ignore */ } finally { setLoading(false); } }; load(); }, [tableName]); const selected = columns.find((c) => c.columnName === value); return ( 컬럼을 찾을 수 없습니다. {columns.map((c) => ( { onChange(c.columnName); setOpen(false); }} className="text-xs">
{c.displayName || c.columnName} {c.displayName && {c.columnName}}
))}
); } interface ConfigPanelProps { config: Partial; onChange: (config: Partial) => void; } export function ProcessWorkStandardConfigPanel({ config: configProp, onChange, }: ConfigPanelProps) { const [tables, setTables] = useState([]); const [loadingTables, setLoadingTables] = useState(false); const config: ProcessWorkStandardConfig = { ...defaultConfig, ...configProp, dataSource: { ...defaultConfig.dataSource, ...configProp?.dataSource }, phases: configProp?.phases?.length ? configProp.phases : defaultConfig.phases, detailTypes: configProp?.detailTypes?.length ? configProp.detailTypes : defaultConfig.detailTypes, }; useEffect(() => { const loadTables = async () => { setLoadingTables(true); try { const { tableManagementApi } = await import("@/lib/api/tableManagement"); const res = await tableManagementApi.getTableList(); if (res.success && res.data) { setTables(res.data.map((t: any) => ({ tableName: t.tableName, displayName: t.displayName || t.tableName }))); } } catch { /* ignore */ } finally { setLoadingTables(false); } }; loadTables(); }, []); const update = (partial: Partial) => { onChange({ ...configProp, ...partial }); }; const updateDataSource = (field: string, value: string) => { update({ dataSource: { ...config.dataSource, [field]: value }, }); }; // 작업 단계 관리 const addPhase = () => { const nextOrder = config.phases.length + 1; update({ phases: [ ...config.phases, { key: `PHASE_${nextOrder}`, label: `단계 ${nextOrder}`, sortOrder: nextOrder }, ], }); }; const removePhase = (idx: number) => { update({ phases: config.phases.filter((_, i) => i !== idx) }); }; const updatePhase = (idx: number, field: keyof WorkPhaseDefinition, value: string | number) => { const next = [...config.phases]; next[idx] = { ...next[idx], [field]: value }; update({ phases: next }); }; // 상세 유형 관리 const addDetailType = () => { update({ detailTypes: [ ...config.detailTypes, { value: `TYPE_${config.detailTypes.length + 1}`, label: "신규 유형" }, ], }); }; const removeDetailType = (idx: number) => { update({ detailTypes: config.detailTypes.filter((_, i) => i !== idx) }); }; const updateDetailType = (idx: number, field: keyof DetailTypeDefinition, value: string) => { const next = [...config.detailTypes]; next[idx] = { ...next[idx], [field]: value }; update({ detailTypes: next }); }; return (

공정 작업기준 설정

{/* 품목 목록 모드 */}

품목 목록 모드

{config.itemListMode === "registered" ? "품목별 라우팅 탭에서 등록한 품목만 표시됩니다. screenCode는 화면 ID 기준으로 자동 설정됩니다." : "모든 품목을 표시합니다."}

{/* 데이터 소스 설정 */}

데이터 소스 설정

updateDataSource("itemTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("itemNameColumn", v)} tableName={config.dataSource.itemTable} placeholder="품목명" />
updateDataSource("itemCodeColumn", v)} tableName={config.dataSource.itemTable} placeholder="품목코드" />
updateDataSource("routingVersionTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("routingFkColumn", v)} tableName={config.dataSource.routingVersionTable} placeholder="FK 컬럼" />
updateDataSource("processTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("processNameColumn", v)} tableName={config.dataSource.processTable} placeholder="공정명" />
updateDataSource("processCodeColumn", v)} tableName={config.dataSource.processTable} placeholder="공정코드" />
{/* 작업 단계 설정 */}

작업 단계 설정

{config.phases.map((phase, idx) => (
updatePhase(idx, "key", e.target.value)} className="h-7 w-20 text-[10px]" placeholder="키" /> updatePhase(idx, "label", e.target.value)} className="h-7 flex-1 text-[10px]" placeholder="표시명" />
))}
{/* 상세 유형 옵션 */}

상세 유형 옵션

{config.detailTypes.map((dt, idx) => (
updateDetailType(idx, "value", e.target.value)} className="h-7 w-24 text-[10px]" placeholder="값" /> updateDetailType(idx, "label", e.target.value)} className="h-7 flex-1 text-[10px]" placeholder="표시명" />
))}
{/* UI 설정 */}

UI 설정

update({ splitRatio: Number(e.target.value) })} min={15} max={50} className="mt-1 h-8 w-20 text-xs" />
update({ leftPanelTitle: e.target.value })} className="mt-1 h-8 text-xs" />
update({ readonly: v })} />
); }