import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '../lib/api'; export interface SignalMessage { id: string; driverId: string; direction: 'INBOUND' | 'OUTBOUND'; content: string; timestamp: string; isRead: boolean; } export interface UnreadCounts { [driverId: string]: number; } /** * Fetch messages for a specific driver */ export function useDriverMessages(driverId: string | null, enabled = true) { return useQuery({ queryKey: ['signal-messages', driverId], queryFn: async () => { if (!driverId) return []; const { data } = await api.get(`/signal/messages/driver/${driverId}`); return data; }, enabled: enabled && !!driverId, refetchInterval: 5000, // Poll for new messages every 5 seconds }); } /** * Fetch unread message counts for all drivers */ export function useUnreadCounts() { return useQuery({ queryKey: ['signal-unread-counts'], queryFn: async () => { const { data } = await api.get('/signal/messages/unread'); return data; }, refetchInterval: 10000, // Poll every 10 seconds }); } /** * Check which events have driver responses since the event started * @param events Array of events with id, driverId, and startTime */ export function useDriverResponseCheck( events: Array<{ id: string; driver?: { id: string } | null; startTime: string }> ) { // Only include events that have a driver const eventsWithDrivers = events.filter((e) => e.driver?.id); return useQuery({ queryKey: ['signal-driver-responses', eventsWithDrivers.map((e) => e.id).join(',')], queryFn: async () => { if (eventsWithDrivers.length === 0) { return new Set(); } const payload = { events: eventsWithDrivers.map((e) => ({ eventId: e.id, driverId: e.driver!.id, startTime: e.startTime, })), }; const { data } = await api.post<{ respondedEventIds: string[] }>( '/signal/messages/check-responses', payload ); return new Set(data.respondedEventIds); }, enabled: eventsWithDrivers.length > 0, refetchInterval: 10000, // Poll every 10 seconds }); } /** * Send a message to a driver */ export function useSendMessage() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ driverId, content }: { driverId: string; content: string }) => { const { data } = await api.post('/signal/messages/send', { driverId, content, }); return data; }, onSuccess: (data, variables) => { // Add the new message to the cache immediately queryClient.setQueryData( ['signal-messages', variables.driverId], (old) => [...(old || []), data] ); // Also invalidate to ensure consistency queryClient.invalidateQueries({ queryKey: ['signal-messages', variables.driverId] }); }, }); } /** * Mark messages as read for a driver */ export function useMarkMessagesAsRead() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (driverId: string) => { const { data } = await api.post(`/signal/messages/driver/${driverId}/read`); return data; }, onSuccess: (_, driverId) => { // Update the unread counts cache queryClient.setQueryData( ['signal-unread-counts'], (old) => { if (!old) return {}; const updated = { ...old }; delete updated[driverId]; return updated; } ); // Mark messages as read in the messages cache queryClient.setQueryData( ['signal-messages', driverId], (old) => old?.map((msg) => ({ ...msg, isRead: true })) || [] ); }, }); }