Files
evidencija-rezija/app/ui/PrintPreview.tsx
Nikola Derežič 9a02124e18 feat: implement US-4 - complete print optimization with CSS media queries
- Add comprehensive CSS print media queries for A4 paper optimization
- Implement 69.6mm barcode width specification (20% larger than original 58mm)
- Apply B&W print color optimization forcing all elements to black/white
- Add page break handling to prevent table rows from splitting across pages
- Fix table cropping issue by removing excessive width and reducing container padding
- Optimize print layout with zero padding for maximum table space utilization
- Ensure header/button elements hidden from print output with proper CSS

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-14 21:44:04 +02:00

158 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { PrintBarcodeData } from '../lib/actions/printActions';
export interface PrintPreviewProps {
data: PrintBarcodeData[];
year: number;
month: number;
translations: {
title: string;
barcodesFound: string;
barcodeSingular: string;
printButton: string;
printFooter: string;
tableHeaderIndex: string;
tableHeaderBillInfo: string;
tableHeaderBarcode: string;
};
}
export const PrintPreview: React.FC<PrintPreviewProps> = ({ data, year, month, translations }) => {
return (
<>
{/* Print-specific CSS styles */}
<style jsx>{`
@media print {
@page {
size: A4;
margin: 1in;
}
body {
-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;
print-color-adjust: exact !important;
}
.print-barcode-img {
width: 69.6mm !important;
max-width: 69.6mm !important;
height: auto !important;
max-height: none !important;
}
.print-table {
page-break-inside: avoid;
}
.print-container {
padding: 0 !important;
}
.print-table tr {
page-break-inside: avoid;
page-break-after: auto;
}
.print-table thead {
display: table-header-group;
}
/* Optimize for B&W printing */
* {
color: black !important;
background: white !important;
box-shadow: none !important;
text-shadow: none !important;
}
.print-table th,
.print-table td {
border: 2px solid black !important;
background: white !important;
}
.print-table thead tr {
background: #f5f5f5 !important;
}
}
`}</style>
<div className="min-h-screen bg-white">
{/* Header section - hidden in print */}
<div className="p-6 border-b border-gray-200 print:hidden">
<h1 className="text-3xl font-bold text-gray-900 mb-2">
{translations.title}
</h1>
<p className="text-lg text-gray-600 mb-4">
{year}-{month.toString().padStart(2, '0')} {data.length} {data.length === 1 ? translations.barcodeSingular : translations.barcodesFound}
</p>
<button
onClick={() => window.print()}
className="btn btn-primary"
>
🖨 {translations.printButton}
</button>
</div>
{/* Print content */}
<div className="p-6 print-container">
<table className="w-full border-collapse border-2 border-gray-800 print-table">
<thead>
<tr className="bg-gray-100">
<th className="border-2 border-gray-800 px-3 py-2 text-center font-bold text-sm w-16">
{translations.tableHeaderIndex}
</th>
<th className="border-2 border-gray-800 px-3 py-2 text-left font-bold text-sm">
{translations.tableHeaderBillInfo}
</th>
<th className="border-2 border-gray-800 px-3 py-2 text-center font-bold text-sm w-64">
{translations.tableHeaderBarcode}
</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={`${item.locationName}-${item.billName}`} className="hover:bg-gray-50">
<td className="border-2 border-gray-800 px-3 py-4 text-center font-mono text-sm font-medium">
{(index + 1).toString().padStart(2, '0')}
</td>
<td className="border-2 border-gray-800 px-3 py-4">
<div className="space-y-1">
<div className="font-bold text-sm text-gray-900">
📅 {item.yearMonth}
</div>
<div className="font-medium text-sm text-gray-800">
🏠 {item.locationName}
</div>
<div className="text-sm text-gray-700">
📋 {item.billName}
</div>
</div>
</td>
<td className="border-2 border-gray-800 px-3 py-1.5 text-center">
<div className="flex justify-center items-center">
<img
src={item.barcodeImage.startsWith('data:') ? item.barcodeImage : `data:image/png;base64,${item.barcodeImage}`}
alt={`Barcode for ${item.billName}`}
className="max-h-28 w-auto border border-gray-300 rounded print-barcode-img"
style={{ maxWidth: '270px' }}
/>
</div>
</td>
</tr>
))}
</tbody>
</table>
{/* Print footer - only visible when printing */}
<div className="mt-6 text-center text-xs text-gray-500 hidden print:block">
<p>{translations.printFooter.replace('{date}', new Date().toLocaleDateString())}</p>
</div>
</div>
</div>
</>
);
};