π₯ Vision general del sistema
NutriFlow Dashboard es una plataforma web B2B de gestion nutricional clinica. Permite a dietistas y administradores de clinica gestionar pacientes, asignar y monitorizar planes de alimentacion, hacer seguimiento de la evolucion y generar informes para la clinica y los pacientes.
El sistema tiene tres tipos de usuario con acceso diferenciado: administradores de clinica que gestionan el equipo y la configuracion, dietistas que trabajan con sus pacientes asignados, y pacientes que visualizan su propio plan y progreso.
Tecnicamente es una aplicacion fullstack: el frontend esta construido con Next.js 14 usando App Router y hace llamadas a una API REST FastAPI desplegada separadamente. El estado del cliente se gestiona con Zustand y las peticiones asincronas con TanStack Query.
Modulos del sistema
| # | Modulo | Paginas | Funcionalidad principal | Roles con acceso |
| 1 | Autenticacion | Login, Recuperar contrasena, Reset contrasena | Acceso seguro con JWT, redireccion por rol | Todos |
| 2 | Gestion de pacientes | Lista, Ficha detalle, Alta/baja | CRUD de pacientes, asignacion a dietistas | Admin, Dietista |
| 3 | Planes nutricionales | Lista planes, Editor de plan, Asignar plan | Crear y asignar planes semana a semana | Dietista |
| 4 | Seguimiento | Registro diario, Historial evolucion, Grafica peso | Registro de comidas y peso, calculo IMC | Dietista, Paciente |
| 5 | Reportes | Metricas clinica, Informe paciente (PDF) | Estadisticas de adherencia y progreso | Admin, Dietista |
| 6 | Configuracion | Perfil clinica, Usuarios, Facturacion | Ajustes del espacio de trabajo | Admin |
π Inventario de paginas
| # | Pagina | Ruta | Modulo | Stack |
| 1 | Login | /login | Auth | Next.js client component |
| 2 | Recuperar contrasena | /auth/recuperar-password | Auth | Next.js client component |
| 3 | Reset contrasena | /auth/reset-password?token=xxx | Auth | Next.js client component |
| 4 | Dashboard principal | /dashboard | Home | Next.js server component |
| 5 | Lista de pacientes | /pacientes | Pacientes | Next.js client component |
| 6 | Ficha paciente | /pacientes/:id | Pacientes | Next.js server + client |
| 7 | Lista planes | /planes | Planes | Next.js client component |
| 8 | Editor de plan | /planes/:id/editar | Planes | Next.js client component |
| 9 | Registro diario | /seguimiento/registro | Seguimiento | Next.js client component |
| 10 | Evolucion paciente | /pacientes/:id/evolucion | Seguimiento | Next.js server + client |
| 11 | Reportes clinica | /reportes | Reportes | Next.js server component |
| 12 | Perfil clinica | /configuracion/clinica | Config | Next.js client component |
| 13 | Gestion usuarios | /configuracion/usuarios | Config | Next.js client component |
| 14 | Facturacion | /configuracion/facturacion | Config | Next.js client component |
π Modelo de permisos
El sistema implementa RBAC (Role-Based Access Control) con tres roles. El token JWT incluye el campo role que el frontend lee de localStorage para redirigir al espacio correcto tras el login.
| Modulo / Pagina | Admin | Dietista | Paciente |
| Dashboard principal | Si (metricas globales) | Si (sus pacientes) | No |
| Lista de pacientes | Todos | Solo los suyos | No |
| Crear / editar paciente | Si | Solo los suyos | No |
| Dar de alta (baja clinica) | Si | Solo los suyos | No |
| Planes nutricionales | Lectura | CRUD completo | Solo ver su plan activo |
| Registro diario | No | Ver | Crear/editar |
| Reportes clinica | Si | Solo sus pacientes | No |
| Configuracion / usuarios | Si | No | No |
Patron global: Toda llamada a la API incluye el header Authorization: Bearer {token}. El backend FastAPI valida el token y el rol antes de cada operacion.
Redireccion post-login: admin β /admin/dashboard | dietista β /dashboard | paciente β /paciente/resumen
π
Modulo 1 β Autenticacion
Paginas de acceso, recuperacion y reseteo de contrasena. Rutas publicas (no requieren token).
Pagina: Login β /login
Pagina de entrada al sistema. El usuario introduce email y contrasena; el sistema valida contra la API, almacena el token JWT en localStorage y redirige segun el rol.
Campos
| Campo | Tipo | Req. | Validacion | Descripcion |
| Correo electronico | Email input | Si | Formato email valido | Cuenta de acceso del usuario |
| Contrasena | Password input | Si | Minimo 8 caracteres | Contrasena de la cuenta |
Interacciones
Envio del formulario (click "Entrar" o Enter)
AccionUsuario hace click en "Entrar" o pulsa Enter. El boton muestra "Cargando..." y queda deshabilitado.
APIPOST /api/auth/login con { email, password }
ValidacionEmail con formato valido. Contrasena minimo 8 caracteres. Ambos campos requeridos.
ExitoSe guarda token en localStorage. Se guarda rol en localStorage. Redireccion al espacio del rol (admin/dietista/paciente).
ErrorSe muestra el mensaje de error de la API ("Credenciales incorrectas" u otro). El boton vuelve a estar activo.
Click en "Olvidaste tu contrasena?"
AccionNavega a /auth/recuperar-password
API asociada
| API | Metodo | Ruta | Trigger | Respuesta |
| Login | POST | /api/auth/login | Submit formulario | { access_token, user: { id, role, nombre } } |
π₯
Modulo 2 β Gestion de pacientes
Listado, fichas y alta/baja de pacientes de la clinica. Acceso para admin y dietistas.
Pagina: Lista de pacientes β /pacientes
Tabla paginada con todos los pacientes. Permite buscar, filtrar por estado, acceder a fichas individuales, crear nuevos pacientes y dar de alta (baja clinica) a los existentes.
Layout
Cabecera: Titulo "Pacientes" + boton "+ Nuevo paciente" (abre modal).
Filtros: Campo de busqueda de texto libre + selector de estado.
Tabla: 7 columnas con paginacion de 20 filas por pagina.
Paginacion: Botones Anterior/Siguiente + contador "Pagina X de Y".
Filtros de busqueda
| Filtro | Tipo | Opciones | Comportamiento |
| Busqueda | Text input | β | Busca por nombre completo, DNI/NIE o email. Resetea paginacion a pagina 1. |
| Estado | Select | Todos / Activo / Inactivo / Alta medica / Pendiente evaluacion | Filtra la tabla. Se puede combinar con busqueda. |
Columnas de la tabla
| Columna | Formato | Clickable | Notas |
| Nombre completo | Texto enlace | Si β ficha paciente | Navega a /pacientes/:id |
| DNI/NIE | Texto | No | β |
| Email | Texto | No | β |
| Dietista asignado | Nombre del dietista | No | Puede estar vacio si no asignado |
| Estado | Badge de color segun estado | No | activo/inactivo/alta/pendiente |
| Ultima visita | Fecha dd/mm/aaaa | No | Locale es-ES |
| Acciones | Links + boton | Si | Ver ficha | Plan nutricional | Dar de alta |
Acciones por fila
| Accion | Comportamiento |
| Ver ficha | Navega a /pacientes/:id |
| Plan nutricional | Navega a /pacientes/:id/plan |
| Dar de alta | Muestra dialogo de confirmacion. Si confirma, hace PATCH /api/pacientes/:id con status='alta'. Refresca la tabla. |
Modal: Nuevo paciente
| Campo | Tipo | Req. | Validacion | Descripcion |
| Nombre | Text | Si | β | Nombre de pila |
| Apellidos | Text | Si | β | Apellidos del paciente |
| DNI/NIE | Text | Si | Patron: 8 digitos + letra mayuscula, o X/Y/Z + 7 digitos + letra | Documento de identidad |
| Fecha de nacimiento | Date | Si | β | Para calculo de edad e IMC |
| Email | Email | Si | Formato email valido | Email de contacto y acceso del paciente |
| Telefono | Text | No | Patron: empieza 6-9, 9 digitos | Movil espanol |
| Dietista asignado | Select | Si | β | Carga lista de dietistas de la clinica |
| Objetivo | Select | No | β | Perdida peso / Ganancia muscular / Mantenimiento / Gestion patologia / Rendimiento deportivo |
| Peso inicial | Number (0.1 paso) | No | β | En kg. Se usa para calculo IMC y evolucion |
| Altura | Number (entero) | No | β | En cm |
| Alergias e intolerancias | Textarea | No | β | Texto libre |
| Observaciones medicas | Textarea | No | β | Notas para el dietista |
Guardar nuevo paciente
ValidacionCampos requeridos: nombre, apellidos, DNI, fecha nacimiento, email, dietista. DNI con patron regex. Email valido. Telefono con patron opcional.
APIPOST /api/pacientes con todos los campos del formulario
ExitoCierra el modal. Refresca la tabla de pacientes.
Error[TBC] El codigo fuente no muestra manejo de error explicitamente en el modal. Pendiente confirmar si muestra toast o error inline.
API de esta pagina
| API | Metodo | Ruta | Trigger | Params |
| Listar pacientes | GET | /api/pacientes | Carga inicial + busqueda + filtro + cambio pagina | page, per_page=20, q, status |
| Crear paciente | POST | /api/pacientes | Submit modal nuevo paciente | Body con todos los campos del formulario |
| Dar de alta | PATCH | /api/pacientes/:id | Click boton "Dar de alta" + confirmacion | Body: { status: "alta" } |
π
Modulo 3 β Planes nutricionales
Creacion y gestion de planes de alimentacion asignados a pacientes. Solo los dietistas pueden crear y editar.
Pagina: Lista de planes β /planes
Tabla de todos los planes nutricionales con tabs de estado para filtrado rapido. Muestra metricas clave como calorias, duracion y adherencia.
Layout
Tabs de estado: "Activos (N)" | "Borradores (N)" | "Completados (N)". Funciona como filtro rapido.
Tabla: 8 columnas. Sin paginacion visible en el codigo analizado β puede estar en el servidor [TBC].
Columnas de la tabla
| Columna | Formato | Notas |
| Paciente | Nombre completo | Enlaza a ficha del paciente |
| Nombre del plan | Texto | Ej: "Plan hipocalorico 8 semanas" |
| Calorias/dia | Numero + "kcal" | Objetivo calorico del plan |
| Semanas | Entero | Duracion total del plan |
| Inicio | Fecha | Fecha de inicio del plan |
| Fin previsto | Fecha | Inicio + duracion en semanas |
| Estado | Badge: borrador/activo/completado/suspendido | Ver enum PlanStatus |
| Adherencia | Porcentaje (ej: 87%) | % de dias con registro completo del paciente |
π
Modulo 4 β Seguimiento
Registro diario de comidas y peso por parte del paciente, y visualizacion de evolucion por el dietista.
Pagina: Registro diario β /seguimiento/registro
El paciente registra lo que ha comido cada dia y su peso. El dietista puede ver y editar estos registros desde la ficha del paciente.
Campos del registro diario
| Campo | Tipo | Req. | Descripcion |
| Fecha | Date | Si | Por defecto: hoy. El paciente puede registrar dias pasados. |
| Peso del dia | Number (0.1 paso) | No | En kg. Muestra diferencia con el dia anterior. |
| Desayuno | Textarea | No | Descripcion libre de alimentos |
| Media manana | Textarea | No | β |
| Comida | Textarea | No | β |
| Merienda | Textarea | No | β |
| Cena | Textarea | No | β |
| Actividad fisica | Select + minutos | No | Tipo (ninguna/caminata/cardio/fuerza/mixto) + duracion en minutos |
| Notas del dia | Textarea | No | Bienestar general, sensaciones, incidencias |
Pagina: Evolucion del paciente β /pacientes/:id/evolucion
Vista historica del progreso del paciente. Muestra grafica de peso con linea de tendencia, tablas de adherencia semanal y comparativa de medidas antropometricas.
Grafica de peso: Linea temporal (Recharts). Eje X: fechas. Eje Y: peso en kg. Incluye linea de objetivo y linea de tendencia calculada.
Tabla de adherencia: Por semana, % de dias con registro completo vs plan.
π
Modulo 5 β Reportes
Metricas globales de la clinica y generacion de informes PDF para pacientes.
Pagina: Reportes clinica β /reportes
Panel de metricas con graficas de resumen: numero de pacientes activos, distribucion de objetivos, adherencia media y evolucion mensual de altas/bajas.
| Metrica | Formato | Descripcion |
| Pacientes activos | Numero | Total con status='activo' |
| Nuevos este mes | Numero + variacion % | Comparativa con mes anterior |
| Adherencia media | Porcentaje | Media de adherencia de todos los planes activos |
| Distribucion de objetivos | Grafica de tarta (Recharts) | % de cada objetivo (perdida peso, ganancia muscular, etc) |
| Evolucion mensual | Grafica de barras (Recharts) | Altas vs bajas por mes, ultimos 6 meses |
π
Apendice A β Inventario completo de API
Todos los endpoints identificados en el codebase (Next.js proxy β FastAPI backend).
| Input | Tipo | Req. | Descripcion |
| email | string | Si | Email de la cuenta |
| password | string | Si | Contrasena, min 8 chars |
| Output | Tipo | Descripcion |
| access_token | string (JWT) | Token de sesion |
| user.id | integer | ID del usuario |
| user.role | enum: admin/dietista/paciente | Rol para redireccion |
| user.nombre | string | Nombre para mostrar en la UI |
| Query param | Tipo | Default | Descripcion |
| page | integer | 1 | Numero de pagina |
| per_page | integer | 20 | Resultados por pagina |
| q | string | β | Busqueda por nombre, DNI o email |
| status | enum PacienteStatus | β | Filtro por estado |
| Output field | Tipo | Descripcion |
| items | array | Lista de pacientes (ver modelo Paciente) |
| total_pages | integer | Total de paginas disponibles |
| total | integer | Total de registros |
Body con los campos del formulario Nuevo Paciente. Devuelve el paciente creado con id asignado.
Usado para dar de alta (cambiar status a "alta") y para editar datos de la ficha. Body parcial con solo los campos a actualizar.
| Output field | Tipo | Descripcion |
| activos | integer | Contador para el tab "Activos" |
| borradores | integer | Contador para el tab "Borradores" |
| completados | integer | Contador para el tab "Completados" |
| items | array | Lista de planes (ver modelo Plan) |
ποΈ
Apendice B β Diccionario de enums y constantes
Todos los valores de estado, tipos y codigos usados en el sistema.
| Valor | Etiqueta UI | Descripcion |
activo | Activo | Paciente en seguimiento activo. Aparece en busquedas por defecto. |
inactivo | Inactivo | Paciente que no tiene plan activo en este momento pero sigue en la base de datos. |
alta | Alta medica | Paciente dado de alta, ya no requiere seguimiento. Se oculta de listas por defecto. |
pendiente | Pendiente evaluacion | Paciente creado pero aun no evaluado por el dietista asignado. |
| Valor | Etiqueta UI | Descripcion |
borrador | Borrador | Plan en creacion, aun no asignado al paciente. |
activo | Activo | Plan en curso, el paciente puede registrar su adherencia. |
completado | Completado | El periodo del plan ha finalizado. |
suspendido | Suspendido | Plan interrumpido antes de finalizar (por motivos medicos u otros). |
| Valor | Etiqueta UI | Descripcion |
perdida_peso | Perdida de peso | Deficit calorico progresivo |
ganancia_muscular | Ganancia muscular | Superavit calorico con enfasis en proteinas |
mantenimiento | Mantenimiento | TDEE equilibrado |
patologia | Gestion de patologia | Plan adaptado a condicion medica (diabetes, celiaquia, etc) |
deportivo | Rendimiento deportivo | Plan periodizado segun carga de entrenamiento |
| Valor | Descripcion |
admin | Administrador de la clinica. Acceso completo a todo. |
dietista | Profesional nutricionista. Acceso a sus pacientes asignados. |
paciente | Paciente de la clinica. Acceso solo a su propio perfil y plan. |
πΊοΈ
Apendice C β Relaciones entre paginas
Mapa de navegacion y paso de parametros entre paginas del sistema.
| Pagina origen | Accion | Destino | Params pasados |
| Login | Login exitoso (role=admin) | /admin/dashboard | β |
| Login | Login exitoso (role=dietista) | /dashboard | β |
| Login | Login exitoso (role=paciente) | /paciente/resumen | β |
| Login | Click "Olvidaste contrasena" | /auth/recuperar-password | β |
| Lista pacientes | Click nombre en tabla | /pacientes/:id | id del paciente |
| Lista pacientes | Click "Plan nutricional" | /pacientes/:id/plan | id del paciente |
| Ficha paciente | Click "Ver evolucion" | /pacientes/:id/evolucion | id del paciente |
| Lista planes | Click nombre del plan | /planes/:id/editar | id del plan |
| Ficha paciente | Click "Editar plan" | /planes/:id/editar | id del plan |
Patron de refresco de datos compartidos
Alta de paciente: Al dar de alta desde Lista pacientes, TanStack Query invalida la cache de ['pacientes', ...] y la tabla se refresca automaticamente.
Nuevo paciente: Al guardar el modal, se llama a refetch() explicitamente sobre la query de la lista.
Cambios en plan: Al guardar un plan desde el editor, se invalida la cache de ['planes'] y de ['pacientes', id] para reflejar el nuevo plan activo en la ficha.