Multi-tenant scheduling SaaS (AgendaPro-equivalent): - Backend: Node + Express + node:sqlite, multi-tenant (admin/owner/employee), versioned migrations, 4 templates (estetica-spa, barberia, clinica, blank). - Frontend: React 18 + TS + Vite + Tailwind, FullCalendar drag-and-drop, Recharts dashboard, mobile-first (day/list views on mobile). - Features: calendar+services+employees+clients+tickets, dashboard with best employee/service, top tickets, top/frequent clients, commissions, cancellation policy + no-show tracking, public online booking (/b/:slug), cash register (cierre de caja), reminders/notifications center. - Verification: 65/65 e2e API, 58/58 visual (0 overflow, 0 console errors), typecheck clean, vite build OK.
165 lines
7.7 KiB
Markdown
165 lines
7.7 KiB
Markdown
# 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
|
||
|
||
```bash
|
||
npm install
|
||
```
|
||
|
||
La base de datos se **siembra automáticamente** con datos demo la primera vez que arranca el servidor.
|
||
Para regenerarla desde cero:
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
Abre http://localhost:5173 (el frontend proxya `/api` al backend en el puerto 3000).
|
||
|
||
## Producción
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
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 | Email | 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.
|