workspace/projects/gamilit/orchestration/agentes/architecture-analyst/gap-analysis/GAP-DATE-HANDLING-ADMIN-PORTAL-2025-11-24.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- Configure workspace Git repository with comprehensive .gitignore
- Add Odoo as submodule for ERP reference code
- Include documentation: SETUP.md, GIT-STRUCTURE.md
- Add gitignore templates for projects (backend, frontend, database)
- Structure supports independent repos per project/subproject level

Workspace includes:
- core/ - Reusable patterns, modules, orchestration system
- projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.)
- knowledge-base/ - Reference code and patterns (includes Odoo submodule)
- devtools/ - Development tools and templates
- customers/ - Client implementations template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:44:23 -06:00

4.9 KiB

GAP Analysis: Manejo de Fechas Nulas en Admin Portal

ID: GAP-DATE-HANDLING-001 Fecha: 2025-11-24 Severidad: ALTA (P1) Analista: Architecture-Analyst Estado: En corrección


1. RESUMEN EJECUTIVO

Se identificó un patrón inseguro de conversión de fechas en múltiples componentes del Admin Portal donde se llama new Date(value) sin validar si value es null o undefined, resultando en "Invalid Date".


2. CAUSA RAÍZ

El campo lastLogin puede ser null

Cuando un usuario nunca ha iniciado sesión, lastLogin es null. Al ejecutar:

new Date(null)  // → Thu Jan 01 1970 00:00:00 (epoch)
new Date(undefined)  // → Invalid Date

El error "date invalid" aparece cuando toLocaleDateString() se llama sobre un Invalid Date.

Flujo del error:

Backend envía: { lastLogin: null }  // Usuario nunca ha iniciado sesión
                     ↓
Frontend:      new Date(null).toLocaleDateString()
                     ↓
Resultado:     "1/1/1970" (incorrecto) o "Invalid Date" (error)

3. INSTANCIAS DEL PROBLEMA

Archivo Principal (Error Reportado)

Archivo Línea Código Problemático
UserManagementTable.tsx 106 {new Date(user.lastLogin).toLocaleDateString()}

Otros Archivos con Mismo Patrón

# Archivo Línea Campo
1 TeacherClassroomsTab.tsx 181 classroom.assignedAt
2 ClassroomTeachersTab.tsx 214 teacher.assignedAt
3 ErrorTrackingTab.tsx 212 trend.time_bucket
4 UserActivityMonitor.tsx 211 activity.timestamp
5 SystemHealthIndicators.tsx 215 incident.timestamp
6 SystemPerformanceDashboard.tsx 219 metrics.timestamp
7 AdminContentPage.tsx 141, 228, 275 row.createdAt, row.uploadedAt
8 AdminInstitutionsPage.tsx 180 row.createdAt
9 AdminGamificationPage.tsx 114 stats.lastModified
10 TenantManagementPanel.tsx 349, 355 createdAt, lastActive
11 FeatureFlagControls.tsx 345, 357, 365, 396 Múltiples campos
12 ABTestingDashboard.tsx 306, 314 startDate, endDate
13 MediaLibraryManager.tsx 260 file.uploadedAt
14 EconomicInterventionPanel.tsx 384, 388 startDate, endDate
15 ContentApprovalQueue.tsx 165, 284 item.submittedAt
16 ContentVersionControl.tsx 114, 138, 192, 234 version.timestamp
17 AdminDashboardHero.tsx 171 health.lastCheck
18 SystemAlertsPanel.tsx 204 selectedAlert.timestamp
19 RecentActionsTable.tsx 318, 418 action.timestamp
20 OrganizationsTable.tsx 140 org.createdAt
21 SystemLogsViewer.tsx 135 log.timestamp

4. PATRÓN CORRECTO

Implementación Segura (Ya existe en AdminUsersPage.tsx:370)

// ✅ CORRECTO - Con validación
{usr.lastLogin ? new Date(usr.lastLogin).toLocaleDateString('es-ES') : 'Nunca'}

Función Utilitaria Recomendada

// apps/frontend/src/shared/utils/formatters.ts

/**
 * Formatea una fecha de forma segura, manejando null/undefined
 * @param dateValue - Valor de fecha (string, Date, null, undefined)
 * @param options - Opciones de formato
 * @param fallback - Texto a mostrar si la fecha es inválida
 * @returns Fecha formateada o fallback
 */
export function formatDateSafe(
  dateValue: string | Date | null | undefined,
  options: Intl.DateTimeFormatOptions = { dateStyle: 'short' },
  fallback: string = 'N/A'
): string {
  if (!dateValue) return fallback;

  const date = new Date(dateValue);
  if (isNaN(date.getTime())) return fallback;

  return date.toLocaleDateString('es-ES', options);
}

5. PLAN DE CORRECCIÓN

Prioridad 1: Error Reportado

  • Archivo: UserManagementTable.tsx
  • Línea: 106
  • Acción: Agregar validación de null

Prioridad 2: Componentes de Alta Visibilidad

  • RecentActionsTable.tsx (Dashboard principal)
  • OrganizationsTable.tsx (Dashboard principal)
  • SystemAlertsPanel.tsx (Dashboard principal)

Prioridad 3: Resto de Componentes

  • Aplicar patrón seguro a todos los archivos listados

6. CRITERIOS DE ACEPTACIÓN

  • UserManagementTable.tsx no genera "Invalid Date"
  • Todos los componentes usan el patrón value ? new Date(value)... : fallback
  • npm run type-check pasa sin errores relacionados
  • Las fechas null muestran texto apropiado ("Nunca", "N/A", "Sin fecha", etc.)

7. ARCHIVOS A MODIFICAR

# Archivo Tipo de Cambio
1 UserManagementTable.tsx Agregar validación null para lastLogin
2 TeacherClassroomsTab.tsx Agregar validación null para assignedAt
3 ClassroomTeachersTab.tsx Agregar validación null para assignedAt
4+ (Ver lista completa arriba) Mismo patrón

Versión: 1.0 Estado: Listo para implementación