"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 }) => { const config = component.componentConfig || {}; // 로컬 상태 관리 (실시간 입력 반영) const [localInputs, setLocalInputs] = useState({ text: 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 || "default", actionType: config.action?.type || "save", 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(() => { setLocalInputs({ text: config.text || "버튼", modalTitle: config.action?.modalTitle || "", editModalTitle: config.action?.editModalTitle || "", editModalDescription: config.action?.editModalDescription || "", targetUrl: config.action?.targetUrl || "", }); setLocalSelects({ variant: config.variant || "default", size: config.size || "default", actionType: config.action?.type || "save", modalSize: config.action?.modalSize || "md", editMode: config.action?.editMode || "modal", }); }, [ config.text, config.variant, config.size, config.action?.type, config.action?.modalTitle, config.action?.modalSize, config.action?.editMode, config.action?.editModalTitle, config.action?.editModalDescription, config.action?.targetUrl, ]); // 화면 목록 가져오기 useEffect(() => { const fetchScreens = async () => { try { setScreensLoading(true); // console.log("🔍 화면 목록 API 호출 시작"); const response = await apiClient.get("/screen-management/screens"); // console.log("✅ 화면 목록 API 응답:", response.data); 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); // console.log("✅ 화면 목록 설정 완료:", screenList.length, "개"); } } 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", { ...config.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", { ...config.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", { ...config.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", { ...config.action, editModalTitle: newValue, }); // webTypeConfig에도 저장 onUpdateProperty("webTypeConfig.editModalTitle", newValue); }} />

비워두면 기본 제목이 표시됩니다

{ const newValue = e.target.value; setLocalInputs((prev) => ({ ...prev, editModalDescription: newValue })); onUpdateProperty("componentConfig.action", { ...config.action, editModalDescription: newValue, }); // webTypeConfig에도 저장 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", { ...config.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", { ...config.action, targetUrl: newValue, }); }} />

URL을 입력하면 화면 선택보다 우선 적용됩니다

)} {/* 🔥 NEW: 제어관리 기능 섹션 */}

🔧 고급 기능

버튼 액션과 함께 실행될 추가 기능을 설정합니다

); };