"use client"; import React, { useState, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Button } from "@/components/ui/button"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Check, ChevronsUpDown, Search, Info, Settings, FileText, Table, Layers } from "lucide-react"; import { cn } from "@/lib/utils"; import { ComponentData, ButtonDataflowConfig } from "@/types/screen"; import { apiClient } from "@/lib/api/client"; import { Badge } from "@/components/ui/badge"; import { Separator } from "@/components/ui/separator"; interface ButtonDataflowConfigPanelProps { component: ComponentData; onUpdateProperty: (path: string, value: any) => void; } interface DiagramOption { id: number; name: string; description?: string; relationshipCount: number; } interface RelationshipOption { id: string; name: string; sourceTable: string; targetTable: string; category: string; } /** * πŸ”₯ λ²„νŠΌ μ œμ–΄κ΄€λ¦¬ μ„€μ • νŒ¨λ„ (Phase 1: κ°„νŽΈ λͺ¨λ“œλ§Œ) * * μ„±λŠ₯ μ΅œμ ν™”λ₯Ό μœ„ν•΄ κ°„νŽΈ λͺ¨λ“œλ§Œ κ΅¬ν˜„: * - κΈ°μ‘΄ 관계도 선택 * - "after" νƒ€μ΄λ°λ§Œ 지원 * - λ³΅μž‘ν•œ κ³ κΈ‰ λͺ¨λ“œλŠ” Phase 2μ—μ„œ */ export const ButtonDataflowConfigPanel: React.FC = ({ component, onUpdateProperty, }) => { const config = component.webTypeConfig || {}; const dataflowConfig = config.dataflowConfig || {}; // πŸ”₯ State 관리 const [diagrams, setDiagrams] = useState([]); const [relationships, setRelationships] = useState([]); const [diagramsLoading, setDiagramsLoading] = useState(false); const [relationshipsLoading, setRelationshipsLoading] = useState(false); const [diagramOpen, setDiagramOpen] = useState(false); const [relationshipOpen, setRelationshipOpen] = useState(false); const [previewData, setPreviewData] = useState(null); // πŸ”₯ 관계도 λͺ©λ‘ λ‘œλ”© useEffect(() => { if (config.enableDataflowControl) { loadDiagrams(); } }, [config.enableDataflowControl]); // πŸ”₯ 관계도 λ³€κ²½ μ‹œ 관계 λͺ©λ‘ λ‘œλ”© useEffect(() => { if (dataflowConfig.selectedDiagramId) { loadRelationships(dataflowConfig.selectedDiagramId); } }, [dataflowConfig.selectedDiagramId]); /** * πŸ”₯ 관계도 λͺ©λ‘ λ‘œλ”© (μΊμ‹œ ν™œμš©) */ const loadDiagrams = async () => { try { setDiagramsLoading(true); console.log("πŸ” λ°μ΄ν„°ν”Œλ‘œμš° 관계도 λͺ©λ‘ λ‘œλ”©..."); const response = await apiClient.get("/test-button-dataflow/diagrams"); if (response.data.success && Array.isArray(response.data.data)) { const diagramList = response.data.data.map((diagram: any) => ({ id: diagram.diagram_id, name: diagram.diagram_name, description: diagram.description, relationshipCount: diagram.relationships?.relationships?.length || 0, })); setDiagrams(diagramList); console.log(`βœ… 관계도 ${diagramList.length}개 λ‘œλ”© μ™„λ£Œ`); } } catch (error) { console.error("❌ 관계도 λͺ©λ‘ λ‘œλ”© μ‹€νŒ¨:", error); setDiagrams([]); } finally { setDiagramsLoading(false); } }; /** * πŸ”₯ 관계 λͺ©λ‘ λ‘œλ”© */ const loadRelationships = async (diagramId: number) => { try { setRelationshipsLoading(true); console.log(`πŸ” 관계도 ${diagramId} 관계 λͺ©λ‘ λ‘œλ”©...`); const response = await apiClient.get(`/test-button-dataflow/diagrams/${diagramId}/relationships`); if (response.data.success && Array.isArray(response.data.data)) { console.log("πŸ” λ°±μ—”λ“œμ—μ„œ 받은 관계 데이터:", response.data.data); const relationshipList = response.data.data.map((rel: any) => { console.log("πŸ” κ°œλ³„ 관계 데이터:", rel); // μ—¬λŸ¬ κ°€μ§€ κ°€λŠ₯ν•œ ν•„λ“œλͺ… μ‹œλ„ (λ°±μ—”λ“œ 둜그 κΈ°μ€€μœΌλ‘œ μˆ˜μ •) const relationshipName = rel.relationshipName || // λ°±μ—”λ“œμ—μ„œ 이 ν•„λ“œ μ‚¬μš© rel.name || rel.relationship_name || rel.label || rel.title || rel.description || `${rel.fromTable || rel.sourceTable || rel.source_table} β†’ ${rel.toTable || rel.targetTable || rel.target_table}`; const sourceTable = rel.fromTable || rel.sourceTable || rel.source_table || "Unknown"; // fromTable μš°μ„  const targetTable = rel.toTable || rel.targetTable || rel.target_table || "Unknown"; // toTable μš°μ„  const mappedRel = { id: rel.id, name: relationshipName, sourceTable, targetTable, category: rel.category || rel.type || "data-save", }; console.log("πŸ” λ§€ν•‘λœ 관계 데이터:", mappedRel); return mappedRel; }); setRelationships(relationshipList); console.log(`βœ… 관계 ${relationshipList.length}개 λ‘œλ”© μ™„λ£Œ:`, relationshipList); } } catch (error) { console.error("❌ 관계 λͺ©λ‘ λ‘œλ”© μ‹€νŒ¨:", error); setRelationships([]); } finally { setRelationshipsLoading(false); } }; /** * πŸ”₯ μ„ νƒλœ 관계 미리보기 λ‘œλ”© */ const loadRelationshipPreview = async () => { if (!dataflowConfig.selectedDiagramId || !dataflowConfig.selectedRelationshipId) { return; } try { const response = await apiClient.get( `/test-button-dataflow/diagrams/${dataflowConfig.selectedDiagramId}/relationships/${dataflowConfig.selectedRelationshipId}/preview`, ); if (response.data.success) { setPreviewData(response.data.data); } } catch (error) { console.error("❌ 관계 미리보기 λ‘œλ”© μ‹€νŒ¨:", error); } }; // μ„ νƒλœ 관계가 λ³€κ²½λ˜λ©΄ 미리보기 λ‘œλ”© useEffect(() => { if (dataflowConfig.selectedRelationshipId) { loadRelationshipPreview(); } }, [dataflowConfig.selectedRelationshipId]); /** * ν˜„μž¬ μ•‘μ…˜ νƒ€μž…λ³„ ν‘œμ‹œλͺ… */ const getActionDisplayName = (actionType: string): string => { const displayNames: Record = { save: "μ €μž₯", delete: "μ‚­μ œ", edit: "μˆ˜μ •", add: "μΆ”κ°€", search: "검색", reset: "μ΄ˆκΈ°ν™”", submit: "제좜", close: "λ‹«κΈ°", popup: "νŒμ—…", navigate: "νŽ˜μ΄μ§€ 이동", control: "μ œμ–΄", }; return displayNames[actionType] || actionType; }; /** * 타이밍별 μ„€λͺ… (κ°„μ†Œν™”) */ const getTimingDescription = (timing: string): string => { switch (timing) { case "before": return "μ•‘μ…˜ μ‹€ν–‰ μ „ μ œμ–΄κ΄€λ¦¬"; case "after": return "μ•‘μ…˜ μ‹€ν–‰ ν›„ μ œμ–΄κ΄€λ¦¬"; case "replace": return "μ œμ–΄κ΄€λ¦¬λ‘œ μ™„μ „ λŒ€μ²΄"; default: return ""; } }; // μ„ νƒλœ 관계도 정보 const selectedDiagram = diagrams.find((d) => d.id === dataflowConfig.selectedDiagramId); const selectedRelationship = relationships.find((r) => r.id === dataflowConfig.selectedRelationshipId); return (
{/* πŸ”₯ μ œμ–΄κ΄€λ¦¬ ν™œμ„±ν™” μŠ€μœ„μΉ˜ */}

λ²„νŠΌ 클릭 μ‹œ 데이터 흐름을 μžλ™μœΌλ‘œ μ œμ–΄ν•©λ‹ˆλ‹€

onUpdateProperty("webTypeConfig.enableDataflowControl", checked)} />
{/* πŸ”₯ μ œμ–΄κ΄€λ¦¬κ°€ ν™œμ„±ν™”λœ κ²½μš°μ—λ§Œ μ„€μ • ν‘œμ‹œ */} {config.enableDataflowControl && ( <> {/* πŸ”₯ μ œμ–΄ 데이터 μ†ŒμŠ€ 선택 */}

{dataflowConfig.controlDataSource === "form" && "ν˜„μž¬ 폼의 μž…λ ₯κ°’μœΌλ‘œ 쑰건을 μ²΄ν¬ν•©λ‹ˆλ‹€"} {dataflowConfig.controlDataSource === "table-selection" && "ν…Œμ΄λΈ”μ—μ„œ μ„ νƒλœ ν•­λͺ©μ˜ λ°μ΄ν„°λ‘œ 쑰건을 μ²΄ν¬ν•©λ‹ˆλ‹€"} {dataflowConfig.controlDataSource === "both" && "폼 데이터와 μ„ νƒλœ ν•­λͺ© 데이터λ₯Ό λͺ¨λ‘ μ‚¬μš©ν•©λ‹ˆλ‹€"} {!dataflowConfig.controlDataSource && "폼 데이터λ₯Ό 기본으둜 μ‚¬μš©ν•©λ‹ˆλ‹€"}

)} {config.enableDataflowControl && (
{/* ν˜„μž¬ μ•‘μ…˜ 정보 (κ°„μ†Œν™”) */}

{getActionDisplayName(config.actionType || "save")} μ•‘μ…˜μ— μ œμ–΄κ΄€λ¦¬ μ—°κ²°

{/* μ‹€ν–‰ 타이밍 선택 (Phase 1: after만 지원) */}
{/* μ œμ–΄ λͺ¨λ“œ 선택 (Phase 1: simple만 지원) */}
{/* κ°„νŽΈ λͺ¨λ“œ μ„€μ • */} {(dataflowConfig.controlMode === "simple" || !dataflowConfig.controlMode) && (

관계도 선택

{/* 관계도 선택 */}
{diagramsLoading ? (
관계도 λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...
) : diagrams.length === 0 ? (
μ‚¬μš© κ°€λŠ₯ν•œ 관계도가 μ—†μŠ΅λ‹ˆλ‹€
) : (
{diagrams.map((diagram) => ( ))}
)}
{/* 관계 선택 */} {dataflowConfig.selectedDiagramId && (
{relationshipsLoading ? (
관계 λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...
) : relationships.length === 0 ? (
이 κ΄€κ³„λ„μ—λŠ” μ‚¬μš© κ°€λŠ₯ν•œ 관계가 μ—†μŠ΅λ‹ˆλ‹€
) : (
{relationships.map((relationship) => ( ))}
)}
)} {/* μ„ νƒλœ 관계 간단 정보 */} {selectedRelationship && (

{selectedRelationship.sourceTable} β†’{" "} {selectedRelationship.targetTable} {previewData && ( (쑰건 {previewData.conditionsCount || 0}개, μ•‘μ…˜ {previewData.actionsCount || 0}개) )}

)}
)}
)}
); };