"use client";
/**
* V2 공정 작업기준 설정 패널 (간소화)
*/
import React, { useState, useEffect } from "react";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Button } from "@/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Badge } from "@/components/ui/badge";
import {
Settings,
ChevronDown,
ChevronRight,
Plus,
Trash2,
Check,
ChevronsUpDown,
Database,
Layers,
List,
} from "lucide-react";
import { cn } from "@/lib/utils";
import type {
ProcessWorkStandardConfig,
WorkPhaseDefinition,
DetailTypeDefinition,
} from "@/lib/registry/components/v2-process-work-standard/types";
import { defaultConfig } from "@/lib/registry/components/v2-process-work-standard/config";
interface TableInfo { tableName: string; displayName?: string; }
function TableCombobox({ value, onChange, tables, loading, label }: {
value: string; onChange: (v: string) => void; tables: TableInfo[]; loading: boolean; label: string;
}) {
const [open, setOpen] = useState(false);
const selected = tables.find((t) => t.tableName === value);
return (
{label}
테이블을 찾을 수 없습니다.
{tables.map((t) => (
{ onChange(t.tableName); setOpen(false); }} className="text-xs">
{t.displayName || t.tableName}
{t.displayName && {t.tableName}}
))}
);
}
interface V2ProcessWorkStandardConfigPanelProps {
config: Partial;
onChange: (config: Partial) => void;
}
export const V2ProcessWorkStandardConfigPanel: React.FC<
V2ProcessWorkStandardConfigPanelProps
> = ({ config: configProp, onChange }) => {
const [phasesOpen, setPhasesOpen] = useState(false);
const [detailTypesOpen, setDetailTypesOpen] = useState(false);
const [layoutOpen, setLayoutOpen] = useState(false);
const [dataSourceOpen, setDataSourceOpen] = useState(false);
const [tables, setTables] = useState([]);
const [loadingTables, setLoadingTables] = useState(false);
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 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,
};
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" && (
품목별 라우팅 탭에서 등록한 품목만 표시됩니다.
)}
{/* 작업 단계 */}
공정별 작업 단계를 정의
{config.phases.map((phase, idx) => (
))}
단계 추가
{/* 상세 유형 */}
상세 유형
{config.detailTypes.length}개
작업 항목의 상세 유형 옵션
{config.detailTypes.map((dt, idx) => (
#{idx + 1}
{dt.label}
{dt.value}
{
e.stopPropagation();
removeDetailType(idx);
}}
className="text-muted-foreground hover:text-destructive h-5 w-5 shrink-0 p-0"
disabled={config.detailTypes.length <= 1}
>
))}
유형 추가
{/* 데이터 소스 (테이블만) */}
테이블 설정
테이블만 선택하면 컬럼 정보는 엔티티 설정에서 자동으로 가져옵니다.
updateDataSource("itemTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("routingVersionTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("routingDetailTable", v)} tables={tables} loading={loadingTables} />
updateDataSource("processTable", v)} tables={tables} loading={loadingTables} />
{/* 레이아웃 & 기타 */}
레이아웃
);
};
V2ProcessWorkStandardConfigPanel.displayName =
"V2ProcessWorkStandardConfigPanel";
export default V2ProcessWorkStandardConfigPanel;