brackt/plan.md

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