55 lines
2 KiB
TypeScript
55 lines
2 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { useSkateRelays } from '@/hooks/useSkateRelays';
|
|
import {
|
|
SKATE_MUSICIAN_KIND,
|
|
CALENDAR_EVENT_KIND,
|
|
parseSkateEvent,
|
|
type SkateEvent,
|
|
} from '@/lib/types';
|
|
|
|
/**
|
|
* Gigs for a musician — calendar events (kind 31923) carrying an `a` tag that
|
|
* points back at the musician's Lab coordinate (`35011:pubkey:d`).
|
|
*
|
|
* This powers the "Upcoming gigs" list on a musician's Lab detail page and
|
|
* closes the Music ↔ Events loop: an event promoter tags a musician when
|
|
* creating an event, and the gig automatically surfaces on the act's profile.
|
|
*/
|
|
export function useGigs(musicianPubkey?: string, musicianIdentifier?: string, limit = 30) {
|
|
const { querySkateContent, getQueryKeySuffix } = useSkateRelays();
|
|
const musicianCoord =
|
|
musicianPubkey && musicianIdentifier
|
|
? `${SKATE_MUSICIAN_KIND}:${musicianPubkey}:${musicianIdentifier}`
|
|
: '';
|
|
|
|
return useQuery({
|
|
queryKey: ['gigs', musicianCoord, getQueryKeySuffix()],
|
|
enabled: !!musicianCoord,
|
|
staleTime: 60 * 1000,
|
|
gcTime: 30 * 60 * 1000,
|
|
queryFn: async () => {
|
|
const signal = AbortSignal.timeout(10000);
|
|
const events = await querySkateContent(
|
|
[{ kinds: [CALENDAR_EVENT_KIND], '#a': [musicianCoord], 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 hasRef = ev.tags.some(([t, v]) => t === 'a' && v === musicianCoord);
|
|
if (skateEvent && hasRef) 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;
|
|
});
|
|
},
|
|
});
|
|
}
|