18 KiB
🏗️ 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
-
Editor Clínico:
- Actualizar dosis según nuevas guías (ERC, AHA, SEMES)
- Añadir advertencias críticas
- Modificar pasos de protocolos
-
Editor Docente:
- Crear nuevas guías formativas
- Modificar casos clínicos
- Actualizar explicaciones fisiopatológicas
-
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:
-
Carga dinámica de contenido:
// Antes (estático) import { procedures } from '@/data/procedures'; // Después (dinámico) const procedures = await fetchContent('protocols'); -
Cache local:
// 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; -
Detección de actualizaciones:
// 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:
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:
-
Cache inicial (build time):
- Contenido embebido en la app (fallback)
- Se genera en build time desde fuente de verdad
-
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
-
Versionado de cache:
interface CachedContent { content: any; version: number; cachedAt: Date; expiresAt: Date; } -
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:
{
"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:
{
"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):
{
"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:
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.