AgendaPro DevandClaude Opus 5 4c19244df9 feat: public landing page with magic login, brand palette and demo build flag
Adds a public funnel landing at `/` and moves the login to `/login`, rebuilt
around the panel's own colors instead of an invented palette.

Landing (`src/components/landing/`, one section per file, no props):
- Seven funnel sections composed by `LandingPage`. The hero's eight swatches are
  literally `PIE_COLORS` from `DashboardPage`, the same hex values the seed hands
  to avatars and services, so "your colors become your numbers" is literal.
- `BrandMark` becomes the single source for the logo, replicating
  `public/favicon.svg`. Blue is the action surface, orange only ever marks.
- `NotebookVisual` is the one deliberate exception to the palette: it is what the
  product replaces.
- Copy drops all system vocabulary; motion comes from `src/lib/motion.ts` with a
  single easing, and reduced-motion resolves `initial` to the final state so a
  never-firing `whileInView` cannot leave a section invisible forever.

Routing and bundle:
- `homePathFor` is the single definition of each role's destination.
- Landing, login, dashboard and calendar load lazily. Eager, the login dragged
  framer-motion (~40 KB gz) into every panel load and the landing downloaded
  recharts + FullCalendar (~187 KB gz) without charting anything. `clsx` is
  pinned to the `react` chunk because Rollup otherwise assigns it to `charts`,
  making the entry import 111 KB gz for a 200-byte utility.

Responsiveness (iPhone/iPad), verified with `npm run audit:responsive`:
- No touch form field below 16px, `dvh` height utilities, safe-area insets, and
  40px touch targets keyed off `pointer: coarse` rather than `sm:`.
- New `.ld-gutter`: `.safe-x` lives outside `@layer` and beats Tailwind's `px-*`,
  so it left the login's side padding at 0 on anything but an iPhone in
  landscape. No overflow check could see it — there was no overflow, just zero
  margin. The audit now guards it with a `gutter` check.
- `shell-height` no longer fires on pages that legitimately scroll; the static
  `raw-viewport-unit` scan covers those instead.

Production build:
- The Dockerfile now sets `VITE_DEMO_UI=1` as a build arg. `DEMO` is a build-time
  constant, so without it Vite eliminated the magic login and the "Ver como…"
  switcher: the deployed landing promised "no registration" and led to an empty
  form. Verified by building both ways and diffing the bundle.
- Service worker cache bumped to v2 so the orphaned pre-landing chunks get purged
  from returning visitors' caches.

Verified: typecheck clean; unit 39/39, e2e 33/33, admin 17/17, booking 12/12,
landing 13/13 (WebKit), PWA passed against the real production build.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-07-28 14:25:58 -06:00

AgendaMax

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

Instalar AgendaMax como app

  • Android/Chrome: abre la URL HTTPS y selecciona la acción de instalación mostrada por AgendaMax o por la barra de direcciones del navegador.
  • iPhone/iPad Safari: usa Compartir -> Añadir a pantalla de inicio; iOS no expone el aviso de instalación dentro de la página de Android.
  • La app instalada puede abrirse sin la interfaz del navegador, pero los datos del negocio siguen requiriendo conexión a internet.
  • Validación local: ejecuta npm.cmd run build, inicia producción con npm.cmd start y después ejecuta npm.cmd run test:pwa.
  • La validación de producción requiere el dominio HTTPS de Coolify, no una dirección IP HTTP.

npm.cmd run test:pwa usa estas variables opcionales para los flujos autenticados; si no se definen, usa las cuentas demo locales:

[email protected]
[email protected]
PWA_PASSWORD=demo1234

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 Email Contraseña Nombre
Admin [email protected] demo1234 Administrador
Dueño [email protected] demo1234 Daniela Reyes
Empleado [email protected] demo1234 Valentina Cruz
Empleado [email protected] demo1234 Mateo Herrera
Empleado sofía.ramí[email protected] demo1234 Sofía Ramírez
Empleado [email protected] demo1234 Diego Castillo
Empleado [email protected] demo1234 Isabela Torres
Empleado carolina.mé[email protected] demo1234 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

AgendaMax 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.

S
Description
No description provided
Readme
614 KiB
Languages
TypeScript 80.8%
JavaScript 15.4%
CSS 3.4%
HTML 0.2%
Dockerfile 0.2%