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
+3
View File
@@ -44,6 +44,9 @@ const { status: bookStatus, json: booked } = await req("POST", `/public/${slug}/
});
check("reserva creada (auto-assign)", bookStatus === 201 && !!booked.appointment?.employee_id, `status=${bookStatus}`);
check("response trae reasons", Array.isArray(booked.appointment?.reasons) && booked.appointment.reasons.length > 0);
check("response trae no_show_count", typeof booked.no_show_count === "number", `got ${typeof booked.no_show_count}`);
check("response trae risk_flag", typeof booked.risk_flag === "boolean", `got ${typeof booked.risk_flag}`);
check("cliente nuevo → sin riesgo", booked.no_show_count === 0 && booked.risk_flag === false, `ns=${booked.no_show_count} risk=${booked.risk_flag}`);
// 5) Mismo slot otra vez → 409 (doble reserva del mismo especialista)
const { status: conflict } = await req("POST", `/public/${slug}/book`, {
+21 -2
View File
@@ -204,14 +204,14 @@ export function seedBusiness(opts: SeedBusinessOptions) {
let pastCount = 0;
let upCount = 0;
const makeAppt = (dayOffset: number, svcIdx: number, status: string, createdBy: number | null) => {
const makeAppt = (dayOffset: number, svcIdx: number, status: string, createdBy: number | null, fixedHour?: number) => {
const svc = template.services[svcIdx];
if (!svc) return null;
const empLocalIdx = pick(svc.employees);
const empId = empIds[empLocalIdx];
const svcId = svcIds[svcIdx];
const clientId = pick(clientIds);
const hour = pick([9, 10, 11, 12, 13, 14, 15, 16, 17, 18]);
const hour = fixedHour ?? pick([9, 10, 11, 12, 13, 14, 15, 16, 17, 18]);
const minute = pick([0, 30]);
const start = isoOffsetDays(dayOffset, hour, minute);
const end = addMinutes(start, svc.duration_min);
@@ -273,6 +273,25 @@ export function seedBusiness(opts: SeedBusinessOptions) {
}
}
// Guarantee visible appointments across the current week (MonSat) regardless of today's weekday
{
const now = new Date();
const dow = now.getDay(); // 0=Sun ... 6=Sat
const mondayOffset = dow === 0 ? -6 : 1 - dow;
for (let d = 0; d < 6; d++) {
const dayOffset = mondayOffset + d;
if (dayOffset < -60) continue;
const past = dayOffset < 0;
const isToday_ = dayOffset === 0;
const hours = pickN([10, 12, 14, 16, 18], rint(2, 4));
for (const hour of hours) {
const svcIdx = rint(0, template.services.length - 1);
const status = past ? "completed" : (isToday_ && hour <= now.getHours()) ? "completed" : "scheduled";
if (makeAppt(dayOffset, svcIdx, status, ownerRow?.id ?? null, hour)) upCount++;
}
}
}
// recompute ratings
db.exec(`
UPDATE employees SET rating = COALESCE(