Frontend de la Hackathon 2 construido con React, TypeScript, Vite, React Router y Tailwind CSS.
- Integrante 1: Rojas Cordova Yazid Gabriel — 202510258
- Integrante 2: Rodrigo De Santa Maria Anco Hito — 202510807
npm install
cp .env.example .env # define VITE_API_BASE_URL con la URL real del backend
npm run devVITE_API_BASE_URL=https://<backend-url>/api/v1Si VITE_API_BASE_URL no está definida, la app no inventa datos: muestra un estado de
configuración faltante con un mensaje accionable. Las credenciales del equipo se ingresan
en la pantalla de login y nunca se suben al repositorio.
npm run dev
npm run typecheck
npm run build
npm run preview- URL: PENDIENTE
El proyecto incluye configuración SPA para Vercel (vercel.json) y Netlify
(public/_redirects) para permitir acceso directo a cualquier ruta.
- El JWT se persiste con un único
tokenStorage(Single Source of Truth) y se envía comoAuthorization: Bearerdesde el cliente HTTP compartido. AuthContextimplementa el Provider Pattern y exponestatus(restoring,authenticated,anonymous). Al recargar restaura la sesión conGET /auth/me, manteniendorestoringpara evitar parpadeos entre login y dashboard.- La sesión solo se limpia si
/auth/meresponde401. Ante fallos transitorios (red, 5xx, configuración faltante) no se destruye el token: se cae aanonymousy una recarga vuelve a validar cuando el backend se recupera. ProtectedRoutebloquea rutas privadas, conserva la ruta original enlocation.statey regresa a ella tras el login.- El login valida campos requeridos con mensajes accionables, bloquea el botón durante la petición, evita doble submit y no borra las credenciales si la petición falla.
GET /dashboard/summaryse valida en runtime (parseDashboardSummary): el cliente HTTP devuelveunknowny el feature solo confía en una forma verificada.- Estados explícitos de
loading,error(con reintento) y datos. Layout estable con alturas mínimas y desglose de severidad accesible.
- La etapa activa se detecta con
IntersectionObserver(Observer Pattern), que funciona como base fiable independientemente del soporte de scroll-driven animations. - El visual persistente se compone localmente con React + CSS, interpretando de forma
determinista
climate,assetKey,colorToken,dominantEventymetrics. Hay una composición distinta por clima (PIXEL_FOREST,NEON_CAVE,CLOUD_AQUARIUM,RETRO_ARCADE) y un fallback genérico para climas desconocidos.assetKeyes un identificador (no una URL): alimenta un hash determinista para variar la escena. - El progreso usa
role="progressbar"accesible, refleja la etapa activa, está acotado a 0..1 y nunca retrocede por debajo del avance por índice. - CSS Scroll-driven Animations se activan con
@supports (animation-timeline: view()); elIntersectionObserveres el fallback funcional. - La transición entre lista de sectores e historia usa la View Transition API cuando existe
(
startViewTransition, tipado sinany) y navegación normal cuando no. - Se respeta
prefers-reduced-motionen CSS y en el comportamiento de scroll por teclado. - Navegación por teclado: Tab/Shift+Tab más flechas, Re Pág/Av Pág, Inicio y Fin; cada etapa es enfocable y actualiza visual, métricas y progreso.
- Si el backend no devuelve exactamente 8 etapas se muestra una advertencia accionable y se renderizan las recibidas sin inventar las faltantes.
- Las respuestas obsoletas se cancelan con
AbortControllery se descartan por secuencia. - El feed infinito usa cursor, deduplicación por ID y una sola carga adicional en vuelo.
- Los filtros se mantienen en la URL con
useSearchParams.
La aplicación consume el backend oficial mediante VITE_API_BASE_URL.
Las credenciales se ingresan únicamente en la pantalla de login y no se guardan en el repositorio.