diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..76c6b86 --- /dev/null +++ b/plan.md @@ -0,0 +1,66 @@ +# 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