"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Plus, Trash2, ChevronDown, List } from "lucide-react"; import { WebTypeConfigPanelProps } from "@/lib/registry/types"; import { WidgetComponent, SelectTypeConfig } from "@/types/screen"; interface SelectOption { label: string; value: string; disabled?: boolean; } export const SelectConfigPanel: React.FC = ({ component, onUpdateComponent, onUpdateProperty, }) => { const widget = component as WidgetComponent; const config = (widget.webTypeConfig as SelectTypeConfig) || {}; // 로컬 상태 const [localConfig, setLocalConfig] = useState({ options: config.options || [ { label: "옵션 1", value: "option1" }, { label: "옵션 2", value: "option2" }, ], multiple: config.multiple || false, searchable: config.searchable || false, placeholder: config.placeholder || "선택하세요", defaultValue: config.defaultValue || "", required: config.required || false, readonly: config.readonly || false, emptyMessage: config.emptyMessage || "선택 가능한 옵션이 없습니다", }); // 새 옵션 추가용 상태 const [newOptionLabel, setNewOptionLabel] = useState(""); const [newOptionValue, setNewOptionValue] = useState(""); const [bulkOptions, setBulkOptions] = useState(""); // 입력 필드용 로컬 상태 const [localInputs, setLocalInputs] = useState({ placeholder: config.placeholder || "", emptyMessage: config.emptyMessage || "", }); // 컴포넌트 변경 시 로컬 상태 동기화 useEffect(() => { const currentConfig = (widget.webTypeConfig as SelectTypeConfig) || {}; setLocalConfig({ options: currentConfig.options || [ { label: "옵션 1", value: "option1" }, { label: "옵션 2", value: "option2" }, ], multiple: currentConfig.multiple || false, searchable: currentConfig.searchable || false, placeholder: currentConfig.placeholder || "선택하세요", defaultValue: currentConfig.defaultValue || "", required: currentConfig.required || false, readonly: currentConfig.readonly || false, emptyMessage: currentConfig.emptyMessage || "선택 가능한 옵션이 없습니다", }); // 입력 필드 로컬 상태도 동기화 setLocalInputs({ placeholder: currentConfig.placeholder || "", emptyMessage: currentConfig.emptyMessage || "", }); }, [widget.webTypeConfig]); // 설정 업데이트 핸들러 const updateConfig = (field: keyof SelectTypeConfig, value: any) => { const newConfig = { ...localConfig, [field]: value }; setLocalConfig(newConfig); onUpdateProperty("webTypeConfig", newConfig); }; // 옵션 추가 const addOption = () => { if (!newOptionLabel.trim() || !newOptionValue.trim()) return; const newOption: SelectOption = { label: newOptionLabel.trim(), value: newOptionValue.trim(), }; const newOptions = [...localConfig.options, newOption]; updateConfig("options", newOptions); setNewOptionLabel(""); setNewOptionValue(""); }; // 옵션 제거 const removeOption = (index: number) => { const newOptions = localConfig.options.filter((_, i) => i !== index); updateConfig("options", newOptions); }; // 옵션 업데이트 (입력 필드용 - 로컬 상태만) const updateOptionLocal = (index: number, field: keyof SelectOption, value: any) => { const newOptions = [...localConfig.options]; newOptions[index] = { ...newOptions[index], [field]: value }; setLocalConfig({ ...localConfig, options: newOptions }); }; // 옵션 업데이트 완료 (onBlur) const handleOptionBlur = () => { onUpdateProperty("webTypeConfig", localConfig); }; // 벌크 옵션 추가 const addBulkOptions = () => { if (!bulkOptions.trim()) return; const lines = bulkOptions.trim().split("\n"); const newOptions: SelectOption[] = []; lines.forEach((line) => { const trimmed = line.trim(); if (!trimmed) return; if (trimmed.includes("|")) { // "라벨|값" 형식 const [label, value] = trimmed.split("|").map((s) => s.trim()); if (label && value) { newOptions.push({ label, value }); } } else { // 라벨과 값이 같은 경우 newOptions.push({ label: trimmed, value: trimmed }); } }); if (newOptions.length > 0) { const combinedOptions = [...localConfig.options, ...newOptions]; updateConfig("options", combinedOptions); setBulkOptions(""); } }; // 기본 옵션 세트 const defaultOptionSets = { yesno: [ { label: "예", value: "Y" }, { label: "아니오", value: "N" }, ], status: [ { label: "활성", value: "active" }, { label: "비활성", value: "inactive" }, { label: "대기", value: "pending" }, ], priority: [ { label: "높음", value: "high" }, { label: "보통", value: "medium" }, { label: "낮음", value: "low" }, ], }; const applyDefaultSet = (setName: keyof typeof defaultOptionSets) => { updateConfig("options", defaultOptionSets[setName]); }; return ( 선택박스 설정 드롭다운 선택박스의 옵션과 동작을 설정합니다. {/* 기본 설정 */}

기본 설정

setLocalInputs({ ...localInputs, placeholder: e.target.value })} onBlur={() => updateConfig("placeholder", localInputs.placeholder)} placeholder="선택하세요" className="text-xs" />
setLocalInputs({ ...localInputs, emptyMessage: e.target.value })} onBlur={() => updateConfig("emptyMessage", localInputs.emptyMessage)} placeholder="선택 가능한 옵션이 없습니다" className="text-xs" />

여러 옵션을 선택할 수 있습니다.

updateConfig("multiple", checked)} />

옵션을 검색할 수 있습니다.

updateConfig("searchable", checked)} />
{/* 기본 옵션 세트 */}

기본 옵션 세트

{/* 옵션 관리 */}

옵션 관리

{/* 개별 옵션 추가 */}
setNewOptionLabel(e.target.value)} placeholder="라벨" className="flex-1 text-xs" /> setNewOptionValue(e.target.value)} placeholder="값" className="flex-1 text-xs" />
{/* 벌크 옵션 추가 */}