import { useQuery } from '@tanstack/react-query'; import { SKATE_SPOT_KIND, parseSkateSpot, type SkateSpot } from '@/lib/types'; import { useSkateRelays } from '@/hooks/useSkateRelays'; import { cacheSpots, getAllCachedSpots, isOffline } from '@/lib/offlineCache'; export function useSkateSpots(limit = 100) { const { querySkateContent, getQueryKeySuffix } = useSkateRelays(); return useQuery({ queryKey: ['skate-spots', limit, getQueryKeySuffix()], queryFn: async () => { // If offline, return cached spots if (isOffline()) { console.log('[useSkateSpots] Offline, returning cached spots'); const cachedSpots = await getAllCachedSpots(); return cachedSpots.sort((a, b) => b.createdAt - a.createdAt).slice(0, limit); } const signal = AbortSignal.timeout(30000); const events = await querySkateContent( [ { kinds: [SKATE_SPOT_KIND], '#t': ['skatespot'], limit, }, ], { signal } ); const spots: SkateSpot[] = []; const spotsWithEvents: Array<{ event: typeof events[0]; spot: SkateSpot }> = []; for (const event of events) { const spot = parseSkateSpot(event); if (spot) { spots.push(spot); spotsWithEvents.push({ event, spot }); } else { console.warn('[useSkateSpots] Failed to parse event:', event); } } console.log('[useSkateSpots] Parsed spots:', spots.length); // Cache spots in the background for offline use if (spotsWithEvents.length > 0) { cacheSpots(spotsWithEvents).catch(err => console.warn('[useSkateSpots] Failed to cache spots:', err) ); } // Sort by created_at descending return spots.sort((a, b) => b.createdAt - a.createdAt); }, staleTime: 30000, gcTime: 300000, refetchOnMount: 'always', }); } export function useSkateSpot(identifier: string, pubkey?: string) { const { querySkateContent, getQueryKeySuffix } = useSkateRelays(); return useQuery({ queryKey: ['skate-spot', identifier, pubkey, getQueryKeySuffix()], queryFn: async () => { // If offline, try to get from cache first if (isOffline() && pubkey) { console.log('[useSkateSpot] Offline, checking cache'); const { getCachedSpot } = await import('@/lib/offlineCache'); const cached = await getCachedSpot(pubkey, identifier); if (cached) { console.log('[useSkateSpot] Found in cache:', identifier); return cached; } } const signal = AbortSignal.timeout(30000); const filter: { kinds: number[]; '#d': string[]; authors?: string[]; limit: number; } = { kinds: [SKATE_SPOT_KIND], '#d': [identifier], limit: 1, }; if (pubkey) { filter.authors = [pubkey]; } const events = await querySkateContent([filter], { signal }); if (events.length === 0) { console.warn(`[useSkateSpot] No events found for identifier: ${identifier}`); return null; } const spot = parseSkateSpot(events[0]); // Cache the spot for offline use if (spot) { const { cacheSpot } = await import('@/lib/offlineCache'); cacheSpot(events[0], spot).catch(err => console.warn('[useSkateSpot] Failed to cache spot:', err) ); } return spot; }, enabled: !!identifier, staleTime: 30000, refetchOnMount: 'always', }); } export function useUserSkateSpots(pubkey: string) { const { querySkateContent, getQueryKeySuffix } = useSkateRelays(); return useQuery({ queryKey: ['user-skate-spots', pubkey, getQueryKeySuffix()], queryFn: async () => { const signal = AbortSignal.timeout(30000); const events = await querySkateContent( [ { kinds: [SKATE_SPOT_KIND], authors: [pubkey], '#t': ['skatespot'], limit: 50, }, ], { signal } ); const spots: SkateSpot[] = []; for (const event of events) { const spot = parseSkateSpot(event); if (spot) spots.push(spot); } return spots.sort((a, b) => b.createdAt - a.createdAt); }, enabled: !!pubkey, staleTime: 30000, refetchOnMount: 'always', }); }