- 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)
41 lines
3.2 KiB
Markdown
41 lines
3.2 KiB
Markdown
# Task 11 — `DateTimePicker` 2-col + month calendar + Mañana/Tarde grouping
|
||
|
||
## File changed
|
||
- `src/pages/public/BookingPage.tsx`
|
||
- Added `import { MonthCalendar } from "../../components/MonthCalendar";` (line 28).
|
||
- Rewrote `DateTimePicker` (now lines 556–639): 2-column grid on `md+`, vertical stack below `md`, new optional `max?: string` prop, slots grouped via new `SlotGroup` subcomponent.
|
||
- Added new `SlotGroup` helper (lines 641–681).
|
||
|
||
## Verification results
|
||
|
||
### `npm run typecheck`
|
||
```
|
||
> tsc -b --noEmit
|
||
```
|
||
**0 errors.** The existing caller of `DateTimePicker` (in `BookingPage`) does not pass `max` — confirms `max` is optional and not breaking the caller.
|
||
|
||
### `npm run build`
|
||
```
|
||
✓ 2461 modules transformed.
|
||
✓ built in 4.98s
|
||
```
|
||
**Succeeds.** Production bundle emitted.
|
||
|
||
### Visual smoke
|
||
Not executed interactively (subagent has no browser). Validated indirectly via successful `vite build` (2461 modules transformed, including the rewritten `BookingPage` and the imported `MonthCalendar`). Task 12 is responsible for wiring `max`/`employeeId` end-to-end and for any final interactive smoke; the unit of work in this task compiles and type-checks cleanly against the rest of the project.
|
||
|
||
## Self-review
|
||
|
||
| Check | Result |
|
||
|---|---|
|
||
| 2-col layout only on `md+` | ✅ Outer wrapper uses `md:grid md:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)] md:items-start md:gap-8`. Below `md` no grid is applied. |
|
||
| Mobile stacked vertically | ✅ Right column wrapper has `mt-4 md:mt-0` so on mobile the calendar card is followed by the slots card with vertical spacing; the outer div is a plain block (no `flex`/`grid`) below `md`. |
|
||
| Slot button markup unchanged | ✅ Identical classes (`grid grid-cols-3 gap-2 sm:grid-cols-4`; button `rounded-xl border px-2 py-2.5 text-sm font-bold transition-all`; active `border-brand-500 bg-brand-500 text-white shadow-soft`; inactive `border-slate-200 bg-white text-slate-700 hover:border-brand-400 hover:bg-brand-50`), same `key={`${slot.iso}-${slot.employee_id}`}`, same `onClick={() => onPick(slot)}`. Only the grouping wrapper (`SlotGroup`) is new. |
|
||
| Morning/afternoon split correct, incl. 12 PM boundary | ✅ Algorithm: parse `(\d{1,2}):(\d{2})` → `h`; `pm = /PM/i`; `hour24 = pm && h!==12 ? h+12 : !pm && h===12 ? 0 : h`; bucket by `hour24 < 12`. Verified cases: `12:00 AM` → h=12, !pm, h===12 → 0 → **Mañana**. `11:30 AM` → 11 → **Mañana**. `12:00 PM` → h=12, pm, h===12 (no +12) → 12 → **Tarde**. `12:30 PM` → 12 → **Tarde**. `1:00 PM` → 13 → **Tarde**. `11:59 PM` → 23 → **Tarde**. Boundary at noon is correct (12:00 PM is the first Tarde slot). |
|
||
| `max` is optional | ✅ Declared `max?: string`. Typecheck with caller that omits `max` passes. |
|
||
| No commit performed | ✅ No `git commit` run. |
|
||
| Scope respected (only `BookingPage.tsx`, only `DateTimePicker` + import + `SlotGroup`) | ✅ No other functions touched (`TopBar`, `ActionBar`, `Confirmation`, `EmployeeList`, `ServiceGrid`, `DetailsForm` unchanged; Task 8's `pl-10` untouched). |
|
||
|
||
## Concerns
|
||
- None. Implementation matches the plan verbatim. Interactive browser smoke deferred to the orchestrator / Task 12 (which will also pass `max` and `employeeId` to the picker and exercise the full wizard).
|