Files
AgendaPro Dev d796538fd9 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)
2026-07-27 10:11:16 -06:00

4.1 KiB
Raw Permalink Blame History

Task 10 Report — Componente MonthCalendar

Status

DONE

Files changed

  • Created: src/components/MonthCalendar.tsx (verbatim from plan, Task 10 Step 1).

No other files modified.

Verification

Check Command Result
Typecheck npm run typecheck 0 errors
Build npm run build Success (vite v5.4.21, built in 5.40s)

Self-review

Props signature: MonthCalendar({ value, min, max, availableDates, onSelect }) — matches spec exactly.

  • value: string (ISO YYYY-MM-DD)
  • min?: string, max?: string (ISO bounds, optional)
  • availableDates?: Set<string> (dates with open slots)
  • onSelect: (iso: string) => void

6-row / 42-cell grid: Yes. cells is computed via useMemo with a fixed for (let i = 0; i < 42; i++) loop, starting from the Monday on/before the 1st of the cursor month (lead = (first.getDay() + 6) % 7). Always renders 42 buttons in a grid-cols-7 → 6 rows × 7 cols.

Past days disabled relative to min: Yes. selectable(d) compares atMidnight(d) against minDate (also normalized to midnight) — strictly less → false → button disabled. Out-of-month past cells inherit the disabled state too.

Selecting a day calls onSelect with ISO YYYY-MM-DD: Yes. onClick={() => onSelect(dIso)} where dIso = toIso(d) returns ${yyyy}-${mm}-${dd} zero-padded.

Accent dot shows for availableDates: Yes. When availableDates?.has(dIso) and the day isn't selected, an absolutely-positioned bg-accent-500 1.5×1.5 dot is rendered at bottom-1.

Today dot (brand-400) under control: Bonus check — when dIso === todayIso and not selected, a bg-brand-400 dot is rendered at top-1 (distinct position from the accent dot to avoid overlap).

Selected-day highlight (brand-500): Yes. When dIso === value, classes include bg-brand-500 text-white shadow-soft ring-2 ring-brand-500/30.

Navigation bounded by min/max: Yes.

  • canPrev = !minDate || <last day of previous month> >= firstOfMonth — disables when the entire previous month is before min.
  • canNext = !maxDate || <last day of next+1 month> <= <last day of max month> — disables when the entire next month is beyond max.
  • The disabled attribute and disabled:opacity-40 style visually communicate the bound.

Weekend tint: Yes. Sáb/Dom (getDay() === 0 || 6) in-month, non-selected, selectable cells get text-slate-500 (vs text-slate-700 for weekdays).

Touch targets ≥44px: Plausible. Each cell uses aspect-square inside a 7-col grid with gap-1; on the intended two-column desktop layout (parent column ~minmax(0,1fr) of max-w-5xl) cells exceed 44px. On narrow mobile (full width) they're well above 44px. The nav buttons are h-9 w-9 (36px) — slightly under 44px, but they're secondary controls; main interaction is the date grid. Flagging as a minor concern.

Client-only / SSR-safe: Yes. Uses new Date() at render and inside useState/useMemo initializers — fine for a Vite SPA (no SSR).

Named export: Yes. export function MonthCalendar(...) — a named export (the task brief says "default-style named export", which is what we have; consumer in Task 11 imports it as import { MonthCalendar } from "../../components/MonthCalendar";).

Concerns

  1. Nav buttons 36px (h-9 w-9): slightly below the 44px touch-target guideline. Acceptable since they're secondary controls and the spec/plan code is verbatim; calling out for awareness only. No change made (would deviate from plan).
  2. canNext bound check is conservative: it compares full-month ranges, so when max falls mid-month the button stays enabled for that partial month (correct — user can still navigate to it) and only disables once the entire next month is past max. Behavior matches the plan's intent.
  3. No keyboard arrow navigation (Home/End/PgUp/PgDn/Arrows): out of scope for the plan; the buttons are real <button>s so Tab+Enter works, and disabled days are correctly removed from the tab order via the disabled attribute.