"use client"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; import { useReportDesigner } from "@/contexts/ReportDesignerContext"; import { Plus, Copy, Trash2, Edit2, Check, X, PanelLeftClose, PanelLeftOpen } from "lucide-react"; import { MM_TO_PX } from "./ReportDesignerCanvas"; import type { ComponentConfig, ReportPage } from "@/types/report"; const THUMB_W = 80; const TYPE_COLORS: Record = { text: "#6366f1", label: "#6366f1", table: "#0891b2", image: "#16a34a", divider: "#9ca3af", signature: "#d97706", stamp: "#d97706", pageNumber: "#8b5cf6", card: "#0ea5e9", calculation: "#ec4899", barcode: "#1e293b", checkbox: "#f59e0b", }; function PageThumbnail({ page }: { page: ReportPage }) { const canvasW = page.width * MM_TO_PX; const canvasH = page.height * MM_TO_PX; const scale = THUMB_W / canvasW; const thumbH = canvasH * scale; return (
{page.components.map((comp: ComponentConfig) => (
))}
); } export function PageListPanel() { const { layoutConfig, currentPageId, addPage, deletePage, duplicatePage, reorderPages, selectPage, updatePageSettings, isPageListCollapsed, setIsPageListCollapsed, } = useReportDesigner(); const [editingPageId, setEditingPageId] = useState(null); const [editingName, setEditingName] = useState(""); const [draggedIndex, setDraggedIndex] = useState(null); const [dropTargetIndex, setDropTargetIndex] = useState(null); const handleStartEdit = (pageId: string, currentName: string) => { setEditingPageId(pageId); setEditingName(currentName); }; const handleSaveEdit = () => { if (editingPageId && editingName.trim()) { updatePageSettings(editingPageId, { page_name: editingName.trim() }); } setEditingPageId(null); setEditingName(""); }; const handleCancelEdit = () => { setEditingPageId(null); setEditingName(""); }; const handleDragStart = (e: React.DragEvent, index: number) => { setDraggedIndex(index); e.dataTransfer.effectAllowed = "move"; e.dataTransfer.setData("text/plain", String(index)); }; const handleDragOver = (e: React.DragEvent, index: number) => { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = "move"; if (draggedIndex === null || draggedIndex === index) { setDropTargetIndex(null); return; } setDropTargetIndex(index); }; const handleDrop = (e: React.DragEvent, targetIndex: number) => { e.preventDefault(); e.stopPropagation(); if (draggedIndex === null) return; if (draggedIndex !== targetIndex) { reorderPages(draggedIndex, targetIndex); } setDraggedIndex(null); setDropTargetIndex(null); }; const handleDragEnd = () => { setDraggedIndex(null); setDropTargetIndex(null); }; if (isPageListCollapsed) { return (
); } return (
{/* 헤더 */}
페이지
{/* 페이지 목록 */}
e.preventDefault()}> {layoutConfig.pages .sort((a, b) => a.page_order - b.page_order) .map((page, index) => (
handleDragStart(e, index)} onDragEnd={handleDragEnd} onDragOver={(e) => handleDragOver(e, index)} onDrop={(e) => handleDrop(e, index)} className={`group relative cursor-grab rounded-md border px-2 pt-1 pb-2 transition-all hover:shadow active:cursor-grabbing ${ page.page_id === currentPageId ? "border-indigo-400 bg-indigo-50 shadow-md ring-1 ring-indigo-200" : "border-gray-100 bg-white hover:border-gray-200" } ${draggedIndex === index ? "opacity-30" : ""} ${dropTargetIndex === index ? "border-dashed border-blue-400" : ""}`} onClick={() => selectPage(page.page_id)} > {/* 상단 우측: 액션 버튼 모음 */}
{/* 썸네일 + 제목 (하단부 배치) */}
{editingPageId === page.page_id ? (
e.stopPropagation()}> setEditingName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") handleSaveEdit(); if (e.key === "Escape") handleCancelEdit(); }} className="h-6 w-full px-1 text-center text-xs" autoFocus />
) : (
{ e.stopPropagation(); handleStartEdit(page.page_id, page.page_name); }} > {index + 1}. {page.page_name}
)}
))}
); }