Introduces comprehensive suppliers management with mock data, localization, and UI components Implements: - Suppliers page with data table - Localization for Danish and English - Search and filtering functionality - Responsive table design - Mock data for initial population
146 lines
4 KiB
TypeScript
146 lines
4 KiB
TypeScript
/**
|
|
* 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<SupplierItem> | 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<HTMLElement>('swp-card.suppliers-list swp-data-table-row[data-href]');
|
|
if (!row) return;
|
|
|
|
const href = row.dataset.href;
|
|
if (href) {
|
|
window.location.href = href;
|
|
}
|
|
});
|
|
}
|
|
}
|