The entire skate-spots codebase was accidentally copied into src/src/ and public/public/ instead of src/ and public/ directly. This left the real src/ directory as blank MKStack template stubs, explaining why the landing page showed the default template instead of SkateSpots. Changes made: - Copied all files from src/src/ up to src/ (App.tsx, AppRouter.tsx, main.tsx, all pages, components, hooks, contexts, lib, i18n, test) - Copied all files from public/public/ up to public/ (images, manifest, etc.) - Deleted src/src/ and public/public/ nested directories - Removed HelloWorld.tsx template stub from pages/ - Retained the previously fixed index.css (Tailwind v3 directives) Full skate-spots feature set is now active: - All 30+ routes (map, events, spots, coaches, marketplace, wallet, etc.) - NWCProvider, LanguageProvider, PWAInstallPrompt, AmberCallbackHandler - Skate community relays (goskatespots.nostr1.com, wotr.relatr.xyz, etc.) - Outfit Variable font, Amber pre-check in main.tsx - All hooks (useSkateSpots, useCoaches, useZaps, etc.) - i18n support (en/es) Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
69 lines
2 KiB
TypeScript
69 lines
2 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { useNostr } from '@nostrify/react';
|
|
import {
|
|
SKATE_COACH_KIND,
|
|
SKATE_FILMER_KIND,
|
|
SKATE_SPOT_KIND,
|
|
parseSkateCoach,
|
|
parseSkateFilmer,
|
|
type SkateCoach,
|
|
type SkateFilmer,
|
|
SKATE_RELAY,
|
|
} from '@/lib/types';
|
|
|
|
interface SpotServices {
|
|
coaches: SkateCoach[];
|
|
filmers: SkateFilmer[];
|
|
}
|
|
|
|
/**
|
|
* Hook to fetch coaches and filmers available at a specific spot
|
|
*/
|
|
export function useSpotServices(spotPubkey?: string, spotIdentifier?: string) {
|
|
const { nostr } = useNostr();
|
|
|
|
return useQuery({
|
|
queryKey: ['spot-services', spotPubkey, spotIdentifier],
|
|
queryFn: async (c): Promise<SpotServices> => {
|
|
if (!spotPubkey || !spotIdentifier) {
|
|
return { coaches: [], filmers: [] };
|
|
}
|
|
|
|
const signal = AbortSignal.any([c.signal, AbortSignal.timeout(8000)]);
|
|
const relay = nostr.relay(SKATE_RELAY);
|
|
|
|
// The spot reference format: "30818:pubkey:identifier"
|
|
const spotRef = `${SKATE_SPOT_KIND}:${spotPubkey}:${spotIdentifier}`;
|
|
|
|
// Query for coaches and filmers that reference this spot
|
|
const events = await relay.query([
|
|
{
|
|
kinds: [SKATE_COACH_KIND, SKATE_FILMER_KIND],
|
|
'#a': [spotRef],
|
|
limit: 50,
|
|
}
|
|
], { signal });
|
|
|
|
const coaches: SkateCoach[] = [];
|
|
const filmers: SkateFilmer[] = [];
|
|
|
|
for (const event of events) {
|
|
if (event.kind === SKATE_COACH_KIND) {
|
|
const coach = parseSkateCoach(event);
|
|
if (coach) coaches.push(coach);
|
|
} else if (event.kind === SKATE_FILMER_KIND) {
|
|
const filmer = parseSkateFilmer(event);
|
|
if (filmer) filmers.push(filmer);
|
|
}
|
|
}
|
|
|
|
// Sort by creation date (newest first)
|
|
coaches.sort((a, b) => b.createdAt - a.createdAt);
|
|
filmers.sort((a, b) => b.createdAt - a.createdAt);
|
|
|
|
return { coaches, filmers };
|
|
},
|
|
enabled: !!spotPubkey && !!spotIdentifier,
|
|
staleTime: 60000,
|
|
});
|
|
}
|