codigo0/docs/SISTEMA_CONTENIDO_COMPLETO.md

16 KiB

📚 Sistema de Gestión de Contenido - Documentación Completa

Versión: 1.0.0
Fecha: 2025-01-06
Estado: Completado


📋 Tabla de Contenidos

  1. Resumen Ejecutivo
  2. Arquitectura del Sistema
  3. Componentes Principales
  4. Flujo de Datos
  5. API y Endpoints
  6. Content Pack
  7. ContentAdapter
  8. Enlaces Bidireccionales
  9. Sistema de Cache
  10. Testing
  11. Guía de Uso
  12. Troubleshooting

🎯 Resumen Ejecutivo

El Sistema de Gestión de Contenido es una arquitectura aditiva y desacoplada que permite gestionar todo el contenido de la aplicación PWA sin tocar el código existente. El sistema garantiza estabilidad total incluso si el sistema externo falla, mediante un mecanismo de fallback robusto.

Características Principales

  • Arquitectura Aditiva: No modifica código existente
  • Fallback Total: Funciona offline con datos locales
  • Content Pack JSON: Sistema de distribución de contenido
  • Enlaces Bidireccionales: Protocolos ↔ Guías ↔ Manual
  • Cache Inteligente: IndexedDB con fallback a localStorage
  • Testing Completo: Herramientas de verificación integradas

🏗️ Arquitectura del Sistema

┌─────────────────────────────────────────────────────────────┐
│                      FRONTEND (PWA)                          │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         ContentAdapterFactory                         │   │
│  │  ┌──────────────────┐    ┌──────────────────┐      │   │
│  │  │ LocalContentAdapter│    │ExternalContentAdapter│   │   │
│  │  │ (Datos locales)   │    │ (Content Pack)     │     │   │
│  │  └──────────────────┘    └──────────────────┘      │   │
│  └──────────────────────────────────────────────────────┘   │
│                          │                                    │
│                          ▼                                    │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         Páginas de la App                              │   │
│  │  (RCP, ViaAerea, Shock, Farmacos, etc.)              │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                               │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         Cache (IndexedDB / localStorage)              │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                          │
                          │ HTTP
                          ▼
┌─────────────────────────────────────────────────────────────┐
│                    BACKEND (Express)                          │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         PostgreSQL Database                            │   │
│  │  - content_items                                      │   │
│  │  - media_resources                                    │   │
│  │  - content_resource_relations                        │   │
│  └──────────────────────────────────────────────────────┘   │
│                          │                                    │
│                          ▼                                    │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         Content Pack Generator                        │   │
│  │  - Genera pack-latest.json                           │   │
│  │  - Calcula hash SHA-256                               │   │
│  └──────────────────────────────────────────────────────┘   │
│                          │                                    │
│                          ▼                                    │
│  ┌──────────────────────────────────────────────────────┐   │
│  │         API Endpoint                                  │   │
│  │  GET /api/content-pack/latest.json                    │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

🔧 Componentes Principales

1. ContentAdapter

Ubicación: src/services/content-adapter.ts

Interfaz que abstrae el acceso al contenido:

interface ContentAdapter {
  getProtocol(id: string): Procedure | null;
  getDrug(id: string): Drug | null;
  getGuide(id: string): Guide | null;
  getAllProtocols(): Procedure[];
  getAllDrugs(): Drug[];
  getAllGuides(): Guide[];
  isAvailable(): boolean;
}

LocalContentAdapter

  • Usa datos locales (procedures.ts, drugs.ts, guides-index.ts)
  • Siempre disponible
  • Fallback garantizado

ExternalContentAdapter

  • Carga Content Pack desde /api/content-pack/latest.json
  • Cache en IndexedDB/localStorage
  • Fallback automático a LocalContentAdapter si falla

ContentAdapterFactory

  • Selecciona automáticamente el adapter disponible
  • Prioriza ExternalContentAdapter si está disponible
  • Fallback a LocalContentAdapter

2. Content Pack

Ubicación Backend: backend/src/services/pack-generator.js
Endpoint: /api/content-pack/latest.json

Estructura del Content Pack:

{
  "version": "1.0.0",
  "generatedAt": "2025-01-06T12:00:00Z",
  "hash": "sha256:...",
  "content": {
    "protocols": [...],
    "guides": [...],
    "drugs": [...],
    "checklists": [...],
    "manuals": [...]
  },
  "media": {
    "images": [...],
    "videos": [...]
  },
  "relations": [...]
}

