"use client"; 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 { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Button } from "@/components/ui/button"; import { Check, ChevronsUpDown, Search } from "lucide-react"; import { cn } from "@/lib/utils"; import { ComponentData } from "@/types/screen"; import { apiClient } from "@/lib/api/client"; import { ButtonDataflowConfigPanel } from "./ButtonDataflowConfigPanel"; import { ImprovedButtonControlConfigPanel } from "./ImprovedButtonControlConfigPanel"; interface ButtonConfigPanelProps { component: ComponentData; onUpdateProperty: (path: string, value: any) => void; } interface ScreenOption { id: number; name: string; description?: string; } export const ButtonConfigPanel: React.FC = ({ component, onUpdateProperty }) => { // πŸ”§ 항상 μ΅œμ‹  componentμ—μ„œ 직접 μ°Έμ‘° const config = component.componentConfig || {}; const currentAction = component.componentConfig?.action || {}; // πŸ”§ μ΅œμ‹  action μ°Έμ‘° // 둜컬 μƒνƒœ 관리 (μ‹€μ‹œκ°„ μž…λ ₯ 반영) const [localInputs, setLocalInputs] = useState({ text: config.text !== undefined ? config.text : "λ²„νŠΌ", // πŸ”§ 빈 λ¬Έμžμ—΄ ν—ˆμš© modalTitle: config.action?.modalTitle || "", editModalTitle: config.action?.editModalTitle || "", editModalDescription: config.action?.editModalDescription || "", targetUrl: config.action?.targetUrl || "", }); const [localSelects, setLocalSelects] = useState({ variant: config.variant || "default", size: config.size || "md", // πŸ”§ 기본값을 "md"둜 λ³€κ²½ actionType: config.action?.type, // πŸ”§ κΈ°λ³Έκ°’ μ™„μ „ 제거 (undefined) modalSize: config.action?.modalSize || "md", editMode: config.action?.editMode || "modal", }); const [screens, setScreens] = useState([]); const [screensLoading, setScreensLoading] = useState(false); const [modalScreenOpen, setModalScreenOpen] = useState(false); const [navScreenOpen, setNavScreenOpen] = useState(false); const [modalSearchTerm, setModalSearchTerm] = useState(""); const [navSearchTerm, setNavSearchTerm] = useState(""); // μ»΄ν¬λ„ŒνŠΈ λ³€κ²½ μ‹œ 둜컬 μƒνƒœ 동기화 useEffect(() => { console.log("πŸ”„ ButtonConfigPanel useEffect μ‹€ν–‰:", { componentId: component.id, "config.action?.type": config.action?.type, "localSelects.actionType (before)": localSelects.actionType, fullAction: config.action, "component.componentConfig.action": component.componentConfig?.action, }); setLocalInputs({ text: config.text !== undefined ? config.text : "λ²„νŠΌ", // πŸ”§ 빈 λ¬Έμžμ—΄ ν—ˆμš© modalTitle: config.action?.modalTitle || "", editModalTitle: config.action?.editModalTitle || "", editModalDescription: config.action?.editModalDescription || "", targetUrl: config.action?.targetUrl || "", }); setLocalSelects((prev) => { const newSelects = { variant: config.variant || "default", size: config.size || "md", // πŸ”§ 기본값을 "md"둜 λ³€κ²½ actionType: config.action?.type, // πŸ”§ κΈ°λ³Έκ°’ μ™„μ „ 제거 (undefined) modalSize: config.action?.modalSize || "md", editMode: config.action?.editMode || "modal", }; console.log("πŸ“ setLocalSelects 호좜:", { "prev.actionType": prev.actionType, "new.actionType": newSelects.actionType, "config.action?.type": config.action?.type, }); return newSelects; }); }, [ component.id, // πŸ”§ μ»΄ν¬λ„ŒνŠΈ ID (λ‹€λ₯Έ μ»΄ν¬λ„ŒνŠΈλ‘œ μ „ν™˜ μ‹œ) component.componentConfig?.action?.type, // πŸ”§ μ•‘μ…˜ νƒ€μž… (μ•‘μ…˜ λ³€κ²½ μ‹œ μ¦‰μ‹œ 반영) component.componentConfig?.text, // πŸ”§ λ²„νŠΌ ν…μŠ€νŠΈ component.componentConfig?.variant, // πŸ”§ λ²„νŠΌ μŠ€νƒ€μΌ component.componentConfig?.size, // πŸ”§ λ²„νŠΌ 크기 ]); // ν™”λ©΄ λͺ©λ‘ κ°€μ Έμ˜€κΈ° useEffect(() => { const fetchScreens = async () => { try { setScreensLoading(true); const response = await apiClient.get("/screen-management/screens"); if (response.data.success && Array.isArray(response.data.data)) { const screenList = response.data.data.map((screen: any) => ({ id: screen.screenId, name: screen.screenName, description: screen.description, })); setScreens(screenList); } } catch (error) { // console.error("❌ ν™”λ©΄ λͺ©λ‘ λ‘œλ”© μ‹€νŒ¨:", error); } finally { setScreensLoading(false); } }; fetchScreens(); }, []); // 검색 필터링 ν•¨μˆ˜ const filterScreens = (searchTerm: string) => { if (!searchTerm.trim()) return screens; return screens.filter( (screen) => screen.name.toLowerCase().includes(searchTerm.toLowerCase()) || (screen.description && screen.description.toLowerCase().includes(searchTerm.toLowerCase())), ); }; console.log("πŸ”§ config-panels/ButtonConfigPanel λ Œλ”λ§:", { component, config, action: config.action, actionType: config.action?.type, screensCount: screens.length, }); return (
{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, text: newValue })); onUpdateProperty("componentConfig.text", newValue); }} placeholder="λ²„νŠΌ ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜μ„Έμš”" />
{/* λͺ¨λ‹¬ μ—΄κΈ° μ•‘μ…˜ μ„€μ • */} {localSelects.actionType === "modal" && (

λͺ¨λ‹¬ μ„€μ •

{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, modalTitle: newValue })); onUpdateProperty("componentConfig.action.modalTitle", newValue); }} />
setModalSearchTerm(e.target.value)} className="border-0 p-0 focus-visible:ring-0" />
{(() => { const filteredScreens = filterScreens(modalSearchTerm); if (screensLoading) { return
ν™”λ©΄ λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...
; } if (filteredScreens.length === 0) { return
검색 κ²°κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.
; } return filteredScreens.map((screen, index) => (
{ onUpdateProperty("componentConfig.action.targetScreenId", screen.id); setModalScreenOpen(false); setModalSearchTerm(""); }} >
{screen.name} {screen.description && {screen.description}}
)); })()}
)} {/* μˆ˜μ • μ•‘μ…˜ μ„€μ • */} {localSelects.actionType === "edit" && (

μˆ˜μ • μ„€μ •

setModalSearchTerm(e.target.value)} className="border-0 p-0 focus-visible:ring-0" />
{(() => { const filteredScreens = filterScreens(modalSearchTerm); if (screensLoading) { return
ν™”λ©΄ λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...
; } if (filteredScreens.length === 0) { return
검색 κ²°κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.
; } return filteredScreens.map((screen, index) => (
{ onUpdateProperty("componentConfig.action.targetScreenId", screen.id); setModalScreenOpen(false); setModalSearchTerm(""); }} >
{screen.name} {screen.description && {screen.description}}
)); })()}

