'use client'; import React, { useState } from 'react'; import { ImpositionResult } from '@/types'; import { Layers, Scissors, Printer, CheckCircle2, RotateCw } from 'lucide-react'; interface ImpositionVisualizerProps { imposition: ImpositionResult; productName?: string; productWidthMm: number; productHeightMm: number; } export const ImpositionVisualizer: React.FC = ({ imposition, productWidthMm, productHeightMm, }) => { const [activeTab, setActiveTab] = useState<'imposition' | 'paperCut'>('imposition'); const { printSheet, parentSheet, upsPerPrintSheet, cutsPerParentSheet, totalUpsPerParentSheet, gripperMarginMm, cols, rows, boxes, sheetEfficiencyPercent, isRotated, cutScheme, } = imposition; // Kích thước SVG tờ in máy const printW = printSheet.widthMm; const printH = printSheet.heightMm; // Kích thước SVG tờ giấy mẹ const parentW = cutScheme?.parentWidthMm || parentSheet.widthCm * 10; const parentH = cutScheme?.parentHeightMm || parentSheet.heightCm * 10; // Bảng màu cho các tờ in khi xén từ tờ mẹ const blockColors = [ { bg: '#eff6ff', stroke: '#3b82f6', text: '#1d4ed8' }, // blue { bg: '#f0fdf4', stroke: '#22c55e', text: '#15803d' }, // green { bg: '#fefce8', stroke: '#eab308', text: '#a16207' }, // yellow { bg: '#faf5ff', stroke: '#a855f7', text: '#7e22ce' }, // purple { bg: '#fff7ed', stroke: '#f97316', text: '#c2410c' }, // orange { bg: '#f0fdfa', stroke: '#14b8a6', text: '#0f766e' }, // teal { bg: '#fff1f2', stroke: '#f43f5e', text: '#be123c' }, // rose { bg: '#eef2ff', stroke: '#6366f1', text: '#4338ca' }, // indigo ]; return (
{/* Sub-tab chuyển đổi giữa Sơ đồ bình bài và Sơ đồ cắt giấy mẹ */}
{activeTab === 'imposition' ? `Khổ in: ${printW}×${printH}mm` : `Khổ mẹ: ${parentW}×${parentH}mm`}
{/* VÙNG 1: SƠ ĐỒ BÌNH BÀI TRÊN TỜ IN MÁY */} {activeTab === 'imposition' && (
{/* Hoa văn sọc vàng cho lề kẹp nhíp */} {/* Tờ in nền trắng */} {/* Đường biên vùng in hữu dụng (vùng an toàn) */} {/* Dải lề kẹp nhíp (Gripper margin) ở cạnh đáy */} ▼ Lề kẹp nhíp: {gripperMarginMm}mm ({printW >= 800 ? 'Bắt nhíp chiều 86cm' : `Bắt nhíp chiều ${Math.round(printW / 10)}cm`}) {/* Danh sách các con sản phẩm (Ups) */} {boxes.map((b) => { const isVerySmall = b.w < 50 || b.h < 35; const fontSize = Math.max(9, Math.min(13, b.w / 5)); return ( {/* Ô sản phẩm */} {/* Dấu xén (Crop marks) nhỏ ở góc nếu kích thước vừa */} {!isVerySmall && ( <> )} {/* Số thứ tự con */} #{b.index} {/* Kích thước con (nếu con đủ lớn) */} {!isVerySmall && ( {Math.round(b.w)}×{Math.round(b.h)}mm )} ); })}
Sản phẩm thành phẩm ({productWidthMm}×{productHeightMm}mm) {isRotated && ( Xoay 90° )} Lề kẹp nhíp ({gripperMarginMm}mm)
)} {/* VÙNG 2: SƠ ĐỒ CẮT XẢ GIẤY MẸ */} {activeTab === 'paperCut' && (
{/* Tờ giấy mẹ nền ngoài */} {/* Các block tờ in con sau khi xén */} {(cutScheme?.blocks || []).map((block, idx) => { const color = blockColors[idx % blockColors.length]; const fontSize = Math.max(12, Math.min(22, block.w / 18)); return ( {/* Tiêu đề tờ in con */} {block.name.split('(')[0].trim() || `Tờ in #${block.index}`} {/* Kích thước khổ xén */} {Math.round(block.w)} × {Math.round(block.h)} mm ({upsPerPrintSheet} con) ); })} {/* Các đường xén giấy (Cắt dao xén) màu đỏ nét đứt */} {(cutScheme?.cutLines || []).map((line, idx) => { const midX = (line.x1 + line.x2) / 2; const midY = (line.y1 + line.y2) / 2; return ( {/* Biểu tượng cây kéo & nhãn đường xén */} ✂ {line.label || 'Đường xén'} ); })}
{cutScheme?.cutDescription || `Cắt xả từ tờ mẹ ${parentSheet.widthCm}×${parentSheet.heightCm}cm`} 1 tờ mẹ = {cutsPerParentSheet} tờ in ({totalUpsPerParentSheet} con)
)} {/* THÔNG SỐ BÌNH TRANG VẮN TẮT */}
Số con / tờ in {upsPerPrintSheet} con {cols}×{rows} {isRotated ? '• Xoay' : ''}
Cắt xả tờ mẹ Chia {cutsPerParentSheet} {parentSheet.widthCm}×{parentSheet.heightCm}cm
Tổng con / tờ mẹ {totalUpsPerParentSheet} con {upsPerPrintSheet} × {cutsPerParentSheet}
Tận dụng giấy {sheetEfficiencyPercent}% Khổ {printW}×{printH}mm
); };