import { useCallback, useRef, useEffect, useMemo } from 'react'; // Components import { ClosedRequestsHeader } from './components/ClosedRequestsHeader'; import { ClosedRequestsList } from './components/ClosedRequestsList'; import { ClosedRequestsEmpty } from './components/ClosedRequestsEmpty'; import { ClosedRequestsPagination } from './components/ClosedRequestsPagination'; // Hooks import { useClosedRequests } from './hooks/useClosedRequests'; import { useClosedRequestsFilters } from './hooks/useClosedRequestsFilters'; // Types import type { ClosedRequestsProps } from './types/closedRequests.types'; // Utils & Factory import { getUserFilterType } from '@/utils/userFilterUtils'; import { getClosedRequestsFilters } from '@/flows'; import { TokenManager } from '@/utils/tokenManager'; export function ClosedRequests({ onViewRequest }: ClosedRequestsProps) { // Data fetching hook const closedRequests = useClosedRequests({ itemsPerPage: 10 }); // Filters hook - use ref to avoid circular dependency const fetchRef = useRef(closedRequests.fetchRequests); fetchRef.current = closedRequests.fetchRequests; const filters = useClosedRequestsFilters(); // Get user filter type and corresponding filter component (plug-and-play pattern) const userFilterType = useMemo(() => { try { const userData = TokenManager.getUserData(); return getUserFilterType(userData); } catch (error) { console.error('[ClosedRequests] Error getting user filter type:', error); return 'STANDARD' as const; } }, []); // Get the appropriate filter component based on user type const ClosedRequestsFiltersComponent = useMemo(() => { return getClosedRequestsFilters(userFilterType); }, [userFilterType]); const isDealer = userFilterType === 'DEALER'; const prevFiltersRef = useRef({ searchTerm: filters.searchTerm, statusFilter: filters.statusFilter, priorityFilter: filters.priorityFilter, templateTypeFilter: filters.templateTypeFilter, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }); const hasInitialFetchRun = useRef(false); // Initial fetch on mount - use stored page from Redux useEffect(() => { const storedPage = filters.currentPage || 1; fetchRef.current(storedPage, { search: filters.searchTerm || undefined, status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined, // Only include priority and templateType filters if user is not a dealer priority: !isDealer && filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined, templateType: !isDealer && filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }); hasInitialFetchRun.current = true; // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDealer]); // Re-fetch if dealer status changes // Track filter changes and refetch useEffect(() => { if (!hasInitialFetchRun.current) return; const prev = prevFiltersRef.current; const hasChanged = prev.searchTerm !== filters.searchTerm || prev.statusFilter !== filters.statusFilter || prev.priorityFilter !== filters.priorityFilter || prev.templateTypeFilter !== filters.templateTypeFilter || prev.sortBy !== filters.sortBy || prev.sortOrder !== filters.sortOrder; if (!hasChanged) return; // No actual change, skip // Debounce search const timeoutId = setTimeout(() => { filters.setCurrentPage(1); // Reset to page 1 when filters change fetchRef.current(1, { search: filters.searchTerm || undefined, status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined, priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined, templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }); // Update previous values prevFiltersRef.current = { searchTerm: filters.searchTerm, statusFilter: filters.statusFilter, priorityFilter: filters.priorityFilter, templateTypeFilter: filters.templateTypeFilter, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }; }, filters.searchTerm !== prev.searchTerm ? 500 : 0); return () => clearTimeout(timeoutId); // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters.searchTerm, filters.statusFilter, filters.priorityFilter, filters.templateTypeFilter, filters.sortBy, filters.sortOrder, isDealer]); // Page change handler const handlePageChange = useCallback( (newPage: number) => { if (newPage >= 1 && newPage <= closedRequests.pagination.totalPages) { filters.setCurrentPage(newPage); // Update page in Redux closedRequests.fetchRequests(newPage, { search: filters.searchTerm || undefined, status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined, priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined, templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }); } }, [closedRequests, filters] ); // Refresh handler const handleRefresh = useCallback(() => { closedRequests.handleRefresh({ search: filters.searchTerm || undefined, status: filters.statusFilter !== 'all' ? filters.statusFilter : undefined, priority: filters.priorityFilter !== 'all' ? filters.priorityFilter : undefined, templateType: filters.templateTypeFilter !== 'all' ? filters.templateTypeFilter : undefined, sortBy: filters.sortBy, sortOrder: filters.sortOrder, }); }, [closedRequests, filters]); return (