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.
169 lines
8.1 KiB
TypeScript
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";
|