"use client"; import { useState, useEffect } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Separator } from "@/components/ui/separator"; import { Search, Plus, Download, Upload, Trash2, Eye, Edit, FileText } from "lucide-react"; import { ScreenTemplate, LayoutData, ScreenDefinition } from "@/types/screen"; import { templateApi } from "@/lib/api/screen"; import { useAuth } from "@/hooks/useAuth"; interface TemplateManagerProps { selectedScreen: ScreenDefinition | null; onBackToList: () => void; onTemplateSelect?: (template: ScreenTemplate) => void; onTemplateApply?: (template: ScreenTemplate) => void; className?: string; } export default function TemplateManager({ selectedScreen, onBackToList, onTemplateSelect, onTemplateApply, className, }: TemplateManagerProps) { const { user } = useAuth(); const [templates, setTemplates] = useState([]); const [selectedTemplate, setSelectedTemplate] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState("my"); // 템플릿 목록 조회 useEffect(() => { const fetchTemplates = async () => { try { setIsLoading(true); const templateList = await templateApi.getTemplates({ companyCode: user?.company_code || "*", }); setTemplates(templateList); } catch (error) { console.error("템플릿 목록 조회 실패:", error); // API 호출 실패 시 기본 템플릿 목록 사용 const fallbackTemplates: ScreenTemplate[] = [ { templateId: 1, templateName: "기본 CRUD 화면", templateType: "CRUD", companyCode: "*", description: "기본적인 CRUD 기능을 제공하는 화면 템플릿", layoutData: { components: [ { id: "search-container", type: "container", position: { x: 0, y: 0 }, size: { width: 12, height: 100 }, title: "검색 영역", children: [], }, { id: "table-container", type: "container", position: { x: 0, y: 1 }, size: { width: 12, height: 300 }, title: "데이터 테이블", children: [], }, { id: "form-container", type: "container", position: { x: 0, y: 2 }, size: { width: 12, height: 200 }, title: "입력 폼", children: [], }, ], gridSettings: { columns: 12, gap: 16, padding: 16 }, }, isPublic: true, createdBy: "admin", createdDate: new Date(), }, { templateId: 2, templateName: "목록 화면", templateType: "LIST", companyCode: "*", description: "데이터 목록을 표시하는 화면 템플릿", layoutData: { components: [ { id: "filter-container", type: "container", position: { x: 0, y: 0 }, size: { width: 12, height: 80 }, title: "필터 영역", children: [], }, { id: "list-container", type: "container", position: { x: 0, y: 1 }, size: { width: 12, height: 400 }, title: "목록 영역", children: [], }, ], gridSettings: { columns: 12, gap: 16, padding: 16 }, }, isPublic: true, createdBy: "admin", createdDate: new Date(), }, { templateId: 3, templateName: "상세 화면", templateType: "DETAIL", companyCode: "*", description: "데이터 상세 정보를 표시하는 화면 템플릿", layoutData: { components: [ { id: "header-container", type: "container", position: { x: 0, y: 0 }, size: { width: 12, height: 60 }, title: "헤더 영역", children: [], }, { id: "detail-container", type: "container", position: { x: 0, y: 1 }, size: { width: 12, height: 400 }, title: "상세 정보", children: [], }, { id: "action-container", type: "container", position: { x: 0, y: 2 }, size: { width: 12, height: 80 }, title: "액션 버튼", children: [], }, ], gridSettings: { columns: 12, gap: 16, padding: 16 }, }, isPublic: true, createdBy: "admin", createdDate: new Date(), }, ]; setTemplates(fallbackTemplates); } finally { setIsLoading(false); } }; fetchTemplates(); }, [user?.company_code]); // 템플릿 검색 const filteredTemplates = templates.filter( (template) => template.templateName.toLowerCase().includes(searchTerm.toLowerCase()) || (template.description || "").toLowerCase().includes(searchTerm.toLowerCase()), ); // 템플릿 선택 const handleTemplateSelect = (template: ScreenTemplate) => { setSelectedTemplate(template); onTemplateSelect?.(template); }; // 템플릿 적용 const handleTemplateApply = (template: ScreenTemplate) => { onTemplateApply?.(template); }; // 템플릿 삭제 const handleTemplateDelete = async (templateId: number) => { if (!confirm("정말로 이 템플릿을 삭제하시겠습니까?")) return; try { await templateApi.deleteTemplate(templateId); setTemplates((prev) => prev.filter((t) => t.templateId !== templateId)); if (selectedTemplate?.templateId === templateId) { setSelectedTemplate(null); } alert("템플릿이 삭제되었습니다."); } catch (error) { console.error("템플릿 삭제 실패:", error); alert("템플릿 삭제에 실패했습니다. 다시 시도해주세요."); } }; // 새 템플릿 생성 const handleCreateTemplate = () => { // TODO: 새 템플릿 생성 모달 또는 페이지로 이동 console.log("새 템플릿 생성"); }; // 템플릿 내보내기 const handleExportTemplate = (template: ScreenTemplate) => { const dataStr = JSON.stringify(template, null, 2); const dataBlob = new Blob([dataStr], { type: "application/json" }); const url = URL.createObjectURL(dataBlob); const link = document.createElement("a"); link.href = url; link.download = `${template.templateName}.json`; link.click(); URL.revokeObjectURL(url); }; // 화면이 선택되지 않았을 때 처리 if (!selectedScreen) { return (

템플릿을 적용할 화면을 선택해주세요

화면 목록에서 화면을 선택한 후 템플릿을 관리하세요

); } return (
{/* 헤더 */}
화면 템플릿 관리
setSearchTerm(e.target.value)} className="pl-10" />
{/* 템플릿 목록 */}
{/* 템플릿 카드 목록 */}
내 템플릿 공개 템플릿
{filteredTemplates .filter((template) => (activeTab === "my" ? template.companyCode !== "*" : template.isPublic)) .map((template) => ( handleTemplateSelect(template)} >

{template.templateName}

{template.description || "설명 없음"}

{template.templateType} {template.isPublic && ( 공개 )} {template.createdBy} • {template.createdDate.toLocaleDateString()}
{template.companyCode !== "*" && ( )}
))}
{/* 선택된 템플릿 상세 정보 */}
{selectedTemplate ? ( 템플릿 상세 정보

{selectedTemplate.templateName}

{selectedTemplate.description}

{selectedTemplate.templateType}

{selectedTemplate.layoutData?.components?.length || 0}개

{selectedTemplate.layoutData?.gridSettings?.columns || 12} 컬럼, 간격:{" "} {selectedTemplate.layoutData?.gridSettings?.gap || 16}px

) : (

템플릿을 선택하면 상세 정보를 볼 수 있습니다

)}
); }