"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 { Badge } from "@/components/ui/badge"; import { Upload, File, X } from "lucide-react"; import { WebTypeConfigPanelProps } from "@/lib/registry/types"; import { WidgetComponent, FileTypeConfig } from "@/types/screen"; export const FileConfigPanel: React.FC = ({ component, onUpdateComponent, onUpdateProperty, }) => { const widget = component as WidgetComponent; const config = (widget.webTypeConfig as FileTypeConfig) || {}; // 로컬 상태 const [localConfig, setLocalConfig] = useState({ multiple: config.multiple || false, maxFileSize: config.maxFileSize || 10, // MB maxFiles: config.maxFiles || 1, acceptedTypes: config.acceptedTypes || [], showPreview: config.showPreview !== false, // 기본값 true showProgress: config.showProgress !== false, // 기본값 true dragAndDrop: config.dragAndDrop !== false, // 기본값 true required: config.required || false, readonly: config.readonly || false, uploadText: config.uploadText || "파일을 선택하거나 여기에 드래그하세요", browseText: config.browseText || "파일 선택", }); // 새 파일 타입 추가용 상태 const [newFileType, setNewFileType] = useState(""); // 컴포넌트 변경 시 로컬 상태 동기화 useEffect(() => { const currentConfig = (widget.webTypeConfig as FileTypeConfig) || {}; setLocalConfig({ multiple: currentConfig.multiple || false, maxFileSize: currentConfig.maxFileSize || 10, maxFiles: currentConfig.maxFiles || 1, acceptedTypes: currentConfig.acceptedTypes || [], showPreview: currentConfig.showPreview !== false, showProgress: currentConfig.showProgress !== false, dragAndDrop: currentConfig.dragAndDrop !== false, required: currentConfig.required || false, readonly: currentConfig.readonly || false, uploadText: currentConfig.uploadText || "파일을 선택하거나 여기에 드래그하세요", browseText: currentConfig.browseText || "파일 선택", }); }, [widget.webTypeConfig]); // 설정 업데이트 핸들러 const updateConfig = (field: keyof FileTypeConfig, value: any) => { const newConfig = { ...localConfig, [field]: value }; setLocalConfig(newConfig); onUpdateProperty("webTypeConfig", newConfig); }; // 파일 타입 추가 const addFileType = () => { if (!newFileType.trim()) return; let extension = newFileType.trim(); if (!extension.startsWith(".")) { extension = "." + extension; } if (!localConfig.acceptedTypes.includes(extension)) { const newTypes = [...localConfig.acceptedTypes, extension]; updateConfig("acceptedTypes", newTypes); } setNewFileType(""); }; // 파일 타입 제거 const removeFileType = (typeToRemove: string) => { const newTypes = localConfig.acceptedTypes.filter((type) => type !== typeToRemove); updateConfig("acceptedTypes", newTypes); }; // 기본 파일 타입 세트 const defaultFileTypeSets = { images: [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"], documents: [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt"], archives: [".zip", ".rar", ".7z", ".tar", ".gz"], media: [".mp4", ".avi", ".mov", ".wmv", ".mp3", ".wav", ".flac"], web: [".html", ".css", ".js", ".json", ".xml"], all: ["*"], }; const applyFileTypeSet = (setName: keyof typeof defaultFileTypeSets) => { updateConfig("acceptedTypes", defaultFileTypeSets[setName]); }; // 파일 크기 단위 변환 const formatFileSize = (sizeInMB: number) => { if (sizeInMB < 1) { return `${(sizeInMB * 1024).toFixed(0)}KB`; } else if (sizeInMB >= 1024) { return `${(sizeInMB / 1024).toFixed(1)}GB`; } else { return `${sizeInMB}MB`; } }; return ( 파일 업로드 설정 파일 업로드 필드의 제한사항과 동작을 설정합니다. {/* 기본 설정 */}

기본 설정

updateConfig("uploadText", e.target.value)} placeholder="파일을 선택하거나 여기에 드래그하세요" className="text-xs" />
updateConfig("browseText", e.target.value)} placeholder="파일 선택" className="text-xs" />

여러 파일을 한 번에 선택할 수 있습니다.

updateConfig("multiple", checked)} />

파일을 드래그해서 업로드할 수 있습니다.

updateConfig("dragAndDrop", checked)} />
{/* 파일 제한 설정 */}

파일 제한

updateConfig("maxFileSize", parseFloat(e.target.value))} min={0.1} max={1024} step={0.1} className="flex-1 text-xs" /> MB
{localConfig.multiple && (
updateConfig("maxFiles", parseInt(e.target.value))} min={1} max={100} className="text-xs" />
)}
{/* 허용된 파일 타입 */}

허용된 파일 타입

{/* 기본 파일 타입 세트 */}
{/* 개별 파일 타입 추가 */}
setNewFileType(e.target.value)} placeholder=".pdf 또는 pdf" className="flex-1 text-xs" />
{/* 현재 허용된 타입 목록 */}
{localConfig.acceptedTypes.length === 0 ? ( 모든 파일 타입 허용 ) : ( localConfig.acceptedTypes.map((type, index) => ( {type} )) )}
{/* UI 설정 */}

UI 설정

선택된 파일의 미리보기를 표시합니다.

updateConfig("showPreview", checked)} />

업로드 진행 상황을 표시합니다.

updateConfig("showProgress", checked)} />
{/* 상태 설정 */}

상태 설정

파일이 반드시 업로드되어야 합니다.

updateConfig("required", checked)} />

파일을 업로드할 수 없습니다.

updateConfig("readonly", checked)} />
{/* 미리보기 */}

미리보기

{localConfig.uploadText}

최대 크기: {formatFileSize(localConfig.maxFileSize || 10)} {localConfig.multiple && ` • 최대 ${localConfig.maxFiles}개 파일`}
허용 타입:{" "} {localConfig.acceptedTypes.length === 0 ? "모든 파일" : localConfig.acceptedTypes.slice(0, 3).join(", ") + (localConfig.acceptedTypes.length > 3 ? ` 외 ${localConfig.acceptedTypes.length - 3}개` : "")}
{localConfig.dragAndDrop && "드래그 앤 드롭 • "} {localConfig.showPreview && "미리보기 • "} {localConfig.showProgress && "진행률 표시 • "} {localConfig.required && "필수"}
); }; FileConfigPanel.displayName = "FileConfigPanel";