Files
thrilltrack-explorer/src-old/lib/hooks/useOptimizedList.ts

102 lines
2.6 KiB
TypeScript

/**
* Optimized List Hook
* Provides memoized filtering, sorting, and pagination for large lists
*/
import { useMemo } from 'react';
export interface UseOptimizedListOptions<T> {
items: T[];
searchTerm?: string;
searchFields?: (keyof T)[];
sortField?: keyof T;
sortDirection?: 'asc' | 'desc';
pageSize?: number;
currentPage?: number;
}
export interface UseOptimizedListResult<T> {
filteredItems: T[];
paginatedItems: T[];
totalCount: number;
pageCount: number;
}
export function useOptimizedList<T extends Record<string, any>>({
items,
searchTerm = '',
searchFields = [],
sortField,
sortDirection = 'asc',
pageSize,
currentPage = 1,
}: UseOptimizedListOptions<T>): UseOptimizedListResult<T> {
// 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,
};
}