/** * Suppliers Controller * * Handles: * - Fuzzy search with Fuse.js * - Row click navigation */ import Fuse from 'fuse.js'; interface SupplierItem { name: string; contact: string; city: string; element: HTMLElement; } export class SuppliersController { private fuse: Fuse | null = null; private suppliers: SupplierItem[] = []; private searchInput: HTMLInputElement | null = null; private emptyState: HTMLElement | null = null; private dataTable: HTMLElement | null = null; constructor() { // Only initialize if we're on the suppliers page const suppliersTable = document.querySelector('swp-card.suppliers-list'); if (!suppliersTable) return; this.init(); } private init(): void { this.searchInput = document.getElementById('supplierSearchInput') as HTMLInputElement; this.emptyState = document.getElementById('supplierEmptyState'); this.dataTable = document.querySelector('swp-card.suppliers-list swp-data-table'); this.buildSupplierIndex(); this.setupSearch(); this.setupRowNavigation(); } private buildSupplierIndex(): void { const supplierRows = document.querySelectorAll('swp-card.suppliers-list swp-data-table-row'); supplierRows.forEach((row) => { const element = row as HTMLElement; const name = element.dataset.name || ''; const contact = element.dataset.contact || ''; const city = element.dataset.city || ''; this.suppliers.push({ name, contact, city, element }); }); } private setupSearch(): void { if (!this.searchInput) return; // Initialize Fuse.js with multiple search keys this.fuse = new Fuse(this.suppliers, { keys: ['name', 'contact', 'city'], threshold: 0.3, minMatchCharLength: 2 }); // Listen for input with debounce let debounceTimer: number; this.searchInput.addEventListener('input', (e) => { clearTimeout(debounceTimer); debounceTimer = window.setTimeout(() => { const query = (e.target as HTMLInputElement).value.trim(); this.filterSuppliers(query); }, 150); }); } private filterSuppliers(query: string): void { if (!query || query.length < 2) { this.showAll(); return; } if (!this.fuse) return; // Get matching suppliers const results = this.fuse.search(query); const matchingSuppliers = new Set(results.map(r => r.item.element)); let visibleCount = 0; // Show/hide suppliers this.suppliers.forEach(supplier => { if (matchingSuppliers.has(supplier.element)) { supplier.element.style.display = 'grid'; visibleCount++; } else { supplier.element.style.display = 'none'; } }); // Show/hide empty state this.updateEmptyState(visibleCount); } private showAll(): void { this.suppliers.forEach(supplier => { supplier.element.style.display = 'grid'; }); this.updateEmptyState(this.suppliers.length); } private updateEmptyState(visibleCount: number): void { if (!this.emptyState || !this.dataTable) return; if (visibleCount === 0) { this.emptyState.style.display = 'flex'; // Hide header when no results const header = this.dataTable.querySelector('swp-data-table-header') as HTMLElement; if (header) header.style.display = 'none'; } else { this.emptyState.style.display = 'none'; // Show header when results exist const header = this.dataTable.querySelector('swp-data-table-header') as HTMLElement; if (header) header.style.display = 'grid'; } } private setupRowNavigation(): void { // Click on rows navigates to supplier detail page document.addEventListener('click', (e) => { const row = (e.target as HTMLElement).closest('swp-card.suppliers-list swp-data-table-row[data-href]'); if (!row) return; const href = row.dataset.href; if (href) { window.location.href = href; } }); } }