Files
thrilltrack-explorer/src-old/hooks/lists/useListItems.ts

60 lines
2.3 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { supabase } from '@/lib/supabaseClient';
import { queryKeys } from '@/lib/queryKeys';
/**
* Hook to fetch list items with entities (batch fetching to avoid N+1)
*/
export function useListItems(listId: string | undefined, enabled = true) {
return useQuery({
queryKey: queryKeys.lists.items(listId || ''),
queryFn: async () => {
if (!listId) return [];
// Get items
const { data: items, error: itemsError } = await supabase
.from('user_top_list_items')
.select('*')
.eq('list_id', listId)
.order('position', { ascending: true });
if (itemsError) throw itemsError;
if (!items || items.length === 0) return [];
// Group by entity type for batch fetching
const parkIds = items.filter(i => i.entity_type === 'park').map(i => i.entity_id);
const rideIds = items.filter(i => i.entity_type === 'ride').map(i => i.entity_id);
const companyIds = items.filter(i => i.entity_type === 'company').map(i => i.entity_id);
// Batch fetch all entities in parallel
const [parksResult, ridesResult, companiesResult] = await Promise.all([
parkIds.length > 0
? supabase.from('parks').select('id, name, slug, park_type, location_id').in('id', parkIds)
: Promise.resolve({ data: [] }),
rideIds.length > 0
? supabase.from('rides').select('id, name, slug, category, park_id').in('id', rideIds)
: Promise.resolve({ data: [] }),
companyIds.length > 0
? supabase.from('companies').select('id, name, slug, company_type').in('id', companyIds)
: Promise.resolve({ data: [] }),
]);
// Create entities map for quick lookup
const entitiesMap = new Map<string, any>();
(parksResult.data || []).forEach(p => entitiesMap.set(p.id, p));
(ridesResult.data || []).forEach(r => entitiesMap.set(r.id, r));
(companiesResult.data || []).forEach(c => entitiesMap.set(c.id, c));
// Map entities to items
return items.map(item => ({
...item,
entity: entitiesMap.get(item.entity_id),
}));
},
enabled: enabled && !!listId,
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 15 * 60 * 1000,
refetchOnWindowFocus: false,
});
}