"use client"; /** * V2Biz 설정 패널 * 토스식 단계별 UX: 비즈니스 타입 카드 선택 -> 타입별 설정 -> 고급 설정(접힘) */ import React, { useState, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { GitBranch, LayoutGrid, MapPin, Hash, FolderTree, ArrowRightLeft, Link2, Loader2, } from "lucide-react"; import { cn } from "@/lib/utils"; import { tableTypeApi } from "@/lib/api/screen"; interface V2BizConfigPanelProps { config: Record; onChange: (config: Record) => void; } interface TableOption { tableName: string; displayName: string; } interface ColumnOption { columnName: string; displayName: string; } const BIZ_TYPE_CARDS = [ { value: "flow", icon: GitBranch, title: "플로우", description: "워크플로우를 구성해요" }, { value: "rack", icon: LayoutGrid, title: "랙 구조", description: "창고 렉 위치를 관리해요" }, { value: "map", icon: MapPin, title: "지도", description: "위치 정보를 표시해요" }, { value: "numbering", icon: Hash, title: "채번 규칙", description: "자동 번호를 생성해요" }, { value: "category", icon: FolderTree, title: "카테고리", description: "분류 체계를 관리해요" }, { value: "data-mapping", icon: ArrowRightLeft, title: "데이터 매핑", description: "테이블 간 매핑해요" }, { value: "related-data", icon: Link2, title: "관련 데이터", description: "연결된 데이터를 조회해요" }, ] as const; export const V2BizConfigPanel: React.FC = ({ config, onChange, }) => { const [tables, setTables] = useState([]); const [loadingTables, setLoadingTables] = useState(false); const [sourceColumns, setSourceColumns] = useState([]); const [targetColumns, setTargetColumns] = useState([]); const [relatedColumns, setRelatedColumns] = useState([]); const [categoryColumns, setCategoryColumns] = useState([]); const [loadingColumns, setLoadingColumns] = useState(false); const updateConfig = (field: string, value: any) => { onChange({ ...config, [field]: value }); }; useEffect(() => { const loadTables = async () => { setLoadingTables(true); try { const data = await tableTypeApi.getTables(); setTables(data.map(t => ({ tableName: t.tableName, displayName: t.displayName || t.tableName }))); } catch (error) { console.error("테이블 목록 로드 실패:", error); } finally { setLoadingTables(false); } }; loadTables(); }, []); useEffect(() => { const loadColumns = async () => { if (!config.sourceTable) { setSourceColumns([]); return; } try { const data = await tableTypeApi.getColumns(config.sourceTable); setSourceColumns(data.map((c: any) => ({ columnName: c.columnName || c.column_name, displayName: c.displayName || c.columnName || c.column_name }))); } catch (error) { console.error("소스 컬럼 로드 실패:", error); } }; loadColumns(); }, [config.sourceTable]); useEffect(() => { const loadColumns = async () => { if (!config.targetTable) { setTargetColumns([]); return; } try { const data = await tableTypeApi.getColumns(config.targetTable); setTargetColumns(data.map((c: any) => ({ columnName: c.columnName || c.column_name, displayName: c.displayName || c.columnName || c.column_name }))); } catch (error) { console.error("대상 컬럼 로드 실패:", error); } }; loadColumns(); }, [config.targetTable]); useEffect(() => { const loadColumns = async () => { if (!config.relatedTable) { setRelatedColumns([]); return; } try { const data = await tableTypeApi.getColumns(config.relatedTable); setRelatedColumns(data.map((c: any) => ({ columnName: c.columnName || c.column_name, displayName: c.displayName || c.columnName || c.column_name }))); } catch (error) { console.error("관련 컬럼 로드 실패:", error); } }; loadColumns(); }, [config.relatedTable]); useEffect(() => { const loadColumns = async () => { if (!config.tableName) { setCategoryColumns([]); return; } setLoadingColumns(true); try { const data = await tableTypeApi.getColumns(config.tableName); setCategoryColumns(data.map((c: any) => ({ columnName: c.columnName || c.column_name, displayName: c.displayName || c.columnName || c.column_name }))); } catch (error) { console.error("카테고리 컬럼 로드 실패:", error); } finally { setLoadingColumns(false); } }; loadColumns(); }, [config.tableName]); const bizType = config.bizType || config.type || "flow"; return (
{/* ─── 1단계: 비즈니스 타입 선택 (카드) ─── */}

어떤 비즈니스 기능을 사용하나요?

{BIZ_TYPE_CARDS.map((card) => { const Icon = card.icon; const isSelected = bizType === card.value; return ( ); })}
{/* ─── 2단계: 타입별 설정 ─── */} {/* 플로우 설정 */} {bizType === "flow" && (
플로우 설정
플로우 ID updateConfig("flowId", e.target.value ? Number(e.target.value) : undefined)} placeholder="플로우 ID" className="h-7 w-[160px] text-xs" />

편집 가능

플로우를 직접 수정할 수 있어요

updateConfig("editable", checked)} />

미니맵 표시

전체 구조를 한눈에 볼 수 있어요

updateConfig("showMinimap", checked)} />
)} {/* 랙 구조 설정 */} {bizType === "rack" && (
랙 구조 설정

렉 크기

updateConfig("rows", e.target.value ? Number(e.target.value) : undefined)} placeholder="5" min="1" className="h-7 text-xs" />
updateConfig("columns", e.target.value ? Number(e.target.value) : undefined)} placeholder="10" min="1" className="h-7 text-xs" />

라벨 표시

각 셀에 위치 라벨이 표시돼요

updateConfig("showLabels", checked)} />
)} {/* 채번 규칙 설정 */} {bizType === "numbering" && (
채번 규칙 설정
채번 규칙 ID updateConfig("ruleId", e.target.value ? Number(e.target.value) : undefined)} placeholder="규칙 ID" className="h-7 w-[160px] text-xs" />
접두사 updateConfig("prefix", e.target.value)} placeholder="예: INV-" className="h-7 w-[160px] text-xs" />

자동 생성

저장할 때 번호가 자동으로 생성돼요

updateConfig("autoGenerate", checked)} />
)} {/* 카테고리 설정 */} {bizType === "category" && (
카테고리 설정

카테고리 테이블

{loadingTables ? (
테이블 로딩 중...
) : ( )}
{config.tableName && (

컬럼

{loadingColumns ? (
컬럼 로딩 중...
) : ( )}
)}
)} {/* 데이터 매핑 설정 */} {bizType === "data-mapping" && (
데이터 매핑 설정

소스 테이블

{loadingTables ? (
테이블 로딩 중...
) : ( )}

대상 테이블

{loadingTables ? (
테이블 로딩 중...
) : ( )}
)} {/* 관련 데이터 설정 */} {bizType === "related-data" && (
관련 데이터 설정

관련 테이블

{loadingTables ? (
테이블 로딩 중...
) : ( )}
{config.relatedTable && (

연결 컬럼

)}
버튼 텍스트 updateConfig("buttonText", e.target.value)} placeholder="관련 데이터 보기" className="h-7 w-[160px] text-xs" />
)}
); }; V2BizConfigPanel.displayName = "V2BizConfigPanel"; export default V2BizConfigPanel;