"use client"; import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Separator } from "@/components/ui/separator"; import { Badge } from "@/components/ui/badge"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { Plus, Trash2, GripVertical, ChevronUp, ChevronDown, Settings as SettingsIcon, Check, ChevronsUpDown } from "lucide-react"; import { cn } from "@/lib/utils"; import { FormSectionConfig, FormFieldConfig, OptionalFieldGroupConfig, FIELD_TYPE_OPTIONS } from "../types"; import { defaultFieldConfig, generateFieldId, generateUniqueId } from "../config"; // 도움말 텍스트 컴포넌트 const HelpText = ({ children }: { children: React.ReactNode }) => (

{children}

); // 테이블 컬럼 정보 타입 interface TableColumnInfo { name: string; type: string; label: string; } interface SectionLayoutModalProps { open: boolean; onOpenChange: (open: boolean) => void; section: FormSectionConfig; onSave: (updates: Partial) => void; onOpenFieldDetail: (field: FormFieldConfig) => void; // 저장 테이블의 컬럼 정보 tableName?: string; tableColumns?: TableColumnInfo[]; } export function SectionLayoutModal({ open, onOpenChange, section, onSave, onOpenFieldDetail, tableName = "", tableColumns = [], }: SectionLayoutModalProps) { // 컬럼 선택 Popover 상태 (필드별) const [columnSearchOpen, setColumnSearchOpen] = useState>({}); // 로컬 상태로 섹션 관리 (fields가 없으면 빈 배열로 초기화) const [localSection, setLocalSection] = useState(() => ({ ...section, fields: section.fields || [], })); // open이 변경될 때마다 데이터 동기화 useEffect(() => { if (open) { setLocalSection({ ...section, fields: section.fields || [], }); } }, [open, section]); // 섹션 업데이트 함수 const updateSection = (updates: Partial) => { setLocalSection((prev) => ({ ...prev, ...updates })); }; // 저장 함수 const handleSave = () => { onSave(localSection); onOpenChange(false); }; // fields 배열 (안전한 접근) const fields = localSection.fields || []; // 필드 추가 const addField = () => { const newField: FormFieldConfig = { ...defaultFieldConfig, id: generateFieldId(), label: `새 필드 ${fields.length + 1}`, columnName: `field_${fields.length + 1}`, }; updateSection({ fields: [...fields, newField], }); }; // 필드 삭제 const removeField = (fieldId: string) => { updateSection({ fields: fields.filter((f) => f.id !== fieldId), }); }; // 필드 업데이트 const updateField = (fieldId: string, updates: Partial) => { updateSection({ fields: fields.map((f) => (f.id === fieldId ? { ...f, ...updates } : f)), }); }; // 필드 이동 const moveField = (fieldId: string, direction: "up" | "down") => { const index = fields.findIndex((f) => f.id === fieldId); if (index === -1) return; if (direction === "up" && index === 0) return; if (direction === "down" && index === fields.length - 1) return; const newFields = [...fields]; const targetIndex = direction === "up" ? index - 1 : index + 1; [newFields[index], newFields[targetIndex]] = [newFields[targetIndex], newFields[index]]; updateSection({ fields: newFields }); }; // 필드 타입별 색상 const getFieldTypeColor = (fieldType: FormFieldConfig["fieldType"]): string => { switch (fieldType) { case "text": case "email": case "password": case "tel": return "bg-blue-50 border-blue-200 text-blue-700"; case "number": return "bg-cyan-50 border-cyan-200 text-cyan-700"; case "date": case "datetime": return "bg-purple-50 border-purple-200 text-purple-700"; case "select": return "bg-green-50 border-green-200 text-green-700"; case "checkbox": return "bg-pink-50 border-pink-200 text-pink-700"; case "textarea": return "bg-orange-50 border-orange-200 text-orange-700"; default: return "bg-gray-50 border-gray-200 text-gray-700"; } }; // 필드 타입 라벨 const getFieldTypeLabel = (fieldType: FormFieldConfig["fieldType"]): string => { const option = FIELD_TYPE_OPTIONS.find((opt) => opt.value === fieldType); return option?.label || fieldType; }; // 그리드 너비 라벨 const getGridSpanLabel = (span: number): string => { switch (span) { case 3: return "1/4"; case 4: return "1/3"; case 6: return "1/2"; case 8: return "2/3"; case 12: return "전체"; default: return `${span}/12`; } }; // 필드 상세 설정 열기 const handleOpenFieldDetail = (field: FormFieldConfig) => { // 먼저 현재 변경사항 저장 onSave(localSection); // 그 다음 필드 상세 모달 열기 onOpenFieldDetail(field); }; return ( 섹션 레이아웃: {localSection.title} 섹션의 필드 구성과 배치를 관리합니다. 필드를 추가하거나 순서를 변경할 수 있습니다.
{/* 섹션 기본 정보 */}

섹션 기본 정보

updateSection({ title: e.target.value })} className="h-7 text-xs mt-1" /> 섹션의 제목을 입력하세요 (예: 기본 정보, 배송 정보)