3. Sistema de Relaciones

Ubicación: src/services/content-relations.ts

Proporciona funciones para obtener relaciones bidireccionales:

  • getGuideForProtocol(protocolId) - Obtiene guía relacionada
  • getProtocolForGuide(guideId) - Obtiene protocolo relacionado
  • getProtocolRelations(protocolId) - Obtiene todas las relaciones
  • getGuideRelations(guideId) - Obtiene todas las relaciones

4. Sistema de Cache

Ubicación: src/utils/indexeddb.ts

IndexedDB (Prioritario)

  • Mayor capacidad de almacenamiento
  • Mejor rendimiento con packs grandes
  • API asíncrona

localStorage (Fallback)

  • Compatible con todos los navegadores
  • Sincrónico
  • Limitado a ~5-10MB

Expiración: 24 horas por defecto


🔄 Flujo de Datos

Carga Inicial

  1. App inicia → ContentAdapterFactory se inicializa
  2. ExternalContentAdapter intenta cargar Content Pack:
    • Primero desde IndexedDB (cache)
    • Si no hay cache o está expirado, descarga desde API
    • Guarda en cache
  3. Si falla, usa LocalContentAdapter (datos locales)

Uso en Páginas

  1. Página necesita contenido → Llama a contentAdapter.getProtocol(id)
  2. ContentAdapterFactory devuelve el adapter activo
  3. Adapter busca en su fuente (pack o local)
  4. Retorna contenido o null (fallback)

Actualización del Pack

  1. Backend genera nuevo pack → Guarda en storage/content-pack/
  2. Frontend detecta nueva versión (hash diferente)
  3. Descarga nuevo pack
  4. Actualiza cache

🌐 API y Endpoints

Content Pack

GET /api/content-pack/latest.json

Obtiene el Content Pack más reciente.

Respuesta:

{
  "version": "1.0.0",
  "generatedAt": "2025-01-06T12:00:00Z",
  "hash": "sha256:...",
  "content": {...},
  "media": {...}
}

Headers:

  • ETag: Hash del pack
  • Cache-Control: public, max-age=3600

GET /api/content-pack/:version.json

Obtiene una versión específica del Content Pack.


📦 Content Pack

Generación

El Content Pack se genera automáticamente:

  1. On-the-fly: Si no existe archivo, se genera al solicitar
  2. Programado: Se puede generar periódicamente (cron job)
  3. Manual: Desde admin panel

Estructura de Contenido

Cada item en el pack tiene esta estructura:

interface ContentItem {
  id: string;
  type: 'protocol' | 'guide' | 'drug' | 'checklist' | 'manual';
  slug: string;
  title: string;
  shortTitle?: string;
  description: string;
  content: any; // Estructura específica por tipo
  priority: 'critical' | 'high' | 'medium' | 'low';
  status: 'draft' | 'in_review' | 'approved' | 'published';
  version: string;
  // ...
}

🔗 Enlaces Bidireccionales

Mapeo

Ubicación: src/data/protocol-guide-manual-mapping.ts

Define las relaciones entre:

  • Protocolos Operativos (Nivel 1)
  • Guías de Refuerzo (Nivel 2)
  • Manual Completo (Nivel 3)

Uso en Páginas

import { getProtocolRelations } from '@/services/content-relations';

const relations = getProtocolRelations('rcp-adulto-svb');
// Retorna: { protocol, guide, manual, mapping }

Navegación

  • Desde Protocolo: Enlaces a Guía y Manual
  • Desde Guía: Enlaces a Protocolo y Manual
  • Desde Manual: (Futuro) Enlaces a Protocolo y Guía

💾 Sistema de Cache

IndexedDB

Ventajas:

  • Mayor capacidad (GBs)
  • Mejor rendimiento
  • API asíncrona

Uso:

import { saveContentPack, getContentPack } from '@/utils/indexeddb';

// Guardar
await saveContentPack(pack);

// Obtener
const cached = await getContentPack(24 * 60 * 60 * 1000); // 24 horas

localStorage (Fallback)

Se usa automáticamente si IndexedDB no está disponible.


🧪 Testing

Página de Testing

Ruta: /testing

Interfaz visual para ejecutar tests y ver resultados.

Funciones de Testing

Ubicación: src/utils/testing-helpers.ts