μ„ νƒλœ 데이터가 이 폼 화면에 μžλ™μœΌλ‘œ λ‘œλ“œλ˜μ–΄ μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€

{localSelects.editMode === "modal" && ( <>
{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, editModalTitle: newValue })); onUpdateProperty("componentConfig.action.editModalTitle", newValue); onUpdateProperty("webTypeConfig.editModalTitle", newValue); }} />

λΉ„μ›Œλ‘λ©΄ κΈ°λ³Έ 제λͺ©μ΄ ν‘œμ‹œλ©λ‹ˆλ‹€

{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, editModalDescription: newValue })); onUpdateProperty("componentConfig.action.editModalDescription", newValue); onUpdateProperty("webTypeConfig.editModalDescription", newValue); }} />

λΉ„μ›Œλ‘λ©΄ μ„€λͺ…이 ν‘œμ‹œλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€

)}
)} {/* νŽ˜μ΄μ§€ 이동 μ•‘μ…˜ μ„€μ • */} {localSelects.actionType === "navigate" && (

νŽ˜μ΄μ§€ 이동 μ„€μ •

setNavSearchTerm(e.target.value)} className="border-0 p-0 focus-visible:ring-0" />
{(() => { const filteredScreens = filterScreens(navSearchTerm); if (screensLoading) { return
ν™”λ©΄ λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...
; } if (filteredScreens.length === 0) { return
검색 κ²°κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.
; } return filteredScreens.map((screen, index) => (
{ onUpdateProperty("componentConfig.action.targetScreenId", screen.id); setNavScreenOpen(false); setNavSearchTerm(""); }} >
{screen.name} {screen.description && {screen.description}}
)); })()}

μ„ νƒν•œ ν™”λ©΄μœΌλ‘œ /screens/{"{"}ν™”λ©΄ID{"}"} ν˜•νƒœλ‘œ μ΄λ™ν•©λ‹ˆλ‹€

{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, targetUrl: newValue })); onUpdateProperty("componentConfig.action.targetUrl", newValue); }} />

URL을 μž…λ ₯ν•˜λ©΄ ν™”λ©΄ 선택보닀 μš°μ„  μ μš©λ©λ‹ˆλ‹€

)} {/* πŸ”₯ NEW: μ œμ–΄κ΄€λ¦¬ κΈ°λŠ₯ μ„Ήμ…˜ */}

πŸ”§ κ³ κΈ‰ κΈ°λŠ₯

λ²„νŠΌ μ•‘μ…˜κ³Ό ν•¨κ»˜ 싀행될 μΆ”κ°€ κΈ°λŠ₯을 μ„€μ •ν•©λ‹ˆλ‹€

); };