import { useQuery } from '@tanstack/react-query'; import { useSkateRelays } from '@/hooks/useSkateRelays'; import { SKATE_CREW_KIND, CALENDAR_EVENT_KIND, parseSkateEvent, type SkateEvent, } from '@/lib/types'; /** * Events hosted BY a crew — calendar events (kind 31923) carrying an `a` tag * that points back at the crew coordinate (`35006:pubkey:d`). * * This powers the "Hosted by [crew]" link on events and the crew's own * "Upcoming jams" list. Crew-hosted events close the Crews ↔ Events ↔ Zaps loop. */ export function useCrewEvents(crewPubkey?: string, crewIdentifier?: string, limit = 30) { const { querySkateContent, getQueryKeySuffix } = useSkateRelays(); const crewCoord = crewPubkey && crewIdentifier ? `${SKATE_CREW_KIND}:${crewPubkey}:${crewIdentifier}` : ''; return useQuery({ queryKey: ['crew-events', crewCoord, getQueryKeySuffix()], enabled: !!crewCoord, staleTime: 60 * 1000, gcTime: 30 * 60 * 1000, queryFn: async () => { const signal = AbortSignal.timeout(10000); const events = await querySkateContent( [{ kinds: [CALENDAR_EVENT_KIND], '#a': [crewCoord], limit }], { signal }, ); const parsed: SkateEvent[] = []; for (const ev of events) { const skateEvent = parseSkateEvent(ev); // Guard against loose relay matches — the `a` tag must be present. const hasCrewRef = ev.tags.some(([t, v]) => t === 'a' && v === crewCoord); if (skateEvent && hasCrewRef) parsed.push(skateEvent); } // Soonest upcoming first, then past. const now = Math.floor(Date.now() / 1000); return parsed.sort((a, b) => { const aFuture = a.start >= now ? 0 : 1; const bFuture = b.start >= now ? 0 : 1; if (aFuture !== bFuture) return aFuture - bFuture; return a.start - b.start; }); }, }); }