"use client"; import { useRef, useState } from "react"; import { ComponentConfig } from "@/types/report"; import { useReportDesigner } from "@/contexts/ReportDesignerContext"; interface CanvasComponentProps { component: ComponentConfig; } export function CanvasComponent({ component }: CanvasComponentProps) { const { selectedComponentId, selectComponent, updateComponent } = useReportDesigner(); const [isDragging, setIsDragging] = useState(false); const [isResizing, setIsResizing] = useState(false); const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); const [resizeStart, setResizeStart] = useState({ x: 0, y: 0, width: 0, height: 0 }); const componentRef = useRef(null); const isSelected = selectedComponentId === component.id; // 드래그 시작 const handleMouseDown = (e: React.MouseEvent) => { if ((e.target as HTMLElement).classList.contains("resize-handle")) { return; } e.stopPropagation(); selectComponent(component.id); setIsDragging(true); setDragStart({ x: e.clientX - component.x, y: e.clientY - component.y, }); }; // 리사이즈 시작 const handleResizeStart = (e: React.MouseEvent) => { e.stopPropagation(); setIsResizing(true); setResizeStart({ x: e.clientX, y: e.clientY, width: component.width, height: component.height, }); }; // 마우스 이동 핸들러 (전역) useState(() => { const handleMouseMove = (e: MouseEvent) => { if (isDragging) { const newX = Math.max(0, e.clientX - dragStart.x); const newY = Math.max(0, e.clientY - dragStart.y); updateComponent(component.id, { x: newX, y: newY }); } else if (isResizing) { const deltaX = e.clientX - resizeStart.x; const deltaY = e.clientY - resizeStart.y; const newWidth = Math.max(50, resizeStart.width + deltaX); const newHeight = Math.max(30, resizeStart.height + deltaY); updateComponent(component.id, { width: newWidth, height: newHeight }); } }; const handleMouseUp = () => { setIsDragging(false); setIsResizing(false); }; if (isDragging || isResizing) { document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; } }); // 컴포넌트 타입별 렌더링 const renderContent = () => { switch (component.type) { case "text": return (
텍스트 필드
e.stopPropagation()} />
); case "label": return (
레이블
레이블 텍스트
); case "table": return (
테이블 (디테일 데이터)
품목명 수량 단가
품목1 10 50,000
품목2 5 30,000
); default: return
알 수 없는 컴포넌트
; } }; return (
{renderContent()} {/* 리사이즈 핸들 (선택된 경우만) */} {isSelected && (
)}
); }