brackt/app/routes
Chris Parsons b8b58ec9f8
Add draft email notifications feature (#459)
* Add on-the-clock email notifications and fix push notification modal

- Add `draft_email_notifications_enabled` column to users table
- New `sendOnTheClockEmail` service sends an email when a user's turn arrives
  in a draft; detects back-to-back picks and sends one combined email instead
  of two; skips notification if the team has autodraft enabled
- Email is triggered after every manual pick (make-pick route) and every
  timer-expiry pick (executeAutoPick) once the full autodraft chain settles,
  so the notified user is always the first human on the clock
- Add email notification toggle to the user settings Notifications section
- Fix push notification dropdown in the draft room: the bare absolute div is
  replaced with a Radix Popover so clicking outside dismisses it without
  toggling notifications off
- Rename draft room label from "Pick Notifications" to "Push Notifications"
  to distinguish from the new email notifications

https://claude.ai/code/session_01LMGxgYvtE3CF8Jf3u2pXgA

* Address code review feedback on email notification feature

- sendOnTheClockEmail now fetches season (and currentPickNumber) internally,
  removing the blocking postChainSeason pre-fetch from both make-pick.ts and
  executeAutoPick; callers are now true fire-and-forget with no IIFE needed
- Parallel Promise.all for team, autodraftSettings, and league queries reduces
  sequential DB round-trips from 5 to 3
- Remove team.ownerId type cast; assign to local after the null guard
- Combine the two calculatePickInfo calls for the same pick into one
- Fix popoverOpen/enabled divergence: remove the {enabled && ...} guard on
  PopoverContent so popoverOpen is the sole visibility control
- Unify NotificationsSection feedback pattern: both Discord and email sections
  now read success/error directly from their respective fetcher data via a
  shared feedbackFromFetcher helper; removes the success/error props and the
  verbose cast that was used for email
- Add 13 unit tests for sendOnTheClockEmail covering: early-exit paths
  (no season, past totalPicks, no owner, notifications disabled, autodraft
  enabled, no league), single vs back-to-back subject selection, draft room
  link presence, error logging without throwing, and parallel query execution

https://claude.ai/code/session_01LMGxgYvtE3CF8Jf3u2pXgA

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-20 15:35:43 -07:00
..
__tests__ Add public sports overview page (#451) 2026-05-19 23:02:58 -07:00
admin/__tests__ Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
api Add draft email notifications feature (#459) 2026-05-20 15:35:43 -07:00
leagues Add draft email notifications feature (#459) 2026-05-20 15:35:43 -07:00
teams Show owner avatar in team settings preview (#386) 2026-05-06 16:00:15 -07:00
admin._index.tsx Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
admin.data-sync.tsx Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
admin.participants.tsx feat: add meta title to all route pages (#109) 2026-03-10 12:10:52 -07:00
admin.simulators.tsx Hide completed seasons in admin tools (#418) 2026-05-12 16:52:26 -07:00
admin.sports-seasons.$id.clone.tsx Formalize simulator system with manifest, input-policy, runner, and admin UI (#409) 2026-05-11 21:09:53 -07:00
admin.sports-seasons.$id.elo-ratings.tsx Fix EPL simulator parity config (#421) 2026-05-13 15:02:23 -07:00
admin.sports-seasons.$id.events.$eventId.bracket.server.ts Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
admin.sports-seasons.$id.events.$eventId.bracket.tsx Fix NBA play-in elimination display and consolidate bracket reprocessing (#299) 2026-04-15 14:56:33 -07:00
admin.sports-seasons.$id.events.$eventId.cs2-setup.tsx Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
admin.sports-seasons.$id.events.$eventId.helpers.ts feat: batch qualifying results entry (#290) 2026-04-12 14:52:22 -07:00
admin.sports-seasons.$id.events.$eventId.server.ts Add not-participating exclusion support for event results (#446) 2026-05-19 11:13:32 -07:00
admin.sports-seasons.$id.events.$eventId.tsx Add not-participating exclusion support for event results (#446) 2026-05-19 11:13:32 -07:00
admin.sports-seasons.$id.events.server.ts Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
admin.sports-seasons.$id.events.tsx Remove sports_season_tournaments junction table — derive from scoring_events (#373) 2026-05-02 22:19:59 -07:00
admin.sports-seasons.$id.expected-values.server.ts Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
admin.sports-seasons.$id.expected-values.tsx Fix oxlint warnings: no-shadow, consistent-function-scoping, no-non-null-assertion, and others (#196) 2026-03-21 10:59:51 -07:00
admin.sports-seasons.$id.futures-odds.tsx Fix NCAAW futures odds simulation and admin import UX (#420) 2026-05-13 01:06:16 -07:00
admin.sports-seasons.$id.golf-skills.tsx Canonical golf skills migration + copy participants feature (#369) 2026-05-02 10:29:28 -07:00
admin.sports-seasons.$id.participants.tsx Canonical golf skills migration + copy participants feature (#369) 2026-05-02 10:29:28 -07:00
admin.sports-seasons.$id.regular-standings.tsx Deduplicate soccer simulator helpers (#391) 2026-05-07 11:48:57 -07:00
admin.sports-seasons.$id.simulate.tsx Formalize simulator system with manifest, input-policy, runner, and admin UI (#409) 2026-05-11 21:09:53 -07:00
admin.sports-seasons.$id.simulator.tsx Upgrade NCAA preseason simulators (#419) 2026-05-12 22:26:25 -07:00
admin.sports-seasons.$id.standings.tsx Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
admin.sports-seasons.$id.surface-elo.tsx Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
admin.sports-seasons.$id.tsx Improve unmatched team reconciliation UX (#425) 2026-05-14 16:45:02 -07:00
admin.sports-seasons.helpers.ts Hide completed seasons in admin tools (#418) 2026-05-12 16:52:26 -07:00
admin.sports-seasons.new.tsx Formalize simulator system with manifest, input-policy, runner, and admin UI (#409) 2026-05-11 21:09:53 -07:00
admin.sports-seasons.tsx Hide completed seasons in admin tools (#418) 2026-05-12 16:52:26 -07:00
admin.sports.$id.tsx Add public sports overview page (#451) 2026-05-19 23:02:58 -07:00
admin.sports.new.tsx Add public sports overview page (#451) 2026-05-19 23:02:58 -07:00
admin.sports.tsx Add public sports overview page (#451) 2026-05-19 23:02:58 -07:00
admin.standings-snapshots.tsx Replace console.* with structured logger, fix no-inferrable-types (closes #98) (#199) 2026-03-21 13:41:39 -07:00
admin.templates.$id.tsx Replace console.* with structured logger, fix no-inferrable-types (closes #98) (#199) 2026-03-21 13:41:39 -07:00
admin.templates.new.tsx Replace console.* with structured logger, fix no-inferrable-types (closes #98) (#199) 2026-03-21 13:41:39 -07:00
admin.templates.tsx feat: add meta title to all route pages (#109) 2026-03-10 12:10:52 -07:00
admin.tournaments.$id.tsx Remove sports_season_tournaments junction table — derive from scoring_events (#373) 2026-05-02 22:19:59 -07:00
admin.tournaments._index.tsx Canonical tournament layer: 2026-05-01 21:04:48 -07:00
admin.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
admin.users.tsx Add admin user management interface with search and username editing (#431) 2026-05-15 12:07:51 -07:00
api.admin.export-sports-data.ts Migrate authentication from Clerk to BetterAuth (#324) 2026-04-24 22:00:49 -07:00
api.auth.$.ts Migrate authentication from Clerk to BetterAuth (#324) 2026-04-24 22:00:49 -07:00
api.upload-avatar.ts Add Cloudinary-backed avatar system (#385) 2026-05-06 14:47:37 -07:00
api.upload-sport-icon.ts Add Cloudinary sports icon uploads (#393) 2026-05-07 16:07:34 -07:00
api.upload-team-logo.ts Add Cloudinary-backed avatar system (#385) 2026-05-06 14:47:37 -07:00
api.webhooks.cloudinary.ts Add Cloudinary-backed avatar system (#385) 2026-05-06 14:47:37 -07:00
check-email.tsx Add email verification for email/password signups (#400) 2026-05-09 23:58:45 -07:00
forgot-password.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
home.tsx Show commish-only leagues in a separate dashboard section, fixes #336 (#412) 2026-05-11 23:57:04 -07:00
how-to-play.tsx Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
i.$inviteCode.tsx Migrate auth from Clerk to BetterAuth (#354) 2026-04-29 10:03:50 -07:00
login.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
onboarding.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
privacy-policy.tsx New design (#309) 2026-04-23 13:14:55 -07:00
register.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
reset-password.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
rules.tsx Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
settings.tsx Add draft email notifications feature (#459) 2026-05-20 15:35:43 -07:00
sports.tsx Add public sports overview page (#451) 2026-05-19 23:02:58 -07:00
support.tsx Add branded dark-themed HTML email template (#402) 2026-05-10 11:18:57 -07:00
test-socket.tsx Replace console.* with structured logger, fix no-inferrable-types (closes #98) (#199) 2026-03-21 13:41:39 -07:00
upcoming-events.tsx Migrate authentication from Clerk to BetterAuth (#324) 2026-04-24 22:00:49 -07:00
user-profile-redirect.tsx Refactor user profile to comprehensive settings page (#403) 2026-05-10 17:26:14 -07:00