"use client"; import React from "react"; import { ComponentData, WebType, WidgetComponent, DateTypeConfig, NumberTypeConfig, SelectTypeConfig, TextTypeConfig, TextareaTypeConfig, CheckboxTypeConfig, RadioTypeConfig, FileTypeConfig, CodeTypeConfig, EntityTypeConfig, } from "@/types/screen"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; // import { Checkbox } from "@/components/ui/checkbox"; // import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Database, Type, Hash, List, AlignLeft, CheckSquare, Radio, Calendar, Code, Building, File, Group, ChevronDown, ChevronRight, Search, RotateCcw, Plus, Edit, Trash2, } from "lucide-react"; interface RealtimePreviewProps { component: ComponentData; isSelected?: boolean; onClick?: (e?: React.MouseEvent) => void; onDragStart?: (e: React.DragEvent) => void; onDragEnd?: () => void; onGroupToggle?: (groupId: string) => void; // 그룹 접기/펼치기 children?: React.ReactNode; // 그룹 내 자식 컴포넌트들 } // 웹 타입에 따른 위젯 렌더링 const renderWidget = (component: ComponentData) => { const { widgetType, label, placeholder, required, readonly, columnName, style } = component; // 디버깅: 실제 widgetType 값 확인 console.log("RealtimePreview - widgetType:", widgetType, "columnName:", columnName); // 사용자가 테두리를 설정했는지 확인 const hasCustomBorder = style && (style.borderWidth || style.borderStyle || style.borderColor || style.border); // 기본 테두리 제거 여부 결정 - Shadcn UI 기본 border 클래스를 덮어쓰기 const borderClass = hasCustomBorder ? "!border-0" : ""; const commonProps = { placeholder: placeholder || "입력하세요...", disabled: readonly, required: required, className: `w-full h-full ${borderClass}`, }; switch (widgetType) { case "text": case "email": case "tel": { const widget = component as WidgetComponent; const config = widget.webTypeConfig as TextTypeConfig | undefined; // 입력 타입에 따른 처리 const isAutoInput = widget.inputType === "auto"; // 자동 값 생성 함수 const getAutoValue = (autoValueType: string) => { switch (autoValueType) { case "current_datetime": return new Date().toLocaleString("ko-KR"); case "current_date": return new Date().toLocaleDateString("ko-KR"); case "current_time": return new Date().toLocaleTimeString("ko-KR"); case "current_user": return "현재사용자"; case "uuid": return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; const v = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); }); case "sequence": return "SEQ_001"; case "user_defined": return "사용자정의값"; default: return "자동생성값"; } }; // 자동 값 플레이스홀더 생성 함수 const getAutoPlaceholder = (autoValueType: string) => { switch (autoValueType) { case "current_datetime": return "현재 날짜시간"; case "current_date": return "현재 날짜"; case "current_time": return "현재 시간"; case "current_user": return "현재 사용자"; case "uuid": return "UUID"; case "sequence": return "시퀀스"; case "user_defined": return "사용자 정의"; default: return "자동 생성됨"; } }; // 플레이스홀더 처리 const finalPlaceholder = isAutoInput ? getAutoPlaceholder(widget.autoValueType || "current_datetime") : config?.placeholder || placeholder || "텍스트를 입력하세요"; // 자동 값 처리 const autoValue = isAutoInput ? getAutoValue(widget.autoValueType || "current_datetime") : ""; const inputType = widgetType === "email" ? "email" : widgetType === "tel" ? "tel" : "text"; // 형식별 패턴 생성 const getPatternByFormat = (format: string) => { switch (format) { case "korean": return "[가-힣\\s]*"; case "english": return "[a-zA-Z\\s]*"; case "alphanumeric": return "[a-zA-Z0-9]*"; case "numeric": return "[0-9]*"; case "email": return "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"; case "phone": return "\\d{3}-\\d{4}-\\d{4}"; case "url": return "https?://[\\w\\-]+(\\.[\\w\\-]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?"; default: return config?.pattern || undefined; } }; // 입력 검증 함수 const handleInputChange = (e: React.ChangeEvent) => { const value = e.target.value; // 형식별 실시간 검증 if (config?.format && config.format !== "none") { const pattern = getPatternByFormat(config.format); if (pattern) { const regex = new RegExp(`^${pattern}$`); if (value && !regex.test(value)) { // 유효하지 않은 입력은 무시 e.preventDefault(); return; } } } // 길이 제한 검증 if (config?.maxLength && value.length > config.maxLength) { e.preventDefault(); return; } }; const inputProps = { ...commonProps, placeholder: finalPlaceholder, value: isAutoInput ? autoValue : undefined, // 자동입력인 경우 자동 값 표시 minLength: config?.minLength, maxLength: config?.maxLength, pattern: getPatternByFormat(config?.format || "none"), onInput: handleInputChange, onChange: () => {}, // 읽기 전용으로 처리 readOnly: readonly || isAutoInput, // 자동입력인 경우 읽기 전용 className: `w-full h-full ${borderClass} ${isAutoInput ? "bg-gray-50 text-gray-600" : ""}`, }; // multiline이면 Textarea로 렌더링 if (config?.multiline) { return