feat: rebrand AgendaPro -> AgendaMax + calendar fixes + current-week demo seed

- Rebrand all user-facing text to AgendaMax
- Fix sidebar scrolling: card container no longer overflows html (flex h-full min-h-0)
- Fix calendar toolbar hover: active buttons keep readable contrast
- Sticky calendar toolbar (month/week/day always visible on scroll)
- Seed guarantees 2-4 appointments per day for current week (Mon-Sat)
This commit is contained in:
AgendaPro Dev
2026-07-27 10:11:16 -06:00
parent 4227db0c8b
commit d796538fd9
57 changed files with 2477 additions and 322 deletions
+14 -2
View File
@@ -178,6 +178,16 @@ bookingRouter.post("/:slug/book", (req, res) => {
clientId = created.id;
}
// F18: soft no-show enforcement (nunca bloquea la reserva)
const nsCount = (db.prepare("SELECT COUNT(*) c FROM appointments WHERE client_id = ? AND status = 'no_show'").get(clientId) as { c: number })?.c ?? 0;
const ns = typeof nsCount === "number" ? nsCount : Number(nsCount) || 0;
const riskFlag = ns >= 2;
let notesBase = client.notes || "Reserva online";
if (ns >= 3) {
notesBase = `[Riesgo de no-show] ${notesBase}`;
db.prepare(`UPDATE clients SET tags = 'Riesgo' WHERE id = ? AND (tags IS NULL OR tags NOT LIKE '%Riesgo%')`).run(clientId);
}
const endIso = new Date(endMs).toISOString().replace(/\.\d{3}Z$/, "Z");
const startIso = new Date(startMs).toISOString().replace(/\.\d{3}Z$/, "Z");
const appt = db
@@ -185,10 +195,10 @@ bookingRouter.post("/:slug/book", (req, res) => {
`INSERT INTO appointments (business_id, service_id, employee_id, client_id, start_at, end_at, status, price, notes)
VALUES (?, ?, ?, ?, ?, ?, 'scheduled', ?, ?) RETURNING *`
)
.get(biz.id, Number(service_id), empId, clientId, startIso, endIso, service.price, client.notes || "Reserva online") as any;
.get(biz.id, Number(service_id), empId, clientId, startIso, endIso, service.price, notesBase) as any;
const empName = (db.prepare(`SELECT name FROM employees WHERE id = ?`).get(empId) as any)?.name;
return { appt, empId: empId as number, empName, reasons, clientCreated: !match };
return { appt, empId: empId as number, empName, reasons, clientCreated: !match, noShowCount: ns, riskFlag };
});
res.status(201).json({
@@ -204,6 +214,8 @@ bookingRouter.post("/:slug/book", (req, res) => {
},
business: { name: biz.name, currency_symbol: biz.currency_symbol },
client_created: result.clientCreated,
no_show_count: result.noShowCount,
risk_flag: result.riskFlag,
});
} catch (e: any) {
if (e && typeof e === "object" && e.status) {