import { useState, useEffect, useRef } from 'react'; export function useAdminCatalog() { const [cards, setCards] = useState([]); const [loading, setLoading] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [selectedGame, setSelectedGame] = useState('all'); const [selectedRarity, setSelectedRarity] = useState('all'); const [selectedSet, setSelectedSet] = useState('all'); const [minPrice, setMinPrice] = useState(''); const [maxPrice, setMaxPrice] = useState(''); const [verifiedOnly, setVerifiedOnly] = useState(false); const [sortColumn, setSortColumn] = useState('name'); const [sortDirection, setSortDirection] = useState('asc'); const [pagination, setPagination] = useState({ page: 1, limit: 50, total: 0, pages: 0 }); const [filters, setFilters] = useState({ games: [], rarities: [], sets: [] }); const [hasMore, setHasMore] = useState(true); const [error, setError] = useState(null); const loadingMoreRef = useRef(false); const hasMoreRef = useRef(true); const abortControllerRef = useRef(null); const fetchCards = async (isLoadMore = false) => { if (isLoadMore && (loadingMoreRef.current || !hasMoreRef.current)) return; let signal; try { if (isLoadMore) { setLoadingMore(true); loadingMoreRef.current = true; } else { setLoading(true); setError(null); } abortControllerRef.current = new AbortController(); ({ signal } = abortControllerRef.current); const params = new URLSearchParams({ query: searchQuery, game: selectedGame, rarity: selectedRarity, set: selectedSet, minPrice, maxPrice, page: isLoadMore ? pagination.page + 1 : 1, limit: pagination.limit, sort: sortColumn, dir: sortDirection, verifiedOnly: verifiedOnly.toString() }); const response = await fetch(`/api/admin/cards?${params}`, { signal }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); if (signal.aborted) return; if (data.success) { const newCards = data.cards; if (isLoadMore) { setCards(prev => [...prev, ...newCards]); } else { setCards(newCards); } setPagination(data.pagination); setFilters(data.filters); setHasMore(data.pagination.hasMore); hasMoreRef.current = data.pagination.hasMore; } else { throw new Error(data.error || 'Failed to fetch cards'); } } catch (err) { if (err.name !== 'AbortError') { console.error('Error fetching admin cards:', err); setError(err.message); } } finally { if (!signal?.aborted) { setLoading(false); setLoadingMore(false); loadingMoreRef.current = false; } } }; const handleSearchChange = (value) => { setSearchQuery(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleGameChange = (value) => { setSelectedGame(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleRarityChange = (value) => { setSelectedRarity(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleSetChange = (value) => { setSelectedSet(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleMinPriceChange = (value) => { setMinPrice(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleMaxPriceChange = (value) => { setMaxPrice(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleVerifiedChange = (value) => { setVerifiedOnly(value); setPagination(prev => ({ ...prev, page: 1 })); setCards([]); }; const handleSort = (column) => { if (sortColumn === column) { setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'); } else { setSortColumn(column); setSortDirection('asc'); } }; const handleLoadMore = () => { if (!loadingMore && hasMore) { fetchCards(true); } }; const handleRefresh = () => { setPagination(prev => ({ ...prev, page: 1 })); setCards([]); fetchCards(false); }; const handleLimitChange = (limit) => { setPagination(prev => ({ ...prev, limit, page: 1 })); setCards([]); }; useEffect(() => { fetchCards(false); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { return () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); } }; }, []); return { cards, loading, loadingMore, searchQuery, selectedGame, selectedRarity, selectedSet, minPrice, maxPrice, verifiedOnly, sortColumn, sortDirection, pagination, filters, hasMore, error, handleSearchChange, handleGameChange, handleRarityChange, handleSetChange, handleMinPriceChange, handleMaxPriceChange, handleVerifiedChange, handleSort, handleLoadMore, handleRefresh, handleLimitChange, setSearchQuery, setSelectedGame, setSelectedRarity, setSelectedSet, setMinPrice, setMaxPrice, setVerifiedOnly, setCards, setPagination, setHasMore, setFilters }; }