diff --git a/app/globals.css b/app/globals.css index 3028556..f949a13 100644 --- a/app/globals.css +++ b/app/globals.css @@ -267,3 +267,52 @@ ul { .mt-4 { margin-top: 1rem; } .mb-4 { margin-bottom: 1rem; } .text-center { text-align: center; } + +/* Print Styles */ +@media print { + /* Remove scroll contexts to allow thead to repeat */ + .table-container { + overflow: visible !important; + overflow-x: visible !important; + border: none !important; + } + + thead { + display: table-header-group; + } + + tr { + page-break-inside: avoid; + break-inside: avoid; + } + + .glass { + box-shadow: none !important; + border: none !important; + background: transparent !important; + } + + /* Hide UI elements unnecessary for print */ + .btn, .input-field, .navbar { + display: none !important; + } + + body { + background-color: white !important; + color: black !important; + } + + .data-table th { + color: black !important; + border-bottom: 2px solid black !important; + } + + .data-table td { + border-bottom: 1px solid #ccc !important; + } + + .text-muted { + color: #555 !important; + } +} + diff --git a/app/print/page.js b/app/print/page.js index b60b41e..9e5957a 100644 --- a/app/print/page.js +++ b/app/print/page.js @@ -2,11 +2,13 @@ import { useEffect, useState } from "react"; import QRCode from "react-qr-code"; -import { Printer, AlertCircle } from "lucide-react"; +import { Printer, AlertCircle, Filter, Search, Tag, CheckCircle2 } from "lucide-react"; export default function PrintPage() { const [items, setItems] = useState([]); const [selectedIds, setSelectedIds] = useState(new Set()); + const [selectedCategory, setSelectedCategory] = useState(""); + const [searchQuery, setSearchQuery] = useState(""); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -27,6 +29,21 @@ export default function PrintPage() { fetchItems(); }, []); + const uniqueCategories = [ + ...new Set(items.map(item => item.category?.trim() || "Uncategorized")) + ].filter(Boolean).sort(); + + const filteredItems = items.filter(item => { + const itemCat = item.category?.trim() || "Uncategorized"; + const matchesCategory = selectedCategory === "" || itemCat === selectedCategory; + const matchesSearch = searchQuery === "" || + item.name?.toLowerCase().includes(searchQuery.toLowerCase()) || + (item.qrCodeId && item.qrCodeId.toLowerCase().includes(searchQuery.toLowerCase())); + return matchesCategory && matchesSearch; + }); + + const isAllFilteredSelected = filteredItems.length > 0 && filteredItems.every(i => selectedIds.has(i.id)); + const handlePrint = () => { if (selectedIds.size === 0) return alert("Please select at least one label to print."); window.print(); @@ -39,12 +56,32 @@ export default function PrintPage() { setSelectedIds(next); }; - const toggleAll = () => { - if (selectedIds.size === items.length) setSelectedIds(new Set()); - else setSelectedIds(new Set(items.map(i => i.id))); + const toggleFilteredAll = () => { + const next = new Set(selectedIds); + if (isAllFilteredSelected) { + filteredItems.forEach(i => next.delete(i.id)); + } else { + filteredItems.forEach(i => next.add(i.id)); + } + setSelectedIds(next); + }; + + const selectOnlyCurrentFiltered = () => { + const next = new Set(); + filteredItems.forEach(i => next.add(i.id)); + setSelectedIds(next); + }; + + const selectAll = () => { + setSelectedIds(new Set(items.map(i => i.id))); + }; + + const deselectAll = () => { + setSelectedIds(new Set()); }; const itemsToPrint = items.filter(i => selectedIds.has(i.id)); + const sheetCount = Math.ceil(itemsToPrint.length / 30); if (loading) return