brackt/app/routes
Chris Parsons 22726550a6
Refactor user profile to comprehensive settings page (#403)
* Add account deletion and multi-section settings page

- Rename /user-profile → /settings with 301 redirect from old URL
- Add multi-section settings nav (Profile, Account, API placeholder, Data & Privacy)
  reusing existing SettingsDesktopNav/SettingsMobileGridNav components
- Implement account deletion via anonymization: wipes all PII from users row,
  releases team ownerships, removes commissioner records, deletes sessions/accounts
- Add data export request form that emails privacy@brackt.com via Resend
- Add deletedAt timestamp column to users table (migration 0100)
- Add anonymizeUserAccount() to user model
- Add removeAllCommissionersByUserId() to commissioner model
- Tests for both new model functions
- Update UserMenu "Profile" link → "Settings" at /settings

https://claude.ai/code/session_017Hvmof82Xr3UwKFc3pnC4X

* Address code review feedback on settings/account deletion

1. Wrap anonymizeUserAccount in a DB transaction so partial failures
   (e.g. session delete succeeds but user update fails) can't leave
   accounts in an inconsistent state
2. Escape user email and notes with escapeHtml() before interpolating
   into the data request email body
3. Reset AlertDialog confirmed state when dialog is dismissed via
   backdrop click or Escape key (onOpenChange handler)
4. Extract accounts DB query to app/models/account.ts (findLinkedAccountsByUserId)
   to comply with the "always query through app/models/" convention
5. Replace dynamic imports() in action handlers with static top-level imports
6. Remove the unused hard-delete deleteUser() function
7. Add lastDataRequestAt timestamp to users (migration 0101) and enforce
   a 30-day server-side cooldown on data export requests
8. Replace fragile actionData type casts with a proper ActionData
   discriminated union; narrowing now works without `as` assertions
9. Strengthen tests: verify which schema tables are passed to delete()
   and that operations run inside the transaction

https://claude.ai/code/session_017Hvmof82Xr3UwKFc3pnC4X

* Fix no-non-null-assertion lint error in PrivacySection

Replace non-null assertion with optional chaining on dataRequestCooldownUntil
to satisfy oxlint no-non-null-assertion rule.

https://claude.ai/code/session_017Hvmof82Xr3UwKFc3pnC4X

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-10 17:26:14 -07:00
..
__tests__ Add email verification for email/password signups (#400) 2026-05-09 23:58:45 -07:00
admin/__tests__ Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -07:00
api Show why a participant is ineligible to draft (#378) 2026-05-04 21:54:14 -07:00
leagues Refactor user profile to comprehensive settings page (#403) 2026-05-10 17:26:14 -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.sports-seasons.$id.clone.tsx Migrate authentication from Clerk to BetterAuth (#324) 2026-04-24 22:00:49 -07:00
admin.sports-seasons.$id.elo-ratings.tsx Fix college hockey bracket resolution (#396) 2026-05-08 12:29:39 -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 Canonical tournament layer: 2026-05-01 21:04:48 -07:00
admin.sports-seasons.$id.events.$eventId.tsx Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -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 Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -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 Canonical tournament layer: schema + backfill (1/2) (#365) 2026-05-01 20:13:18 -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 Remove sports_season_tournaments junction table — derive from scoring_events (#373) 2026-05-02 22:19:59 -07:00
admin.sports-seasons.new.tsx Replace isDraftable boolean with draftOn/draftOff date range (#263) 2026-04-05 22:09:52 -04:00
admin.sports-seasons.tsx Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
admin.sports.$id.tsx Harden sport icon cleanup (#397) 2026-05-08 21:19:09 -07:00
admin.sports.new.tsx Harden sport icon cleanup (#397) 2026-05-08 21:19:09 -07:00
admin.sports.tsx Add Cloudinary sports icon uploads (#393) 2026-05-07 16:07:34 -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 Canonical tournament layer: 2026-05-01 21:04:48 -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 Migrate auth from Clerk to BetterAuth (#354) 2026-04-29 10:03:50 -07:00
home.tsx Migrate authentication from Clerk to BetterAuth (#324) 2026-04-24 22:00:49 -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 Migrate auth from Clerk to BetterAuth (#354) 2026-04-29 10:03:50 -07:00
privacy-policy.tsx New design (#309) 2026-04-23 13:14:55 -07:00
register.tsx Add email verification for email/password signups (#400) 2026-05-09 23:58:45 -07:00
reset-password.tsx Migrate auth from Clerk to BetterAuth (#354) 2026-04-29 10:03:50 -07:00
rules.tsx Add Brackt as a league-private meta-sport (#200) (#377) 2026-05-04 20:31:44 -07:00
settings.tsx Refactor user profile to comprehensive settings page (#403) 2026-05-10 17:26:14 -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