'use client'; import React, { useState, useMemo } from 'react'; import { PaperType } from '@/types'; import { Search, X, Building2, Check, Filter, RotateCcw, Sparkles, Layers, ChevronDown, } from 'lucide-react'; interface PaperSelectorModalProps { isOpen: boolean; onClose: () => void; papers: PaperType[]; selectedPaperId: number; onSelectPaper: (paper: PaperType) => void; } export const PaperSelectorModal: React.FC = ({ isOpen, onClose, papers, selectedPaperId, onSelectPaper, }) => { const [searchTerm, setSearchTerm] = useState(''); const [selectedSupplier, setSelectedSupplier] = useState('all'); const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedSize, setSelectedSize] = useState('all'); const [selectedGsm, setSelectedGsm] = useState('all'); // Danh sách nhà cung cấp duy nhất const suppliers = useMemo(() => { const list = Array.from(new Set(papers.map((p) => p.supplier || 'Thuận Phát'))).filter(Boolean); return list.sort(); }, [papers]); // Phân loại danh mục giấy const getCategory = (p: PaperType): string => { const name = p.name.toLowerCase(); const code = p.code.toLowerCase(); if (name.includes('ivory') || code.startsWith('i')) return 'Ivory'; if (name.includes('couche') || code.startsWith('c')) return 'Couche'; if (name.includes('fort') || name.includes('ford') || code.startsWith('f')) return 'Fort'; if (name.includes('duplex') || code.startsWith('d')) return 'Duplex'; if (name.includes('bristol') || code.startsWith('b')) return 'Bristol'; if (name.includes('decal')) return 'Decal'; if (name.includes('kraft')) return 'Kraft'; return 'Khác'; }; const categories = ['Ivory', 'Couche', 'Fort', 'Duplex', 'Bristol', 'Decal', 'Kraft']; // Danh sách các khổ giấy duy nhất const sizes = useMemo(() => { const s = Array.from(new Set(papers.map((p) => `${p.parentWidthCm}x${p.parentHeightCm}`))); return s.sort(); }, [papers]); // Danh sách các mức định lượng gsm duy nhất const gsmList = useMemo(() => { const g = Array.from(new Set(papers.map((p) => p.gsm))).filter(Boolean); return g.sort((a, b) => a - b); }, [papers]); // Lọc danh sách giấy theo các tiêu chí const filteredPapers = useMemo(() => { return papers.filter((p) => { // 1. Lọc theo NCC if (selectedSupplier !== 'all') { const supp = p.supplier || 'Thuận Phát'; if (supp !== selectedSupplier) return false; } // 2. Lọc theo danh mục loại giấy if (selectedCategory !== 'all') { const cat = getCategory(p); if (cat !== selectedCategory) return false; } // 3. Lọc theo khổ giấy mẹ if (selectedSize !== 'all') { const sizeStr = `${p.parentWidthCm}x${p.parentHeightCm}`; if (sizeStr !== selectedSize) return false; } // 4. Lọc theo định lượng gsm if (selectedGsm !== 'all') { if (p.gsm !== Number(selectedGsm)) return false; } // 5. Tìm kiếm từ khóa tự do (mã, tên, hiệu, ncc) if (searchTerm.trim()) { const term = searchTerm.toLowerCase().trim(); const matchName = p.name.toLowerCase().includes(term); const matchCode = p.code.toLowerCase().includes(term); const matchDesc = (p.description || '').toLowerCase().includes(term); const matchSupp = (p.supplier || '').toLowerCase().includes(term); if (!matchName && !matchCode && !matchDesc && !matchSupp) return false; } return true; }); }, [papers, searchTerm, selectedSupplier, selectedCategory, selectedSize, selectedGsm]); const handleResetFilters = () => { setSearchTerm(''); setSelectedSupplier('all'); setSelectedCategory('all'); setSelectedSize('all'); setSelectedGsm('all'); }; const getCategoryColor = (cat: string) => { switch (cat) { case 'Ivory': return 'bg-purple-100 text-purple-700 border-purple-200'; case 'Couche': return 'bg-blue-100 text-blue-700 border-blue-200'; case 'Fort': return 'bg-emerald-100 text-emerald-700 border-emerald-200'; case 'Duplex': return 'bg-amber-100 text-amber-700 border-amber-200'; case 'Bristol': return 'bg-indigo-100 text-indigo-700 border-indigo-200'; case 'Decal': return 'bg-rose-100 text-rose-700 border-rose-200'; case 'Kraft': return 'bg-orange-100 text-orange-700 border-orange-200'; default: return 'bg-slate-100 text-slate-700 border-slate-200'; } }; if (!isOpen) return null; return (
{/* Header Modal */}

