Something went wrong. Try again.
A mobile app view of atmoquest
Something went wrong. Try again.
7.6 kB · 249 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';import { apiFetch } from './client';
// ─── Types ──────────────────────────────────────────────────────────
export interface UserSession { did: string; handle: string; isAdmin: boolean;}
export interface Profile { did: string; handle: string; displayName: string; bio: string; interests: string[]; links: { label: string; url: string }[]; location: string; isHiring: boolean; isLooking: boolean;}
export interface Connection { did: string; handle: string; displayName: string; connectedAt: string;}
export interface ConnectionNotes { notes: string; followUp: boolean; updatedAt: string;}
export interface Event { token: string; name: string; description: string; startDate: string; endDate: string; location: string; lat?: number; lng?: number; radius?: number; checkinCount: number;}
export interface EventDetail extends Event { attendees: { did: string; handle: string; displayName: string }[]; stats: { uniqueConnectors: number; totalCheckins: number; attendeeCount: number; }; isCheckedIn: boolean;}
export interface Badge { name: string; earnedAt: string; eventToken?: string; svgUrl: string;}
export interface Settings { did: string; handle: string; showInAttendees: boolean; showInLeaderboard: boolean;}
// ─── Query Keys ─────────────────────────────────────────────────────
export const queryKeys = { session: ['session'] as const, profile: ['profile'] as const, userProfile: (did: string) => ['profile', did] as const, connections: ['connections'] as const, connectionNotes: (did: string) => ['connectionNotes', did] as const, events: ['events'] as const, eventDetail: (token: string) => ['event', token] as const, eventStats: (token: string) => ['eventStats', token] as const, badges: ['badges'] as const, badgesRecent: ['badges', 'recent'] as const, settings: ['settings'] as const, settingsNotes: ['settings', 'notes'] as const,} as const;
// ─── Auth ───────────────────────────────────────────────────────────
export function useSession() { return useQuery({ queryKey: queryKeys.session, queryFn: () => apiFetch<UserSession>('/auth/session'), retry: false, staleTime: 5 * 60 * 1000, });}
// ─── Profile ────────────────────────────────────────────────────────
export function useProfile() { return useQuery({ queryKey: queryKeys.profile, queryFn: () => apiFetch<Profile>('/profile'), staleTime: 5 * 60 * 1000, });}
export function useUserProfile(did: string) { return useQuery({ queryKey: queryKeys.userProfile(did), queryFn: () => apiFetch<Profile>(`/users/${encodeURIComponent(did)}`), staleTime: 5 * 60 * 1000, });}
export function useUpdateProfile() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: Partial<Profile>) => apiFetch<Profile>('/profile', { method: 'PUT', body: JSON.stringify(data) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.profile }); }, });}
// ─── Connections ────────────────────────────────────────────────────
export function useConnections() { return useQuery({ queryKey: queryKeys.connections, queryFn: () => apiFetch<Connection[]>('/connections'), staleTime: 2 * 60 * 1000, });}
export function useCreateConnection() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (did: string) => apiFetch('/connections/' + encodeURIComponent(did), { method: 'POST' }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.connections }); }, });}
export function useConnectionNotes(did: string) { return useQuery({ queryKey: queryKeys.connectionNotes(did), queryFn: () => apiFetch<ConnectionNotes>(`/connections/${encodeURIComponent(did)}/notes`), });}
export function useSaveConnectionNotes() { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ did, notes, followUp }: { did: string; notes: string; followUp: boolean }) => apiFetch(`/connections/${encodeURIComponent(did)}/notes`, { method: 'PUT', body: JSON.stringify({ notes, followUp }), }), onSuccess: (_, { did }) => { queryClient.invalidateQueries({ queryKey: queryKeys.connectionNotes(did) }); queryClient.invalidateQueries({ queryKey: queryKeys.settingsNotes }); }, });}
// ─── Events ─────────────────────────────────────────────────────────
export function useEvents() { return useQuery({ queryKey: queryKeys.events, queryFn: () => apiFetch<Event[]>('/events'), staleTime: 60 * 1000, });}
export function useEventDetail(token: string) { return useQuery({ queryKey: queryKeys.eventDetail(token), queryFn: () => apiFetch<EventDetail>(`/events/${encodeURIComponent(token)}`), staleTime: 60 * 1000, });}
export function useEventStats(token: string) { return useQuery({ queryKey: queryKeys.eventStats(token), queryFn: () => apiFetch<EventDetail['stats']>(`/events/${encodeURIComponent(token)}/stats`), refetchInterval: 5000, });}
export function useCheckin() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (token: string) => apiFetch(`/events/${encodeURIComponent(token)}/checkin`, { method: 'POST' }), onSuccess: (_, token) => { queryClient.invalidateQueries({ queryKey: queryKeys.eventDetail(token) }); queryClient.invalidateQueries({ queryKey: queryKeys.events }); }, });}
// ─── Badges ─────────────────────────────────────────────────────────
export function useBadges() { return useQuery({ queryKey: queryKeys.badges, queryFn: () => apiFetch<Badge[]>('/badges'), staleTime: 5 * 60 * 1000, });}
export function useRecentBadges() { return useQuery({ queryKey: queryKeys.badgesRecent, queryFn: () => apiFetch<Badge[]>('/badges/recent'), staleTime: 30 * 1000, });}
// ─── Settings ───────────────────────────────────────────────────────
export function useSettings() { return useQuery({ queryKey: queryKeys.settings, queryFn: () => apiFetch<Settings>('/settings'), staleTime: 5 * 60 * 1000, });}
export function useUpdatePrivacy() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: Partial<Pick<Settings, 'showInAttendees' | 'showInLeaderboard'>>) => apiFetch('/settings/privacy', { method: 'PUT', body: JSON.stringify(data) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.settings }); }, });}