SkateSpots/src/hooks/useCrewsForSpot.ts
shakespeare.diy 6848a72869 Crews: proximity discovery, activity/rep signals, treasury, hiring pipeline, crew-hosted events + reverse links; add Contacts page
Crews page
- "Near me" geolocation toggle with haversine distance sort + distance chips
- Crew count + cities social-proof stat header
- Deterministic per-crew vibe-colour accents (no more wall of teal)
- Activity pulse ("🔥 active this week") + OG/Verified/Established rep badges
- Rich empty state ("Claim your local scene") instead of dead "No crews yet"

Crew synergies
- Crew treasury: transparent, non-custodial NIP-75 zap goal (kind 9041) with
  live progress bar tallied from zap receipts; funds settle to founder's own
  Lightning wallet — no shared wallet or new wallet settings needed
- Crew-hosted events: host a jam/comp as the crew (event a-tag → crew coord),
  "Hosted by [crew]" on event pages, Crew Events list on the crew page
- Crew ↔ Lab hiring pipeline: "Open Call / looking-for" flags (filmer, editor,
  coach, builder, members) surfaced on the crew page
- Request to join: encrypted NIP-17 DM to founder + admins (no founder-push
  bottleneck, no public join event)
- Reverse links: "Crews that skate here" on spot pages

Contacts (0xchat-style + Armada-style privacy)
- New /contacts page with Crew-mates / Follows / Recent DMs / Saved tabs
- Per-contact quick actions: message, zap, view profile, star
- Private encrypted contacts list (NIP-51 kind 30000, NIP-44 encrypted to self)
- Added to burger menu + desktop More menu (gated to logged-in users)

Docs: NIP.md updated with crew treasury, crew-hosted events, looking-for tags,
and the private encrypted contacts list.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-25 12:38:45 +07:00

45 lines
1.5 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { useSkateRelays } from '@/hooks/useSkateRelays';
import {
SKATE_CREW_KIND,
SKATE_SPOT_KIND,
parseSkateCrew,
type SkateCrew,
} from '@/lib/types';
/**
* Reverse link: which crews list this spot as a home spot?
*
* Crews store home spots as `a` tags (`30818:pubkey:d`). We query crews whose
* `a` tag references this spot coordinate, so a spot page can show
* "Crews that skate here".
*/
export function useCrewsForSpot(spotPubkey?: string, spotIdentifier?: string, limit = 20) {
const { querySkateContent, getQueryKeySuffix } = useSkateRelays();
const spotCoord =
spotPubkey && spotIdentifier
? `${SKATE_SPOT_KIND}:${spotPubkey}:${spotIdentifier}`
: '';
return useQuery({
queryKey: ['crews-for-spot', spotCoord, getQueryKeySuffix()],
enabled: !!spotCoord,
staleTime: 5 * 60 * 1000,
gcTime: 30 * 60 * 1000,
queryFn: async () => {
const signal = AbortSignal.timeout(10000);
const events = await querySkateContent(
[{ kinds: [SKATE_CREW_KIND], '#a': [spotCoord], limit }],
{ signal },
);
const crews: SkateCrew[] = [];
for (const ev of events) {
const crew = parseSkateCrew(ev);
// Guard: relay `#a` matching can be loose — confirm the ref is present.
if (crew && crew.spotRefs.includes(spotCoord)) crews.push(crew);
}
return crews.sort((a, b) => b.members.length - a.members.length);
},
});
}