"use client"; import React, { useState, useRef } from "react"; import { Button } from "@/components/ui/button"; 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 { Alert, AlertDescription } from "@/components/ui/alert"; import { ResizableDialog, ResizableDialogContent, ResizableDialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Upload, Download, FileText, AlertCircle, CheckCircle } from "lucide-react"; import { toast } from "sonner"; import { useTemplates } from "@/hooks/admin/useTemplates"; interface TemplateImportExportProps { onTemplateImported?: () => void; } interface ImportData { template_code: string; template_name: string; template_name_eng?: string; description?: string; category: string; icon_name?: string; default_size?: { width: number; height: number; }; layout_config: any; } export function TemplateImportExport({ onTemplateImported }: TemplateImportExportProps) { const [isImportDialogOpen, setIsImportDialogOpen] = useState(false); const [importData, setImportData] = useState(null); const [importError, setImportError] = useState(""); const [jsonInput, setJsonInput] = useState(""); const fileInputRef = useRef(null); const { importTemplate, isImporting } = useTemplates(); // 파일 업로드 핸들러 const handleFileUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; if (file.type !== "application/json") { setImportError("JSON 파일만 업로드할 수 있습니다."); return; } const reader = new FileReader(); reader.onload = (e) => { try { const content = e.target?.result as string; const data = JSON.parse(content); validateAndSetImportData(data); setJsonInput(JSON.stringify(data, null, 2)); } catch (error) { setImportError("유효하지 않은 JSON 파일입니다."); } }; reader.readAsText(file); }; // JSON 텍스트 입력 핸들러 const handleJsonInputChange = (value: string) => { setJsonInput(value); if (!value.trim()) { setImportData(null); setImportError(""); return; } try { const data = JSON.parse(value); validateAndSetImportData(data); } catch (error) { setImportError("유효하지 않은 JSON 형식입니다."); setImportData(null); } }; // 가져오기 데이터 검증 const validateAndSetImportData = (data: any) => { setImportError(""); // 필수 필드 검증 const requiredFields = ["template_code", "template_name", "category", "layout_config"]; const missingFields = requiredFields.filter((field) => !data[field]); if (missingFields.length > 0) { setImportError(`필수 필드가 누락되었습니다: ${missingFields.join(", ")}`); setImportData(null); return; } // 템플릿 코드 형식 검증 if (!/^[a-z0-9_-]+$/.test(data.template_code)) { setImportError("템플릿 코드는 영문 소문자, 숫자, 하이픈, 언더스코어만 사용할 수 있습니다."); setImportData(null); return; } // layout_config 구조 검증 if (!data.layout_config.components || !Array.isArray(data.layout_config.components)) { setImportError("layout_config.components가 올바른 배열 형태가 아닙니다."); setImportData(null); return; } setImportData(data); }; // 템플릿 가져오기 실행 const handleImport = async () => { if (!importData) return; try { await importTemplate(importData); toast.success(`템플릿 '${importData.template_name}'이 성공적으로 가져왔습니다.`); setIsImportDialogOpen(false); setImportData(null); setJsonInput(""); setImportError(""); onTemplateImported?.(); } catch (error: any) { toast.error(`템플릿 가져오기 실패: ${error.message}`); } }; // 파일 선택 트리거 const triggerFileSelect = () => { fileInputRef.current?.click(); }; return (
{/* 가져오기 버튼 */} 템플릿 가져오기
{/* 파일 업로드 영역 */} 1. JSON 파일 업로드

템플릿 JSON 파일을 선택하세요

또는 아래에 JSON 내용을 직접 입력하세요

{/* JSON 직접 입력 */} 2. JSON 직접 입력