import { 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('/auth/session'), retry: false, staleTime: 5 * 60 * 1000, }); } // ─── Profile ──────────────────────────────────────────────────────── export function useProfile() { return useQuery({ queryKey: queryKeys.profile, queryFn: () => apiFetch('/profile'), staleTime: 5 * 60 * 1000, }); } export function useUserProfile(did: string) { return useQuery({ queryKey: queryKeys.userProfile(did), queryFn: () => apiFetch(`/users/${encodeURIComponent(did)}`), staleTime: 5 * 60 * 1000, }); } export function useUpdateProfile() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: Partial) => apiFetch('/profile', { method: 'PUT', body: JSON.stringify(data) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.profile }); }, }); } // ─── Connections ──────────────────────────────────────────────────── export function useConnections() { return useQuery({ queryKey: queryKeys.connections, queryFn: () => apiFetch('/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(`/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('/events'), staleTime: 60 * 1000, }); } export function useEventDetail(token: string) { return useQuery({ queryKey: queryKeys.eventDetail(token), queryFn: () => apiFetch(`/events/${encodeURIComponent(token)}`), staleTime: 60 * 1000, }); } export function useEventStats(token: string) { return useQuery({ queryKey: queryKeys.eventStats(token), queryFn: () => apiFetch(`/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('/badges'), staleTime: 5 * 60 * 1000, }); } export function useRecentBadges() { return useQuery({ queryKey: queryKeys.badgesRecent, queryFn: () => apiFetch('/badges/recent'), staleTime: 30 * 1000, }); } // ─── Settings ─────────────────────────────────────────────────────── export function useSettings() { return useQuery({ queryKey: queryKeys.settings, queryFn: () => apiFetch('/settings'), staleTime: 5 * 60 * 1000, }); } export function useUpdatePrivacy() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: Partial>) => apiFetch('/settings/privacy', { method: 'PUT', body: JSON.stringify(data) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.settings }); }, }); }