Skip to content

feat: re-add timezone-safe multi-weekday picker to recurring hangouts - #573

Open
juanmahidalgo wants to merge 1 commit into
masterfrom
feat/recurring-event-custom-weekdays
Open

feat: re-add timezone-safe multi-weekday picker to recurring hangouts#573
juanmahidalgo wants to merge 1 commit into
masterfrom
feat/recurring-event-custom-weekdays

Conversation

@juanmahidalgo

Copy link
Copy Markdown
Contributor

Follow-up to #561 (issue #560).

Context

#561 collapsed the hangout recurrence UI into one dropdown and, to kill the "Toxic Tuesday" phantom-occurrence bug, dropped the per-weekday picker and derived the weekly weekday from start_at. That removed the ability to schedule a single event on multiple weekdays (e.g. Mon/Wed/Fri), which is a real use case. This PR brings the multi-weekday picker back — without reopening the bug.

Why the bug happened (and how this avoids it)

The events server stores recurrent_weekday_mask and runs its RRule in UTC, while the form collects weekdays in the creator's local calendar. The original bug was a phantom occurrence: start_at's own UTC weekday wasn't present in the stored mask, so RRule emitted the start day on top of the rule's days. The fix guarantees that can't happen:

  • The start date's weekday chip is always selected and locked.
  • On submit, the selected local weekdays are converted to UTC via the start instant's day delta (localWeekdaysToUtcMask), so occurrences land on the creator's intended local days and start_at's UTC weekday is always in the mask.

Changes

  • src/utils/recurrence.ts: new effectiveWeekdays (always folds in the start weekday), localWeekdaysToUtcMask / utcMaskToLocalWeekdays (local↔UTC conversion anchored on the start instant).
  • Form: repeatDays back in form state; weekday chips render for weekly cadences (every week / 2 / 3 / 4 weeks) with the start day locked; submit builds the UTC mask from the selected days (daily/monthly still send 0). Edit hydration decodes the stored mask back to local weekdays.
  • Upcoming-dates preview: now projects every selected weekday within each active interval-week cycle (Monday WKST).
  • Event detail modal: decodeRecurrentByDay now decodes the UTC mask into the viewer's local weekdays, so the recurrence label matches the locally-formatted schedule and the create-form preview.
  • i18n: re-added repeat_on across all six locales.

Test plan

  • Unit specs: recurrence.spec.ts (conversion + wrap + start-weekday-always-present invariant, with mocked UTC delta), useCreateEventForm.helpers.spec.ts (multi-day preview + mask hydration), useCreateEventForm.spec.tsx (mask carries start weekday + extra days), EventForm.spec.tsx (chips render/lock/toggle, hidden for non-weekly). Local full-suite run deferred to CI for memory reasons.
  • Create a weekly hangout, select Mon/Wed/Fri, confirm the preview lists those days and the saved event renders only on them.
  • Edit an existing single-day weekly event and confirm its weekday is pre-selected and locked.

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sites Ready Ready Preview, Comment Jun 10, 2026 6:59pm

Request Review

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 27299074920

Coverage increased (+0.02%) to 93.543%

Details

  • Coverage increased (+0.02%) from the base build.
  • Patch coverage: 5 uncovered changes across 2 files (50 of 55 lines covered, 90.91%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
src/components/whats-on/EventDetailModal/normalizers.ts 4 1 25.0%
src/components/whats-on/CreateEvent/EventForm.tsx 16 14 87.5%
Total (5 files) 55 50 90.91%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 6329
Covered Lines: 6186
Line Coverage: 97.74%
Relevant Branches: 4434
Covered Branches: 3882
Branch Coverage: 87.55%
Branches in Coverage %: Yes
Coverage Strength: 17.55 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants