You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Competition dates become calendar events, alongside the exam sessions and personal events already there.
Files
src/app/calendar/CalendarView.tsx - extend, currently 478 lines
src/lib/competition-events.ts - new, flattens competitions into calendar events
What exists today
CalendarView.tsx is a hand-rolled month grid with no date library, and that stays true. Plain Date, plain CSS Grid.
:25-29BOARD_COLORS for SAT, IB, IGCSE
:31PERSONAL_EVENT_COLOR
:61-71getEventsInMonth
:91-104getActiveDaysForEvent handles multi-day windows
:201-205 builds the day cell array
:380-464 the grid itself, colored dots per board
Two event sources today: the static EXAM_EVENTS array (src/lib/exam-dates.ts) and the user_events Supabase table. Competitions is the third. Add a COMPETITION_EVENT_COLOR next to the existing constants.
The density problem, which has to be designed for rather than discovered
50 competitions with roughly 4 dates each, plus 13 country tracks with roughly 3 stages each, is well over 2000 potential events. Dropping all of that onto a month grid makes it unusable, particularly on mobile.
Three controls, in this order of importance:
Signed-in users with at least one save default to saved competitions only, with a toggle to show all.
Everyone else defaults to all competitions filtered to their country, never to an empty grid. This matters: a saved-only default would give every new and signed-out visitor a blank calendar, and an empty first screen is a bad first screen.
The estimated flag exists on every date and stage in the dataset. Render those visibly differently from confirmed ones: an outline dot rather than a filled one, and say so in the legend. ExamEvent already carries the same idea via resultsEstimated (src/lib/exam-dates.ts:13-29), so follow whatever that does.
Acceptance criteria
Competition dates appear on the correct days in the correct month
Signed out: the calendar is not empty, and shows country-scoped competitions
Signed in with saves: defaults to saved only, toggle reveals all
Signed in with no saves: does not show an empty grid
Only one country's stages render at a time
Estimated dates are visually distinct and explained in the legend
A day with many events stays legible at 360px wide
Month navigation stays smooth with all competitions shown
Supabase unconfigured: exam events and competitions still render, personal events and the saved filter are absent
Blocked by #195 and #200.
Competition dates become calendar events, alongside the exam sessions and personal events already there.
Files
src/app/calendar/CalendarView.tsx- extend, currently 478 linessrc/lib/competition-events.ts- new, flattens competitions into calendar eventsWhat exists today
CalendarView.tsxis a hand-rolled month grid with no date library, and that stays true. PlainDate, plain CSS Grid.:25-29BOARD_COLORSfor SAT, IB, IGCSE:31PERSONAL_EVENT_COLOR:61-71getEventsInMonth:91-104getActiveDaysForEventhandles multi-day windows:201-205builds the day cell array:380-464the grid itself, colored dots per boardTwo event sources today: the static
EXAM_EVENTSarray (src/lib/exam-dates.ts) and theuser_eventsSupabase table. Competitions is the third. Add aCOMPETITION_EVENT_COLORnext to the existing constants.The density problem, which has to be designed for rather than discovered
50 competitions with roughly 4 dates each, plus 13 country tracks with roughly 3 stages each, is well over 2000 potential events. Dropping all of that onto a month grid makes it unusable, particularly on mobile.
Three controls, in this order of importance:
countryon the user's profile (feat(onboarding): user_profiles table with RLS and CHECK constraints (SQL inline) #203) when present, otherwise a picker defaulting to a sensible guess. Never render all 13 at once.Estimated dates
The
estimatedflag exists on every date and stage in the dataset. Render those visibly differently from confirmed ones: an outline dot rather than a filled one, and say so in the legend.ExamEventalready carries the same idea viaresultsEstimated(src/lib/exam-dates.ts:13-29), so follow whatever that does.Acceptance criteria