lib/actividad.ts — Agregación por fecha (Actividad)
Última actualización: 06-01-2026 09:01 PM
lib/actividad.ts — Agregación por fecha (Actividad)
Section titled “lib/actividad.ts — Agregación por fecha (Actividad)”1) Objetivo
Section titled “1) Objetivo”Este módulo centraliza la lógica para construir métricas por fecha a partir de los retos:
- Convertir/validar fechas a
YYYY-MM-DD. - Sumar minutos por día para un proyecto o de forma global (todos los proyectos).
- Derivar años disponibles a partir de actividad detectada.
Es una capa sin UI y sin dependencias de React, diseñada para ser:
- testable,
- reutilizable,
- estable.
2) Entradas y salidas
Section titled “2) Entradas y salidas”2.1 Tipos de salida
Section titled “2.1 Tipos de salida”ActividadPorDia = Record<string, number>- key:
YYYY-MM-DD - value: minutos acumulados ese día
- key:
2.2 Datos de entrada utilizados
Section titled “2.2 Datos de entrada utilizados”NodoReto.fecha(string)NodoReto.minutos(number)- (opcional)
NodoReto.estadosi algún consumo decide “onlyDone”.
Reglas actuales:
- Si
fechaes inválida → se ignora. - Si
minutoses inválido o< 0→ se normaliza a 0 y se ignora si queda 0.
3) API pública (funciones)
Section titled “3) API pública (funciones)”3.1 normalizarFechaISO(fecha?: string): string | null
Section titled “3.1 normalizarFechaISO(fecha?: string): string | null”Responsabilidad:
- Acepta strings con o sin tiempo (por ejemplo
YYYY-MM-DDTHH:mm...). - Recorta a 10 chars y valida
YYYY-MM-DD. - Valida fecha real (evita
2025-02-31). - Devuelve
YYYY-MM-DDonullsi no pasa validación.
Motivo de diseño:
- El resto del sistema trabaja con una clave normalizada y segura.
- Evita propagar fechas “raras” a la UI.
3.2 actividadPorDia(proyecto: Proyecto, opts?: { onlyDone?: boolean }): ActividadPorDia
Section titled “3.2 actividadPorDia(proyecto: Proyecto, opts?: { onlyDone?: boolean }): ActividadPorDia”Responsabilidad:
- Recorre todos los nodos del proyecto.
- Para cada reto:
- normaliza fecha,
- acumula minutos en
out[fecha] += minutos.
- Si
onlyDoneestá activo → suma solo retosestado === "done".
Complejidad:
- O(n) sobre el total de nodos/retos del proyecto.
3.3 actividadGlobalPorDia(proyectos: Proyecto[], opts?: { onlyDone?: boolean }): ActividadPorDia
Section titled “3.3 actividadGlobalPorDia(proyectos: Proyecto[], opts?: { onlyDone?: boolean }): ActividadPorDia”Responsabilidad:
- Ejecuta
actividadPorDiapor proyecto y hace merge/suma por claveYYYY-MM-DD. - Resultado es global.
Uso típico:
- Calendario global del sidebar derecho.
- Reportes (futuro).
3.4 yearsDesdeActividad(actividad: ActividadPorDia): number[]
Section titled “3.4 yearsDesdeActividad(actividad: ActividadPorDia): number[]”Responsabilidad:
- Extrae el año desde las keys
YYYY-MM-DD. - Devuelve lista ordenada desc (más reciente primero).
- Si no hay datos → devuelve
[añoActual].
4) Decisiones importantes
Section titled “4) Decisiones importantes”4.1 Normalización conservadora
Section titled “4.1 Normalización conservadora”normalizarFechaISO no “arregla” cosas ambiguas.
Si la fecha no se puede validar con seguridad, se descarta.
Ventaja: datos confiables en UI. Costo: si el usuario mete fechas en otro formato, no se contarán (pero tampoco se rompe nada).
4.2 Minutos: solo suma positivos
Section titled “4.2 Minutos: solo suma positivos”Se evita contaminar agregados con negativos o strings raros.
5) Edge cases cubiertos
Section titled “5) Edge cases cubiertos”- Fechas con tiempo:
2025-12-31T10:30:00Z→2025-12-31. - Fecha inválida:
2025-02-31→null. minutos = "30"oundefined→ se fuerza a número y se normaliza (si queda 0, no suma).- Proyectos vacíos → actividad vacía.
- Año sin actividad →
yearsDesdeActividadcae al año actual (para UI).
6) Recomendaciones de pruebas (si luego metes tests)
Section titled “6) Recomendaciones de pruebas (si luego metes tests)”Casos mínimos:
- Normalización:
"2025-12-31"→"2025-12-31""2025-12-31T23:59:59"→"2025-12-31""2025-02-31"→null
- Agregación:
- 2 retos mismo día → suma correcta.
- 2 proyectos distintos mismo día → suma global correcta.
- onlyDone:
- uno done y otro todo → solo suma done.
7) No hacer (reglas de mantenimiento)
Section titled “7) No hacer (reglas de mantenimiento)”- No duplicar agregación en la UI.
- No meter dependencias de UI/React aquí.
- No asumir formatos de fecha distintos a ISO sin un plan (si se decide soportar otro formato, debe ser explícito y documentado).
8) Mejoras opcionales futuras
Section titled “8) Mejoras opcionales futuras”actividadGlobalPorDia(proyectos, { onlyDone: true })como toggle de UI.- Escala robusta para intensidad: percentiles/log (si hay outliers).
- Soportar
fechaen formatos no ISO (solo si realmente lo necesitas; aumenta complejidad).