# π 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