64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
/**
|
|
* useRiderStats
|
|
*
|
|
* Fetches on-chain stats for a given pubkey to display on the Rider Card:
|
|
* - spotsAdded: how many skate spots (kind 30818) this user has published
|
|
* - eventsCreated: how many calendar events (kind 31923) they created
|
|
* - zapsReceived: count of zap receipts (kind 9735) targeting their pubkey
|
|
* - shopCards: kind 37097 shop rider cards issued TO this user
|
|
* - parkCards: kind 35679 park access grants issued TO this user
|
|
*
|
|
* All queries hit the SkateSpots community relay so results are skate-specific.
|
|
*/
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { useNostr } from '@nostrify/react';
|
|
|
|
export interface RiderStats {
|
|
spotsAdded: number;
|
|
eventsCreated: number;
|
|
zapsReceived: number;
|
|
shopCards: number;
|
|
parkCards: number;
|
|
}
|
|
|
|
export function useRiderStats(pubkey: string | undefined) {
|
|
const { nostr } = useNostr();
|
|
|
|
return useQuery({
|
|
queryKey: ['rider-stats', pubkey],
|
|
enabled: !!pubkey,
|
|
staleTime: 60_000,
|
|
queryFn: async (c) => {
|
|
if (!pubkey) return null;
|
|
const signal = AbortSignal.any([c.signal, AbortSignal.timeout(8000)]);
|
|
|
|
// Single query — multiple filter objects, one round-trip
|
|
const events = await nostr.query(
|
|
[
|
|
// Spots the user added
|
|
{ kinds: [30818], authors: [pubkey], '#t': ['skatespot'], limit: 200 },
|
|
// Events they created
|
|
{ kinds: [31923], authors: [pubkey], limit: 100 },
|
|
// Zap receipts targeting their pubkey
|
|
{ kinds: [9735], '#p': [pubkey], limit: 200 },
|
|
// Shop rider cards issued TO this user (kind 37097)
|
|
{ kinds: [37097], '#p': [pubkey], limit: 50 },
|
|
// Park access cards issued TO this user (kind 35679)
|
|
{ kinds: [35679], '#p': [pubkey], limit: 50 },
|
|
],
|
|
{ signal },
|
|
);
|
|
|
|
const stats: RiderStats = {
|
|
spotsAdded: events.filter(e => e.kind === 30818).length,
|
|
eventsCreated: events.filter(e => e.kind === 31923).length,
|
|
zapsReceived: events.filter(e => e.kind === 9735).length,
|
|
shopCards: events.filter(e => e.kind === 37097).length,
|
|
parkCards: events.filter(e => e.kind === 35679).length,
|
|
};
|
|
|
|
return stats;
|
|
},
|
|
});
|
|
}
|