AgendaPro
Aplicación web multi-tenant (SaaS) para la gestión de negocios de servicios (estética, spa, barbería, clínicas, etc.): calendario de citas con arrastrar y soltar, gestión de empleados, servicios, clientes y tickets, y un tablero con ingresos, mejores empleados, servicios más rentables y clientes top.
Tres roles: Administrador de plataforma (crea y gestiona todos los negocios desde la consola admin), Dueño (ve su negocio y el tablero) y Empleado (agenda citas que se auto-asignan a él).
Stack
- Frontend: React 18 + TypeScript + Vite + Tailwind CSS
- Calendario: FullCalendar (drag & drop, resize, day/time grid)
- Gráficas: Recharts
- Backend: Node.js + Express
- Base de datos: SQLite (vía
node:sqlite, nativo de Node — sin compilación nativa)
Requisitos
- Node.js 22.5+ (recomendado 24+). Este proyecto usa el módulo nativo
node:sqlite.
Instalación
npm install
La base de datos se siembra automáticamente con datos demo la primera vez que arranca el servidor. Para regenerarla desde cero:
# Borra la DB y vuelve a sembrar
npm run seed
# o, forzando reset desde el servidor:
$env:RESET_DB="1"; npm run dev:server # PowerShell
RESET_DB=1 npm run dev:server # bash
Desarrollo
npm run dev
Abre http://localhost:5173 (el frontend proxya /api al backend en el puerto 3000).
Producción
npm run build # compila TS y empaqueta el frontend en dist/
npm start # sirve la API y el frontend estático en http://localhost:3000
Tests y auditoría visual
npm run test:e2e # 22 pruebas end-to-end de la API (login, CRUD, dashboard, auto-asignación, roles, multi-tenant)
npm run test:admin # 17 pruebas del admin (crear negocio + plantilla, aislamiento, reset-demo, delete cascade)
npm run audit:visual # Playwright: navega 10 páginas × 4 viewports (móvil/tablet/desktop/wide),
# mide overflow horizontal, captura errores de consola y guarda capturas en screenshots/
La auditoría visual verifica responsividad en 375 / 768 / 1280 / 1536 px, detecta overflow, errores de consola y confirma que el calendario, el modal de cita y el cambio de sesión funcionan en cada tamaño.
Cuentas demo
Todas usan la contraseña demo1234.
| Rol | Nombre | |
|---|---|---|
| Admin | [email protected] |
Administrador |
| Dueño | [email protected] |
Daniela Reyes |
| Empleado | [email protected] |
Valentina Cruz |
| Empleado | [email protected] |
Mateo Herrera |
| Empleado | [email protected] |
Sofía Ramírez |
| Empleado | [email protected] |
Diego Castillo |
| Empleado | [email protected] |
Isabela Torres |
| Empleado | [email protected] |
Carolina Méndez |
En la pantalla de login aparecen botones de acceso rápido a las cuentas demo, y desde la barra lateral puedes cambiar de cuenta con “Ver como…”.
Multi-tenant y consola de administrador
AgendaPro es multi-tenant: cada negocio es un tenant aislado (todos los datos llevan business_id
y las consultas se filtran por el negocio del usuario). El administrador de plataforma gestiona
todos los negocios desde /admin:
- Resumen: KPIs globales (negocios activos, usuarios, ingresos y citas de toda la plataforma).
- Negocios: lista buscable con stats por negocio (usuarios, citas, ingresos).
- Crear negocio (2 pasos): eliges una plantilla → se cargan empleados, servicios y clientes demo con historial de citas/tickets listos para usar; defines los datos del negocio y la cuenta del dueño.
- Detalle de negocio: editar nombre/industria, cambiar plan (Prueba/Pro/Free) y estado (Activo/Suspendido), recargar datos demo con otra plantilla (preserva las cuentas de usuario) o eliminar el negocio por completo (con cascade de todos sus datos).
Plantillas disponibles: estetica-spa (Lumière), barberia (Urban Cut), clinica (Dental Sonrisa)
y blank (vacío, para configurar desde cero). Defínelas en server/lib/templates.ts.
El aislamiento entre tenants se valida: un dueño solo ve los datos de su negocio, y los empleados no pueden acceder al tablero ni a la gestión (403).
Funcionalidades
Calendario (Dueño y Empleado)
- Vistas de mes / semana / día, con indicador de hora actual.
- En móvil se abre por defecto en vista Día y se ofrece una vista Lista (agenda) — la vista Semana/Mes queda reservada para tablet/desktop para evitar columnas aplastadas.
- Arrastra para reagendar y redimensiona para cambiar duración.
- Clic en un hueco o en Nueva cita para abrir el formulario.
- Clic en una cita para editarla: cambiar servicio, especialista, cliente, hora, precio, notas.
- Marcar como completada (genera un ticket con propina y método de pago).
- Cancelar o eliminar citas.
- Filtra por empleado y por estado (programada / completada / cancelada).
Formulario de cita
- Servicio desplegable (menú del negocio), con precio y duración.
- Especialista: el empleado lo tiene auto-asignado por defecto (filtrado a quienes ofrecen el servicio).
- Cliente: buscar existente o crear uno nuevo al vuelo.
- Duración, precio y notas editables.
Tablero (Dueño)
- KPIs: ingresos del período, citas programadas, ticket promedio, ocupación y % de cancelación.
- Gráfica de ingresos diarios y distribución por categoría.
- Mejores empleados por ingreso, con rating y utilización.
- Servicios más rentables.
- Tickets más altos recientes.
- Top clientes (por gasto) y clientes frecuentes (por visitas).
- Rango de tiempo ajustable (7 / 30 / 60 días).
Gestión (Dueño)
- Empleados: crear, editar, asignar servicios, ver ingresos/citas/rating.
- Servicios: catálogo agrupado por categoría, con especialistas asignados.
- Tickets: historial de ventas con filtros por método de pago.
Clientes (Dueño y Empleado)
- Buscador por nombre / teléfono / correo.
- Ficha del cliente con historial de citas, gasto total y visitas.
Estructura
.
├── server/ # API Express + SQLite
│ ├── db.ts # esquema multi-tenant + sistema de migraciones versionado
│ ├── index.ts # app Express (auto-siembla admin + negocio demo en primer arranque)
│ ├── lib/auth.ts # middlewares: authRequired, ownerOnly, adminOnly
│ ├── lib/templates.ts # plantillas: estetica-spa, barberia, clinica, blank
│ ├── routes/ # auth, business, employees, services, clients, appointments, dashboard, admin
│ └── scripts/seed.ts# seedBusiness(businessId, template) reutilizable + script standalone
├── shared/types.ts # tipos TS compartidos cliente/servidor
├── src/ # frontend React
│ ├── components/ # AppShell, AdminShell, Modal, AppointmentModal, ui, DemoSwitcher, admin/CreateBusinessModal
│ ├── lib/ # api, auth, format
│ └── pages/ # Login, Dashboard, Calendar, Employees, Services, Clients, Tickets + admin/*
└── data/ # SQLite (generado, .gitignored)
Notas de seguridad
Es una demo. La autenticación usa un token trivial (el id del usuario) sin hashing de contraseña ni sesiones reales — no usar en producción tal cual. Antes de un despliegue real habría que añadir hashing (bcrypt), JWT firmados, validación estricta con zod, rate-limiting y HTTPS.