diff --git a/frontend/src/components/PrintPreview/PrintPreview.tsx b/frontend/src/components/PrintPreview/PrintPreview.tsx new file mode 100644 index 0000000..3daa68d --- /dev/null +++ b/frontend/src/components/PrintPreview/PrintPreview.tsx @@ -0,0 +1,300 @@ +import React, { useState, useMemo, useCallback } from 'react'; +import type { YjsDocument } from '../../crdt/YjsDocument'; +import { + preparePrint, + printPages, + svgToDataUrl, + DEFAULT_PRINT_SETTINGS, + type PrintSettings, + type PrintResult, + type PageSize, + type Orientation, + type ScalePreset, +} from '../../services/printService'; +import './PrintPreview.css'; + +interface PrintPreviewProps { + yjsDoc: React.RefObject; + onClose: () => void; +} + +const PAGE_SIZES: PageSize[] = ['a4', 'a3', 'a2', 'a1']; +const SCALE_PRESETS: ScalePreset[] = ['1:50', '1:100', '1:200', 'custom']; + +const PrintPreview: React.FC = ({ yjsDoc, onClose }) => { + const [settings, setSettings] = useState({ ...DEFAULT_PRINT_SETTINGS }); + const [currentPage, setCurrentPage] = useState(0); + + const printResult: PrintResult | null = useMemo(() => { + const doc = yjsDoc?.current; + if (!doc) return null; + return preparePrint(doc, settings); + }, [yjsDoc, settings]); + + const updateSettings = useCallback((updates: Partial) => { + setSettings((prev) => ({ ...prev, ...updates })); + setCurrentPage(0); + }, []); + + const updateTitleBlock = useCallback((updates: Partial>) => { + setSettings((prev) => ({ + ...prev, + titleBlockData: { ...prev.titleBlockData!, ...updates }, + })); + }, []); + + const handlePrint = useCallback(() => { + if (printResult) { + printPages(printResult); + } + }, [printResult]); + + if (!printResult) { + return ( +
+
+
+

Druckvorschau

+ +
+
Kein Dokument verfügbar.
+
+
+ ); + } + + const { layout, pages, bbox } = printResult; + const page = pages[currentPage]; + const previewUrl = page ? svgToDataUrl(page.svg) : ''; + + return ( +
+
+ {/* Header */} +
+

Druckvorschau

+ +
+ +
+ {/* Settings sidebar */} +
+
+ Seite + + + +
+ +
+ Maßstab + + {settings.scale === 'custom' && ( + + )} +
+ +
+ Optionen + + +
+ + {settings.showTitleBlock && settings.titleBlockData && ( +
+ Titelblock + + + +
+ )} + + {/* Info */} +
+
+ Zeichnung: + {Math.round(bbox.width)} × {Math.round(bbox.height)} CAD +
+
+ Seiten: + {layout.totalPages} ({layout.cols} × {layout.rows}) +
+
+ Format: + {layout.pageWidth} × {layout.pageHeight} mm +
+
+ Maßstab: + 1:{layout.scaleValue} +
+
+
+ + {/* Preview area */} +
+ {pages.length > 0 && previewUrl ? ( + <> +
+ {`Page +
+ Seite {currentPage + 1} / {pages.length} +
+
+ + {/* Page navigation */} + {pages.length > 1 && ( +
+ + + {currentPage + 1} / {pages.length} + + +
+ )} + + {/* Page grid overview */} + {pages.length > 1 && ( +
+ {pages.map((p, i) => ( + + ))} +
+ )} + + ) : ( +
Keine Elemente zum Drucken.
+ )} +
+
+ + {/* Footer with actions */} +
+ + +
+
+
+ ); +}; + +export default PrintPreview;