/** * Optimized List Hook * Provides memoized filtering, sorting, and pagination for large lists */ import { useMemo } from 'react'; export interface UseOptimizedListOptions { items: T[]; searchTerm?: string; searchFields?: (keyof T)[]; sortField?: keyof T; sortDirection?: 'asc' | 'desc'; pageSize?: number; currentPage?: number; } export interface UseOptimizedListResult { filteredItems: T[]; paginatedItems: T[]; totalCount: number; pageCount: number; } export function useOptimizedList>({ items, searchTerm = '', searchFields = [], sortField, sortDirection = 'asc', pageSize, currentPage = 1, }: UseOptimizedListOptions): UseOptimizedListResult { // Memoized filtering const filteredItems = useMemo(() => { if (!searchTerm || searchFields.length === 0) { return items; } const lowerSearchTerm = searchTerm.toLowerCase(); return items.filter(item => searchFields.some(field => { const value = item[field]; if (value == null) return false; return String(value).toLowerCase().includes(lowerSearchTerm); }) ); }, [items, searchTerm, searchFields]); // Memoized sorting const sortedItems = useMemo(() => { if (!sortField) { return filteredItems; } return [...filteredItems].sort((a, b) => { const aValue = a[sortField]; const bValue = b[sortField]; if (aValue == null && bValue == null) return 0; if (aValue == null) return sortDirection === 'asc' ? 1 : -1; if (bValue == null) return sortDirection === 'asc' ? -1 : 1; if (typeof aValue === 'string' && typeof bValue === 'string') { return sortDirection === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); } if (typeof aValue === 'number' && typeof bValue === 'number') { return sortDirection === 'asc' ? aValue - bValue : bValue - aValue; } return 0; }); }, [filteredItems, sortField, sortDirection]); // Memoized pagination const paginatedItems = useMemo(() => { if (!pageSize) { return sortedItems; } const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; return sortedItems.slice(startIndex, endIndex); }, [sortedItems, pageSize, currentPage]); // Calculate page count const pageCount = useMemo(() => { if (!pageSize) return 1; return Math.ceil(sortedItems.length / pageSize); }, [sortedItems.length, pageSize]); return { filteredItems: sortedItems, paginatedItems, totalCount: sortedItems.length, pageCount, }; }