import { Booking } from '@/features/booking/booking'; import { ApiClientError, apiClient } from '@/lib/api-client'; import { useCurrentComplexStore } from '@/lib/stores/current-complex-store'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from '@tanstack/react-router'; import { useEffect } from 'react'; function extractMessage(error: unknown, fallback: string) { if (error instanceof ApiClientError) { return error.message || fallback; } return fallback; } export function HomePage() { const queryClient = useQueryClient(); const navigate = useNavigate(); const currentComplexQuery = useQuery({ queryKey: ['current-complex'], queryFn: () => apiClient.complexes.getCurrent(), }); const { setCurrentComplex } = useCurrentComplexStore(); useEffect(() => { if (currentComplexQuery.data) { setCurrentComplex(currentComplexQuery.data.complexSlug); } }, [currentComplexQuery.data, setCurrentComplex]); useEffect(() => { const unsubscribe = useCurrentComplexStore.subscribe((state, prevState) => { if (state.currentComplexSlug !== prevState.currentComplexSlug) { queryClient.invalidateQueries({ queryKey: ['current-complex'] }); queryClient.invalidateQueries({ queryKey: ['admin-bookings'] }); } }); return unsubscribe; }, [queryClient]); const myComplexesQuery = useQuery({ queryKey: ['my-complexes'], queryFn: () => apiClient.complexes.listMine(), }); useEffect(() => { async function autoSelect() { if (myComplexesQuery.data && myComplexesQuery.data.length === 1) { try { const result = await apiClient.complexes.select({ complexId: myComplexesQuery.data[0].id, }); queryClient.setQueryData(['current-complex'], result); } catch (error) { console.error('Error al auto-seleccionar complejo:', error); } } else if ( myComplexesQuery.data && myComplexesQuery.data.length > 1 && !currentComplexQuery.data ) { navigate({ to: '/select-complex' }); } } if ( !currentComplexQuery.isLoading && !currentComplexQuery.data && myComplexesQuery.data && !myComplexesQuery.isLoading ) { if (myComplexesQuery.data.length === 0) { navigate({ to: '/onboard/setup' }); return; } autoSelect(); } }, [ currentComplexQuery.isLoading, currentComplexQuery.data, myComplexesQuery.data, myComplexesQuery.isLoading, navigate, queryClient, ]); const selectedComplex = currentComplexQuery.data ?? null; useEffect(() => { if (!selectedComplex?.id) return; const channel = `complex-${selectedComplex.id}`; let eventSource: EventSource | null = null; let reconnectTimeout: ReturnType | null = null; let reconnectAttempts = 0; const maxReconnectAttempts = 3; let lastEventId: string | null = null; let pollInterval: ReturnType | null = null; const startPolling = () => { if (pollInterval) return; pollInterval = setInterval(() => { void queryClient.invalidateQueries({ queryKey: ['admin-bookings', selectedComplex.id] }); }, 10000); }; const connect = () => { if (eventSource) { eventSource.close(); } if (reconnectAttempts >= maxReconnectAttempts) { startPolling(); return; } const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000'; const url = `${baseUrl}/api/events/${encodeURIComponent(channel)}`; eventSource = new EventSource(url); eventSource.onerror = () => { if (eventSource?.readyState === EventSource.CLOSED) { reconnectAttempts++; reconnectTimeout = setTimeout(() => { connect(); }, 2000); } }; eventSource.addEventListener('message', (event) => { if (event.data && event.data !== 'connected' && event.data !== 'ping') { if (event.data !== lastEventId) { lastEventId = event.data; reconnectAttempts = 0; void queryClient.invalidateQueries({ queryKey: ['admin-bookings', selectedComplex.id], }); } } }); }; connect(); return () => { if (reconnectTimeout) { clearTimeout(reconnectTimeout); } if (pollInterval) { clearInterval(pollInterval); } eventSource?.close(); }; }, [selectedComplex?.id, queryClient]); if (myComplexesQuery.isLoading) { return

Cargando panel...

; } if (myComplexesQuery.isError) { return (

{extractMessage(myComplexesQuery.error, 'No pudimos cargar tus complejos.')}

); } if (!selectedComplex) { return

No tienes complejos asignados todavĂ­a.

; } return ; }