Tests disponibles:

  • testContentAdapterAvailable() - Verifica que el adapter está disponible
  • testGetProtocols() - Verifica obtención de protocolos
  • testGetDrugs() - Verifica obtención de fármacos
  • testGetGuides() - Verifica obtención de guías
  • testProtocolToGuideRelations() - Verifica relaciones
  • testContentPackCache() - Verifica cache

Ejecutar Tests

import { runAllBasicTests, formatTestResults } from '@/utils/testing-helpers';

const results = runAllBasicTests();
console.log(formatTestResults(results));

📖 Guía de Uso

Para Desarrolladores

Obtener Contenido

import { getProtocol, getAllProtocols } from '@/services/content-adapter';

// Obtener protocolo específico
const protocol = getProtocol('rcp-adulto-svb');

// Obtener todos los protocolos
const protocols = getAllProtocols();

Usar Hooks

import { useProtocolAdapter, useGuideAdapter } from '@/services/content-adapter';

function MyComponent() {
  const { protocol, isLoading, isExternal } = useProtocolAdapter('rcp-adulto-svb');
  
  if (isLoading) return <div>Cargando...</div>;
  if (!protocol) return <div>No encontrado</div>;
  
  return (
    <div>
      <h1>{protocol.title}</h1>
      {isExternal && <span>Contenido Externo</span>}
    </div>
  );
}

Obtener Relaciones

import { getProtocolRelations } from '@/services/content-relations';

const relations = getProtocolRelations('rcp-adulto-svb');
if (relations.guide) {
  // Hay guía relacionada
}
if (relations.manual) {
  // Hay manual relacionado
}

Para Administradores

Generar Content Pack

  1. Acceder al Admin Panel
  2. Ir a "Content Pack"
  3. Hacer clic en "Generar Pack"
  4. El pack se genera y se guarda automáticamente

Verificar Cache

  1. Abrir DevTools (F12)
  2. Ir a Application → IndexedDB
  3. Verificar guia-tes-contentcontent-pack

🔧 Troubleshooting

El Content Pack no se carga

Síntomas:

  • No aparece badge "Externo"
  • Contenido siempre es local

Soluciones:

  1. Verificar que el backend está corriendo
  2. Verificar endpoint /api/content-pack/latest.json
  3. Revisar consola del navegador para errores
  4. Verificar que el pack se genera correctamente

Cache no funciona

Síntomas:

  • El pack se descarga cada vez
  • No se guarda en IndexedDB

Soluciones:

  1. Verificar permisos de IndexedDB en el navegador
  2. Verificar que hay espacio disponible
  3. Revisar consola para errores
  4. El sistema fallback a localStorage automáticamente

Enlaces bidireccionales no funcionan

Síntomas:

  • Enlaces no aparecen
  • Enlaces rotos

Soluciones:

  1. Verificar que el mapeo existe en protocol-guide-manual-mapping.ts
  2. Verificar que las IDs coinciden
  3. Revisar consola para errores
  4. Usar página de testing para verificar relaciones

📊 Estadísticas del Sistema

Capacidad

  • IndexedDB: Hasta varios GBs
  • localStorage: ~5-10MB
  • Content Pack: Típicamente < 5MB

Rendimiento

  • Carga inicial: < 500ms (con cache)
  • Carga sin cache: 1-3s (depende del tamaño)
  • Búsqueda: < 10ms (en memoria)

Compatibilidad

  • Chrome/Edge (IndexedDB + localStorage)
  • Firefox (IndexedDB + localStorage)
  • Safari (IndexedDB + localStorage)
  • Mobile browsers (IndexedDB + localStorage)

🚀 Próximas Mejoras

  1. Compresión del Pack: Comprimir JSON antes de enviar
  2. Differential Updates: Solo actualizar cambios
  3. Service Worker: Cache más agresivo
  4. Analytics: Tracking de uso del contenido
  5. A/B Testing: Múltiples versiones de contenido

📝 Notas Técnicas

Seguridad

  • El Content Pack es público (no contiene datos sensibles)
  • Autenticación solo para admin panel
  • Validación de contenido antes de publicar

Escalabilidad

  • El sistema puede manejar miles de items
  • IndexedDB escala bien con grandes volúmenes
  • El pack se puede dividir por categorías si crece mucho

Mantenibilidad

  • Código modular y desacoplado
  • Fácil de extender con nuevos tipos de contenido
  • Testing integrado

Última actualización: 2025-01-06
Mantenido por: Equipo de Desarrollo TES