# 🏗️ ARQUITECTURA DEL PANEL DE ADMINISTRACIÓN - EMERGES TES **Versión:** 1.0 **Fecha:** 2025-01-XX **Estado:** Documento de Diseño - Sin Implementación **Autor:** Arquitecto de Software Senior + Diseñador Instruccional Sanitario --- ## 🎯 PROPÓSITO DEL DOCUMENTO Este documento define **LA ARQUITECTURA CONCEPTUAL** del Panel de Administración de Contenidos para EMERGES TES. Es el **diseño técnico** que: - ✅ Permite editar contenido SIN tocar código React - ✅ Mantiene compatibilidad offline-first - ✅ Garantiza seguridad en entorno sanitario - ✅ Permite auditoría y versionado - ✅ Escala a nivel institucional **Este documento NO incluye implementación. Solo diseño arquitectónico.** --- ## 1️⃣ OBJETIVO DEL PANEL ### Principio Rector **"Se edita CONTENIDO, no CONTINENTE"** El panel permite modificar: - ✅ Textos de protocolos - ✅ Dosis de fármacos - ✅ Notas clínicas - ✅ Advertencias - ✅ Observaciones - ✅ Bloques formativos (Markdown) El panel NO permite modificar: - ❌ Componentes React - ❌ Estructura visual - ❌ Lógica de la app - ❌ Rutas y navegación - ❌ Service Worker --- ### Casos de Uso Principales 1. **Editor Clínico:** - Actualizar dosis según nuevas guías (ERC, AHA, SEMES) - Añadir advertencias críticas - Modificar pasos de protocolos 2. **Editor Docente:** - Crear nuevas guías formativas - Modificar casos clínicos - Actualizar explicaciones fisiopatológicas 3. **Administrador Institucional:** - Validar contenido antes de publicación - Revisar historial de cambios - Activar/desactivar contenido --- ## 2️⃣ ARQUITECTURA PROPUESTA ### Modelo de Separación: Contenido vs Aplicación ``` ┌─────────────────────────────────────────────────────────┐ │ APLICACIÓN (React - Estática) │ │ - Componentes React (NO editables) │ │ - Lógica de UI (NO editable) │ │ - Service Worker (NO editable) │ │ - Estructura de navegación (NO editable) │ └─────────────────────────────────────────────────────────┘ │ │ Carga dinámica │ ▼ ┌─────────────────────────────────────────────────────────┐ │ CONTENIDO (JSON/Markdown - Dinámico) │ │ - Protocolos (JSON) │ │ - Fármacos (JSON) │ │ - Guías formativas (Markdown) │ │ - Manual completo (Markdown) │ └─────────────────────────────────────────────────────────┘ │ │ Edición │ ▼ ┌─────────────────────────────────────────────────────────┐ │ PANEL DE ADMINISTRACIÓN (Web App) │ │ - Editor de contenido │ │ - Validación clínica │ │ - Control de versiones │ │ - Gestión de usuarios │ └─────────────────────────────────────────────────────────┘ ``` --- ### Flujo de Datos ``` 1. Panel Admin → Edita contenido → Guarda en backend/API 2. Backend → Valida → Versiona → Almacena 3. App → Solicita contenido → Backend → Entrega JSON/Markdown 4. App → Cachea localmente → Funciona offline 5. App → Detecta actualizaciones → Notifica usuario ``` --- ### Arquitectura de Capas #### Capa 1: Almacenamiento de Contenido **Opciones técnicas:** **Opción A: Sistema de Archivos Versionado (Git-based)** - Contenido en repositorio Git - Panel edita archivos JSON/Markdown - Commits automáticos con versionado - Ventaja: Historial completo, rollback fácil - Desventaja: Requiere servidor Git **Opción B: Base de Datos + API REST** - Contenido en base de datos (PostgreSQL, MongoDB) - API REST para CRUD de contenido - Panel consume API - Ventaja: Escalable, flexible - Desventaja: Más complejo, requiere backend **Opción C: Headless CMS (Strapi, Contentful, Sanity)** - CMS especializado en contenido - Panel integrado - API automática - Ventaja: Rápido de implementar - Desventaja: Dependencia externa, coste **Recomendación:** Opción A (Git-based) para MVP, migrar a Opción B si escala. --- #### Capa 2: API de Contenido **Endpoints propuestos:** ``` GET /api/content/protocols → Lista todos los protocolos GET /api/content/protocols/:id → Protocolo específico PUT /api/content/protocols/:id → Actualizar protocolo POST /api/content/protocols → Crear protocolo GET /api/content/drugs → Lista todos los fármacos GET /api/content/drugs/:id → Fármaco específico PUT /api/content/drugs/:id → Actualizar fármaco GET /api/content/guides/:id/sections/:num → Sección de guía PUT /api/content/guides/:id/sections/:num → Actualizar sección GET /api/content/manual/blocks/:id → Bloque del manual PUT /api/content/manual/blocks/:id → Actualizar bloque GET /api/content/versions/:id → Historial de versiones GET /api/content/versions/:id/:version → Versión específica ``` --- #### Capa 3: Panel de Administración **Tecnología propuesta:** - Framework: React (consistente con app principal) - UI: shadcn/ui (consistente con app principal) - Editor Markdown: react-markdown-editor-lite o similar - Validación: Zod (TypeScript-first) **Estructura propuesta:** ``` admin-panel/ ├── src/ │ ├── pages/ │ │ ├── ProtocolsEditor.tsx → Editor de protocolos │ │ ├── DrugsEditor.tsx → Editor de fármacos │ │ ├── GuidesEditor.tsx → Editor de guías │ │ ├── ManualEditor.tsx → Editor de manual │ │ └── Validation.tsx → Panel de validación │ ├── components/ │ │ ├── ContentEditor/ → Componentes de edición │ │ ├── Validation/ → Componentes de validación │ │ └── VersionHistory/ → Historial de versiones │ └── lib/ │ ├── api.ts → Cliente API │ └── validation.ts → Reglas de validación ``` --- #### Capa 4: Aplicación Principal (Consumidora) **Modificaciones necesarias:** 1. **Carga dinámica de contenido:** ```typescript // Antes (estático) import { procedures } from '@/data/procedures'; // Después (dinámico) const procedures = await fetchContent('protocols'); ``` 2. **Cache local:** ```typescript // Cache en IndexedDB o localStorage const cachedContent = await getCachedContent('protocols'); if (cachedContent && !isStale(cachedContent)) { return cachedContent; } const freshContent = await fetchContent('protocols'); await cacheContent('protocols', freshContent); return freshContent; ``` 3. **Detección de actualizaciones:** ```typescript // Verificar versiones periódicamente const latestVersion = await checkContentVersion(); if (latestVersion > cachedVersion) { showUpdateNotification(); } ``` --- ## 3️⃣ FUNCIONALIDADES DEL PANEL ### 3.1 Gestión de Contenido #### Editor de Protocolos **Campos editables:** - Título - Pasos (array de strings) - Advertencias (array de strings) - Puntos clave (array de strings) - Material necesario (array de strings) - Fármacos relacionados (array de IDs) **Validación:** - Pasos no pueden estar vacíos - Advertencias máx. 5 - IDs de fármacos deben existir **UI propuesta:** ``` ┌─────────────────────────────────────────┐ │ Editor de Protocolo: RCP Adulto SVB │ ├─────────────────────────────────────────┤ │ Título: [RCP Adulto - Soporte Vital...] │ │ │ │ Pasos: │ │ [1] [Garantizar seguridad de la escena]│ │ [2] [Comprobar consciencia...] │ │ [+] Añadir paso │ │ │ │ Advertencias: │ │ [•] [Profundidad compresiones: 5-6 cm] │ │ [+] Añadir advertencia │ │ │ │ [Guardar] [Cancelar] [Validar] │ └─────────────────────────────────────────┘ ``` --- #### Editor de Fármacos **Campos editables:** - Nombre genérico - Nombre comercial - Dosis adulto - Dosis pediátrica - Vías de administración - Dilución - Indicaciones - Contraindicaciones - Efectos secundarios - Notas clínicas - Puntos críticos TES **Validación:** - Dosis debe tener formato válido - Vías deben ser del enum permitido - Indicaciones/contraindicaciones no pueden estar vacías --- #### Editor de Guías Formativas **Editor Markdown con preview:** - Editor dividido (Markdown | Preview) - Soporte para imágenes - Validación de estructura (8 secciones) - Metadatos (título, descripción, icono) --- #### Editor de Manual **Editor Markdown completo:** - Editor Markdown avanzado - Navegación por bloques - Búsqueda y reemplazo - Validación de referencias cruzadas --- ### 3.2 Control Sanitario #### Campos de Validación **Cada contenido editable debe tener:** ```typescript interface ContentMetadata { // Identificación id: string; // ID único e inmutable version: number; // Versión incremental // Validación clínica validatedBy?: string; // ID del validador validatedAt?: Date; // Fecha de validación clinicalSource?: string; // ERC, AHA, SEMES, etc. validationStatus: 'draft' | 'pending' | 'validated' | 'rejected'; // Control de calidad reviewedBy?: string; // ID del revisor reviewedAt?: Date; // Fecha de revisión qualityScore?: number; // 0-100 // Historial createdAt: Date; // Fecha de creación createdBy: string; // ID del creador updatedAt: Date; // Fecha de última actualización updatedBy: string; // ID del último editor changeLog: ChangeLogEntry[]; // Historial de cambios } ``` --- #### Flujo de Validación ``` 1. Editor → Crea/Modifica contenido → Estado: "draft" 2. Editor → Solicita validación → Estado: "pending" 3. Validador → Revisa contenido → Acepta/Rechaza 4. Si acepta → Estado: "validated" → Publicable 5. Si rechaza → Estado: "rejected" → Vuelve a "draft" ``` --- ### 3.3 Seguridad y Roles #### Roles Propuestos **1. Administrador Clínico:** - ✅ Validar contenido clínico - ✅ Aprobar/rechazar cambios - ✅ Acceso a historial completo - ❌ No puede editar contenido directamente **2. Editor Docente:** - ✅ Crear/editar guías formativas - ✅ Crear/editar manual - ✅ Modificar casos clínicos - ❌ No puede validar contenido clínico - ❌ No puede modificar protocolos operativos **3. Editor Clínico:** - ✅ Crear/editar protocolos operativos - ✅ Crear/editar vademécum - ✅ Modificar dosis y advertencias - ❌ No puede validar (debe solicitar validación) **4. Revisor:** - ✅ Revisar contenido pendiente - ✅ Sugerir cambios - ❌ No puede editar directamente - ❌ No puede validar --- #### Autenticación y Autorización **Propuesta:** - Autenticación: JWT tokens - Autorización: RBAC (Role-Based Access Control) - Auditoría: Log de todas las acciones **Endpoints protegidos:** ``` POST /api/auth/login → Autenticación POST /api/auth/logout → Cerrar sesión GET /api/auth/me → Información del usuario GET /api/content/* → Lectura (público o autenticado) PUT /api/content/* → Escritura (requiere rol) POST /api/content/* → Creación (requiere rol) DELETE /api/content/* → Eliminación (solo admin) ``` --- ## 4️⃣ COMPATIBILIDAD OFFLINE ### Estrategia de Cache **Principio:** "El último contenido válido siempre está disponible offline" **Implementación:** 1. **Cache inicial (build time):** - Contenido embebido en la app (fallback) - Se genera en build time desde fuente de verdad 2. **Cache dinámico (runtime):** - App solicita contenido al iniciar - Si hay red: Descarga y cachea - Si no hay red: Usa cache local - Cache se actualiza en background cuando hay red 3. **Versionado de cache:** ```typescript interface CachedContent { content: any; version: number; cachedAt: Date; expiresAt: Date; } ``` 4. **Invalidación de cache:** - Por tiempo: Cache expira después de X días - Por versión: Si versión remota > versión local - Manual: Usuario puede forzar actualización --- ### Flujo Offline-First ``` App inicia │ ├─ ¿Hay red? │ │ │ ├─ SÍ → Solicitar contenido actualizado │ │ │ │ │ ├─ ¿Hay actualización? │ │ │ │ │ │ │ ├─ SÍ → Descargar y cachear │ │ │ │ Mostrar contenido actualizado │ │ │ │ │ │ │ └─ NO → Usar cache local │ │ │ │ │ └─ Si falla → Usar cache local │ │ │ └─ NO → Usar cache local │ └─ Mostrar contenido (siempre funciona) ``` --- ## 5️⃣ MODELO DE DATOS CONCEPTUAL ### Estructura de Contenido Editable **Protocolo Operativo:** ```json { "id": "rcp-adulto-svb", "version": 3, "title": "RCP Adulto - Soporte Vital Básico", "shortTitle": "RCP Adulto SVB", "category": "soporte_vital", "priority": "critico", "steps": [ "Garantizar seguridad de la escena", "Comprobar consciencia..." ], "warnings": [ "Profundidad compresiones: 5-6 cm", "Frecuencia: 100-120 compresiones/min" ], "keyPoints": [...], "equipment": [...], "drugs": [...], "metadata": { "validatedBy": "dr-juan-perez", "validatedAt": "2025-01-15T10:00:00Z", "clinicalSource": "ERC 2021", "validationStatus": "validated" } } ``` **Fármaco:** ```json { "id": "adrenalina", "version": 5, "genericName": "Adrenalina (Epinefrina)", "tradeName": "Adrenalina Braun®", "adultDose": "ANAFILAXIA: 0.5 mg IM...", "pediatricDose": "ANAFILAXIA: 0.01 mg/kg IM...", "routes": ["IM", "IV", "IO"], "dilution": "ANAFILAXIA: Sin diluir...", "indications": [...], "contraindications": [...], "notes": [...], "criticalPoints": [...], "metadata": {...} } ``` **Guía Formativa (Sección):** ```json { "guideId": "rcp-adulto-svb", "sectionNumber": 1, "version": 2, "title": "Introducción y Contexto", "content": "# SECCIÓN 1: Introducción...\n\n[Markdown completo]", "metadata": {...} } ``` --- ## 6️⃣ SEGURIDAD Y AUDITORÍA ### Logging y Auditoría **Todas las acciones deben registrarse:** ```typescript interface AuditLog { id: string; timestamp: Date; userId: string; action: 'create' | 'update' | 'delete' | 'validate' | 'reject'; resourceType: 'protocol' | 'drug' | 'guide' | 'manual'; resourceId: string; changes?: { field: string; oldValue: any; newValue: any; }[]; ipAddress?: string; userAgent?: string; } ``` --- ### Protección de Datos **Requisitos:** - Contenido sanitario es sensible - Debe cumplir protección de datos (RGPD si aplica) - Historial de cambios debe ser inmutable - Backups regulares --- ## 7️⃣ ESCALABILIDAD INSTITUCIONAL ### Multi-tenancy (Futuro) **Si escala a múltiples instituciones:** - Cada institución tiene su propio contenido - Panel permite seleccionar institución - Contenido puede ser compartido o privado - Roles por institución --- ### API Pública (Futuro) **Para integración con otros sistemas:** - API REST pública (read-only) - Autenticación por API key - Rate limiting - Documentación OpenAPI/Swagger --- ## 📋 RESUMEN EJECUTIVO **Arquitectura propuesta:** - Separación: Contenido (dinámico) vs Aplicación (estática) - Almacenamiento: Git-based (MVP) → Base de datos (escala) - Panel: React + shadcn/ui (consistente con app) - API: REST para CRUD de contenido - Cache: Offline-first con versionado **Funcionalidades:** - ✅ Editor de protocolos, fármacos, guías, manual - ✅ Validación clínica con roles - ✅ Historial de versiones - ✅ Auditoría completa **Seguridad:** - ✅ Autenticación JWT - ✅ Autorización RBAC - ✅ Logging de auditoría - ✅ Protección de datos **Compatibilidad:** - ✅ Offline-first garantizado - ✅ Cache local con versionado - ✅ Fallback a contenido embebido --- **Este documento es el diseño arquitectónico. La implementación se realizará en fases según el roadmap.**