brackt/plan.md
Chris Parsons eb7aa42cef
Add implementation plan for commissioner-without-team feature (#6)
* Add implementation plan for commissioner-without-team feature

https://claude.ai/code/session_01NSRMSYtb7jSFbngDS8okn3

* Allow commissioners to exist without owning a team

- Add opt-out checkbox on league creation ("I want to play in this league")
  so the creator can be commissioner-only without claiming a team
- Add Commissioner Management card to league settings with add/remove
  commissioner UI; guards against removing the last commissioner
- Add countCommissionersByLeagueId model helper for the last-commissioner guard
- Show "No team" indicator on the league homepage next to commissioners
  who don't own a team in the current season

https://claude.ai/code/session_01NSRMSYtb7jSFbngDS8okn3

* Fix code review issues in commissioner management

- Add success/error feedback banners to commissioner add/remove actions
- Gate allUsers query to admin-only (prevents exposing all users to non-admin commissioners)
- Prevent commissioner self-removal in both action (server) and UI (client)
- Add "(you)" label next to current user in commissioner list
- Remove all unnecessary `any` type casts in favor of inferred types

https://claude.ai/code/session_01NSRMSYtb7jSFbngDS8okn3

* Allow commissioners to add league members as co-commissioners

Non-admin commissioners can now add users who already own a team in
the league as co-commissioners. Admins still see the full user list.
Previously the add-commissioner form was admin-only.

https://claude.ai/code/session_01NSRMSYtb7jSFbngDS8okn3

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 08:45:09 -08:00

3.7 KiB

Plan: Commissioner Without a Team

Current State

At the database level, commissioners and teams are already independent:

  • Commissioners are stored in the commissioners table (league-level, keyed by leagueId + userId)
  • Teams are stored in the teams table (season-level, keyed by seasonId + ownerId)
  • A commissioner does NOT need a team to access the league homepage or draft room — this already works

The actual problem is that there's no way to become a commissioner without also getting a team:

  1. League creation (app/routes/leagues/new.tsx:198-201): The creator is always assigned the first team (ownerId: i === 0 ? userId : null)
  2. No "Add Commissioner" UI: There's no way for a league creator to add additional commissioners at all
  3. Invite link flow (app/routes/i.$inviteCode.tsx): Joining always assigns a team — there's no option to join as commissioner-only

Also, the league creation flow has no opt-out for team ownership — the creator always gets Team 1.

Changes

1. League creation: Add "Join as player" checkbox

File: app/routes/leagues/new.tsx

  • Add a checkbox: "I want to play in this league" (checked by default)
  • When unchecked, skip assigning the creator to the first team (all teams get ownerId: null)
  • When checked, behavior stays the same (creator gets first team)

2. Add Commissioner Management UI to League Settings

File: app/routes/leagues/$leagueId.settings.tsx

  • Add a new "Commissioner Management" card section
  • Show current commissioners with a "Remove" button (cannot remove if they're the last commissioner)
  • Add an "Add Commissioner" form with a user search/select dropdown
    • Only show users who are already members of the league (team owners) OR allow adding by searching all users
    • Since only the site admin can currently assign users to teams, let's keep it simple: commissioners can add any registered user as a commissioner
  • Backend actions: add-commissioner and remove-commissioner intents

3. Model changes

File: app/models/commissioner.ts

  • Already has createCommissioner, deleteCommissioner, removeCommissionerByLeagueAndUser — these are sufficient
  • Add countCommissionersByLeagueId to prevent removing the last commissioner

4. Settings loader changes

File: app/routes/leagues/$leagueId.settings.tsx

  • Load commissioners list and user data for display
  • Load all users list for the "add commissioner" dropdown (reuse existing allUsers pattern but make it available to commissioners, not just admins)

5. League homepage: Show commissioner-only indicator

File: app/routes/leagues/$leagueId.tsx

  • In the commissioners list, if a commissioner doesn't own a team in the current season, show a "(No team)" indicator next to their name
  • This helps distinguish playing commissioners from non-playing commissioners

Files to modify

  1. app/routes/leagues/new.tsx — Add "play in league" checkbox, conditionally assign first team
  2. app/models/commissioner.ts — Add countCommissionersByLeagueId helper
  3. app/routes/leagues/$leagueId.settings.tsx — Add commissioner management card (loader + action + UI)
  4. app/routes/leagues/$leagueId.server.ts — Pass team ownership info for commissioners to the homepage
  5. app/routes/leagues/$leagueId.tsx — Show "(No team)" indicator for commissioners without teams

Out of scope (not changing)

  • The invite link flow — this is for players joining, not commissioners. Commissioners should be added through settings.
  • The createdBy vs commissioners table inconsistency in draft control endpoints — that's a separate bug
  • Adding a way for a commissioner to later claim/release a team mid-season — possible future work but not needed here