codigo0/docs/SISTEMA_CONTENIDO_COMPLETO.md

537 lines
16 KiB
Markdown
Raw Normal View History

2026-01-19 08:10:16 +00:00
# 📚 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](#resumen-ejecutivo)
2. [Arquitectura del Sistema](#arquitectura-del-sistema)
3. [Componentes Principales](#componentes-principales)
4. [Flujo de Datos](#flujo-de-datos)
5. [API y Endpoints](#api-y-endpoints)
6. [Content Pack](#content-pack)
7. [ContentAdapter](#contentadapter)
8. [Enlaces Bidireccionales](#enlaces-bidireccionales)
9. [Sistema de Cache](#sistema-de-cache)
10. [Testing](#testing)
11. [Guía de Uso](#guía-de-uso)
12. [Troubleshooting](#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:
```typescript
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:
```json
{
"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:**
```json
{
"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:
```typescript
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
```typescript
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:**
```typescript
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
```typescript
import { runAllBasicTests, formatTestResults } from '@/utils/testing-helpers';
const results = runAllBasicTests();
console.log(formatTestResults(results));
```
---
## 📖 Guía de Uso
### Para Desarrolladores
#### Obtener Contenido
```typescript
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
```typescript
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
```typescript
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-content``content-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