Chọn & Lọc Bảng Giá Giấy In {papers.length} loại

Tìm kiếm thông minh theo Nhà Cung Cấp, Loại Giấy, Khổ & Định Lượng

{/* Thanh công cụ tìm kiếm & Bộ lọc (Search & Filters Panel) */}
{/* Hàng 1: Ô tìm kiếm từ khóa */}
setSearchTerm(e.target.value)} placeholder="Nhập mã giấy, tên giấy, thương hiệu (Indo, Nevia, Oji...), nhà cung cấp..." className="w-full bg-white border border-slate-300 rounded-xl pl-10 pr-10 py-2.5 text-xs text-slate-900 placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 shadow-2xs font-medium" /> {searchTerm && ( )}
{/* Hàng 2: Các bộ lọc dạng Dropdown / Chips */}
{/* Lọc theo NCC */}
{/* Lọc theo Loại Giấy */}
{/* Lọc theo Khổ Giấy */}
{/* Lọc theo Định Lượng GSM */}
{/* Dải thông tin trạng thái lọc */}
Tìm thấy {filteredPapers.length} / {papers.length} loại giấy {selectedSupplier !== 'all' && • NCC: {selectedSupplier}} {selectedCategory !== 'all' && • Loại: {selectedCategory}} {(searchTerm || selectedSupplier !== 'all' || selectedCategory !== 'all' || selectedSize !== 'all' || selectedGsm !== 'all') && ( )}
{/* Danh sách thẻ giấy (Scrollable Cards Grid) */}
{filteredPapers.length === 0 ? (

Không tìm thấy loại giấy nào phù hợp với bộ lọc.

) : (
{filteredPapers.map((paper) => { const isSelected = paper.id === selectedPaperId; const cat = getCategory(paper); const priceAbove = paper.priceAbove500 || paper.pricePerRam || 0; const priceBelow = paper.priceBelow500 || priceAbove; const unitAbove = Math.round(priceAbove / 500); const unitBelow = Math.round(priceBelow / 500); return (
{ onSelectPaper(paper); onClose(); }} className={`relative p-3.5 rounded-xl border transition-all cursor-pointer flex flex-col justify-between ${ isSelected ? 'border-blue-600 bg-blue-50/40 shadow-sm ring-2 ring-blue-500/20' : 'border-slate-200 hover:border-blue-300 hover:bg-slate-50/80' }`} > {/* Hàng trên: Badges */}
{/* Badge Loại giấy */} {cat} {/* Badge NCC */} {paper.supplier || 'Thuận Phát'} {/* Badge Khổ giấy */} {paper.parentWidthCm} × {paper.parentHeightCm} cm
{isSelected && ( Đang chọn )}
{/* Tên giấy & Mã */}

{paper.name}

{paper.description && (

{paper.description}

)}
{/* Bảng giá: Giá trên 500 tờ (trên ram) và Giá dưới 500 tờ (dưới ram) */}
Giá ≥ 500 tờ (Trên ram) {priceAbove.toLocaleString('vi-VN')}đ ~{unitAbove.toLocaleString('vi-VN')}đ / tờ
Giá < 500 tờ (Dưới ram) {priceBelow.toLocaleString('vi-VN')}đ ~{unitBelow.toLocaleString('vi-VN')}đ / tờ
); })}
)}
{/* Footer */}
Mẹo: Click vào bất kỳ loại giấy nào để chọn ngay vào bài tính giá
); };