Files
AgendaPro/server/lib/templates.ts
T
AgendaPro Dev e8d2435cc2 AgendaPro v1.0 - multi-tenant SaaS, mobile calendar, public booking
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.
2026-07-25 13:45:53 -06:00

169 lines
8.1 KiB
TypeScript

// Predefined business templates for the admin "create business" flow.
// Each template describes the demo seed (services, employees, sample clients)
// that gets loaded into a freshly created tenant.
const C = {
blue: "#3b66ff",
orange: "#f17616",
green: "#10b981",
purple: "#a855f7",
pink: "#ec4899",
teal: "#14b8a6",
amber: "#f59e0b",
indigo: "#6366f1",
};
export interface TemplateService {
name: string;
category: string;
duration_min: number;
price: number;
color: string;
employees: number[]; // indexes into template.employees
}
export interface TemplateEmployee {
name: string;
role: string;
color: string;
}
export interface ClientSeed {
name: string;
tags?: string;
notes?: string;
}
export interface TemplateDef {
key: string;
name: string;
industry: string;
currency: string;
currency_symbol: string;
description: string;
emailDomain: string;
employees: TemplateEmployee[];
services: TemplateService[];
clients: ClientSeed[];
}
const SPA_CLIENTS: ClientSeed[] = [
"Alejandra Pérez","Roberto Díaz","Mariana López","Fernando Ruiz","Gabriela Sánchez",
"Ricardo Vargas","Patricia Moreno","Javier Estrada","Lucía Fernández","Andrés Ortega",
"Daniela Castro","Eduardo Mendoza","Valeria Guzmán","Carlos Iglesias","Fernanda Romero",
].map((n, i) => ({
name: n,
tags: i % 4 === 0 ? "VIP" : i % 3 === 0 ? "Frecuente" : undefined,
notes: i % 2 === 0 ? "Prefiere horario matutino" : undefined,
}));
export const TEMPLATES: TemplateDef[] = [
{
key: "estetica-spa",
name: "Lumière Estética & Spa",
industry: "Estética y Spa",
currency: "MXN",
currency_symbol: "$",
description: "Salón de belleza y spa: cabello, barbería, faciales, masajes y uñas.",
emailDomain: "@lumiere.mx",
employees: [
{ name: "Valentina Cruz", role: "Estilista Senior", color: C.blue },
{ name: "Mateo Herrera", role: "Barbero", color: C.orange },
{ name: "Sofía Ramírez", role: "Facialista", color: C.green },
{ name: "Diego Castillo", role: "Masajista", color: C.purple },
{ name: "Isabela Torres", role: "Manicurista", color: C.pink },
{ name: "Carolina Méndez", role: "Estilista Junior", color: C.teal },
],
services: [
{ name: "Corte y peinado", category: "Cabello", duration_min: 60, price: 350, color: C.blue, employees: [0, 5] },
{ name: "Coloración global", category: "Cabello", duration_min: 120, price: 1200, color: C.blue, employees: [0] },
{ name: "Mechas balayage", category: "Cabello", duration_min: 180, price: 1800, color: C.indigo, employees: [0] },
{ name: "Tratamiento de keratina", category: "Cabello", duration_min: 150, price: 1500, color: C.teal, employees: [0, 5] },
{ name: "Corte caballero", category: "Barbería", duration_min: 30, price: 180, color: C.orange, employees: [1] },
{ name: "Corte + arreglo de barba", category: "Barbería", duration_min: 45, price: 280, color: C.orange, employees: [1] },
{ name: "Limpieza facial profunda", category: "Facial", duration_min: 75, price: 700, color: C.green, employees: [2] },
{ name: "Facial anti-edad", category: "Facial", duration_min: 90, price: 950, color: C.green, employees: [2] },
{ name: "Masaje relajante 60 min", category: "Spa", duration_min: 60, price: 800, color: C.purple, employees: [3] },
{ name: "Masaje descontracturante 90 min", category: "Spa", duration_min: 90, price: 1100, color: C.purple, employees: [3] },
{ name: "Manicura semipermanente", category: "Uñas", duration_min: 60, price: 450, color: C.pink, employees: [4] },
{ name: "Pedicura spa", category: "Uñas", duration_min: 60, price: 550, color: C.pink, employees: [4] },
],
clients: SPA_CLIENTS,
},
{
key: "barberia",
name: "Urban Cut Barbería",
industry: "Barbería",
currency: "MXN",
currency_symbol: "$",
description: "Barbería moderna: cortes, arreglo de barba, tratamientos capilares para caballero.",
emailDomain: "@urbancut.mx",
employees: [
{ name: "Andrés Morales", role: "Barbero Senior", color: C.orange },
{ name: "Tomás Rivas", role: "Barbero", color: C.blue },
{ name: "Bruno Salazar", role: "Barbero Junior", color: C.green },
{ name: "Hugo Beltrán", role: "Especialista en Barba", color: C.amber },
],
services: [
{ name: "Corte clásico", category: "Cortes", duration_min: 30, price: 150, color: C.orange, employees: [0, 1, 2] },
{ name: "Corte + diseño", category: "Cortes", duration_min: 45, price: 220, color: C.orange, employees: [0, 1] },
{ name: "Arreglo de barba", category: "Barba", duration_min: 30, price: 120, color: C.amber, employees: [3] },
{ name: "Corte + barba", category: "Combo", duration_min: 60, price: 280, color: C.indigo, employees: [0, 1, 3] },
{ name: "Rasurado tradicional con toalla", category: "Barba", duration_min: 45, price: 200, color: C.amber, employees: [3] },
{ name: "Tinte de cabello", category: "Color", duration_min: 90, price: 600, color: C.purple, employees: [0] },
{ name: "Tratamiento hidratante capilar", category: "Tratamientos", duration_min: 40, price: 350, color: C.teal, employees: [0, 1] },
{ name: "Cejas masculinas", category: "Detalles", duration_min: 20, price: 80, color: C.pink, employees: [2, 3] },
],
clients: [
"Ricardo Vargas","Javier Estrada","Andrés Ortega","Eduardo Mendoza","Carlos Iglesias",
"Miguel Torres","Sebastián Navarro","Bruno Aguilar","Emilio Domínguez","Rodrigo Herrera",
"Fernando Ruiz","Diego Soto","Hugo Mendoza","Tomás Cisneros","Manuel Vega",
].map((n, i) => ({ name: n, tags: i % 5 === 0 ? "VIP" : i % 3 === 0 ? "Frecuente" : undefined })),
},
{
key: "clinica",
name: "Clínica Dental Sonrisa",
industry: "Salud / Dental",
currency: "MXN",
currency_symbol: "$",
description: "Clínica dental: limpieza, ortodoncia, estética dental y consultas.",
emailDomain: "@sonrisa.mx",
employees: [
{ name: "Dra. Elena Vargas", role: "Dentista General", color: C.blue },
{ name: "Dr. Pablo Núñez", role: "Ortodoncista", color: C.green },
{ name: "Dra. Reina Flores", role: "Estética Dental", color: C.pink },
{ name: "Lic. Martha Ibáñez", role: "Higienista", color: C.teal },
],
services: [
{ name: "Consulta y diagnóstico", category: "Consulta", duration_min: 30, price: 400, color: C.blue, employees: [0] },
{ name: "Limpieza dental profunda", category: "Higiene", duration_min: 60, price: 700, color: C.teal, employees: [3] },
{ name: "Blanqueamiento dental", category: "Estética", duration_min: 90, price: 2500, color: C.pink, employees: [2] },
{ name: "Carillas dentales", category: "Estética", duration_min: 120, price: 4500, color: C.pink, employees: [2] },
{ name: "Consulta de ortodoncia", category: "Ortodoncia", duration_min: 45, price: 600, color: C.green, employees: [1] },
{ name: "Ajuste de brackets", category: "Ortodoncia", duration_min: 60, price: 800, color: C.green, employees: [1] },
{ name: "Extracción simple", category: "Cirugía", duration_min: 60, price: 1200, color: C.orange, employees: [0] },
{ name: "Resina (obturación)", category: "Restauración", duration_min: 45, price: 900, color: C.indigo, employees: [0] },
],
clients: [
"Mariana López","Patricia Moreno","Lucía Fernández","Daniela Castro","Valeria Guzmán",
"Fernanda Romero","Andrea Vega","Natalia Reyes","Camila Soto","Renata Domínguez",
"Alejandra Pérez","Gabriela Sánchez","Roberto Díaz","Carlos Iglesias","Eduardo Mendoza",
].map((n, i) => ({ name: n, tags: i % 4 === 0 ? "VIP" : undefined, notes: i % 2 === 0 ? "Alergia a anestesia local" : undefined })),
},
{
key: "blank",
name: "Nuevo Negocio",
industry: "General",
currency: "MXN",
currency_symbol: "$",
description: "Plantilla vacía: sin servicios ni datos demo. Configura todo desde cero.",
emailDomain: "@demo.mx",
employees: [],
services: [],
clients: [],
},
];
export function getTemplate(key: string): TemplateDef | undefined {
return TEMPLATES.find((t) => t.key === key);
}
export const DEFAULT_TEMPLATE_KEY = "estetica-spa";