Roster + tryout number management — server-rendered HTML (Phase 4) #21

Closed
opened 2026-03-10 00:06:35 +00:00 by forgejo_admin · 0 comments

Lineage

plan-2026-03-08-tryout-prep → Phase 4

Repo

forgejo_admin/basketball-api

User Story

As Marcus (admin),
I want to open the roster on my phone, see all registered players with photos and profile completeness, and assign tryout numbers,
So that I can manage tryout day without a laptop or front desk.

As a coach,
I want to see player cards with photos, names, schools, and positions,
So that I can learn names and faces before evaluations.

Context

The roster endpoint already exists at GET /tenants/{tenant_slug}/roster (JSON) and GET /tenants/{tenant_slug}/roster/view (HTML). Currently it shows a basic table with player name, parent, and payment status. It needs to be enhanced into a proper player-card-based view with photos, profile completeness, tryout numbers, search/filter, and admin controls.

Players self-serve — they scan a QR code or click their email link and fill out their own profile on their phone. There is NO front-desk check-in terminal. The roster is a monitoring + management view for Marcus and coaches.

Phase 3a adds Westside red/black branding to all pages. This phase must use the same brand CSS. Phase 3a also adds registration tokens, so by the time this phase ships, players will be completing profiles and the roster will have real data to display.

The Player model already has tryout_number (Integer, nullable) and checked_in (Boolean, nullable) fields from migration 002.

File Targets

Files to modify:

  • src/basketball_api/routes/roster.py — enhanced HTML roster view with player cards, admin controls, coach view, search/filter, QR code generation. Westside red/black branded.
  • src/basketball_api/models.py — no changes needed (tryout_number + checked_in already exist)

Files to read for context:

  • src/basketball_api/routes/register.py — see brand CSS pattern after Phase 3a lands
  • src/basketball_api/models.py — Player fields: photo_url, name, height, position, graduating_class, current_school, tryout_number, checked_in, date_of_birth, team_preference
  • src/basketball_api/main.py — roster router already included at /tenants
  • ~/west-side-basketball/css/style.css — design tokens

Files NOT to touch:

  • src/basketball_api/routes/register.py — Phase 3a owns this
  • src/basketball_api/services/email.py — Phase 3b owns this

Acceptance Criteria

Admin roster view (/tenants/{slug}/roster/view with admin auth):

  • Player cards showing: photo (or placeholder), name, parent name, school, position, graduating class, height, tryout number, payment status, profile completeness indicator
  • Profile completeness = which optional fields are filled (photo, school, position, DOB, etc.) — show as a percentage or checklist
  • Assign tryout number: input field per player, POST to save. Can assign individually.
  • Bulk assign: button to auto-assign sequential numbers to all players missing a number (sorted by name or registration order)
  • Visual distinction between: paid + profile complete, paid + profile incomplete, paid + no profile
  • Search by player name (client-side filter, instant)
  • Total count: "34 registered, 28 profiles complete, 6 pending"
  • Mobile-responsive — works on Marcus's phone
  • Westside red/black branded

Coach roster view (same URL with coach auth):

  • Player cards: tryout number, photo, name, school, position, graduating class, height
  • Filter by position (dropdown)
  • Search by player name
  • Read-only — no edit controls, no payment info
  • Mobile-responsive
  • Westside red/black branded

QR code:

  • GET /tenants/{slug}/roster/qr — generates a printable page with QR code linking to https://basketball-api.tail5b443a.ts.net/register
  • QR code is large enough to scan from a table (minimum 200x200px)
  • Page includes text: "Scan to register for tryouts" + the URL as fallback

API endpoints:

  • POST /tenants/{slug}/roster/assign-number — body: {"player_id": N, "tryout_number": M}. Admin-only.
  • POST /tenants/{slug}/roster/bulk-assign — auto-assigns sequential numbers to all players without one. Admin-only. Returns count assigned.
  • Both endpoints auth-protected (admin role via pal-e-auth)

Test Expectations

  • Unit test: admin roster view returns all players with correct fields
  • Unit test: coach roster view excludes payment info and edit controls
  • Unit test: assign-number updates the correct player's tryout_number
  • Unit test: bulk-assign gives sequential numbers, skips players who already have one
  • Unit test: assign endpoints require admin auth (coach gets 403)
  • Unit test: search filter works (if server-side) or HTML contains search input (if client-side)
  • Run command: pytest tests/ -v

Constraints

  • Use same Westside red/black CSS brand as Phase 3a (extract from ~/west-side-basketball/css/style.css)
  • Player cards must show photos — use player.photo_url if set, otherwise a generic placeholder silhouette
  • QR code generation: use qrcode Python library (add to dependencies if not present) or inline SVG
  • Admin vs coach view: same route, different rendering based on auth role. Don't create separate routes.
  • Profile completeness logic: count filled optional fields (photo_url, date_of_birth, current_school, position, target_schools, hometown, team_preference) out of total. Display as "5/7 complete" or similar.
  • Client-side search is fine (JavaScript filter on the rendered cards) — keeps it simple, no server roundtrip

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • Ruff format + lint clean
  • project-westside-basketball
  • plan-2026-03-08-tryout-prep → Phase 4
  • Depends on: Issue #19 (Phase 3a — brand CSS must be applied first)
  • Used by: Marcus + coaches on tryout day (March 13)
### Lineage `plan-2026-03-08-tryout-prep` → Phase 4 ### Repo `forgejo_admin/basketball-api` ### User Story As Marcus (admin), I want to open the roster on my phone, see all registered players with photos and profile completeness, and assign tryout numbers, So that I can manage tryout day without a laptop or front desk. As a coach, I want to see player cards with photos, names, schools, and positions, So that I can learn names and faces before evaluations. ### Context The roster endpoint already exists at `GET /tenants/{tenant_slug}/roster` (JSON) and `GET /tenants/{tenant_slug}/roster/view` (HTML). Currently it shows a basic table with player name, parent, and payment status. It needs to be enhanced into a proper player-card-based view with photos, profile completeness, tryout numbers, search/filter, and admin controls. Players self-serve — they scan a QR code or click their email link and fill out their own profile on their phone. There is NO front-desk check-in terminal. The roster is a monitoring + management view for Marcus and coaches. Phase 3a adds Westside red/black branding to all pages. This phase must use the same brand CSS. Phase 3a also adds registration tokens, so by the time this phase ships, players will be completing profiles and the roster will have real data to display. The Player model already has `tryout_number` (Integer, nullable) and `checked_in` (Boolean, nullable) fields from migration 002. ### File Targets Files to modify: - `src/basketball_api/routes/roster.py` — enhanced HTML roster view with player cards, admin controls, coach view, search/filter, QR code generation. Westside red/black branded. - `src/basketball_api/models.py` — no changes needed (tryout_number + checked_in already exist) Files to read for context: - `src/basketball_api/routes/register.py` — see brand CSS pattern after Phase 3a lands - `src/basketball_api/models.py` — Player fields: photo_url, name, height, position, graduating_class, current_school, tryout_number, checked_in, date_of_birth, team_preference - `src/basketball_api/main.py` — roster router already included at `/tenants` - `~/west-side-basketball/css/style.css` — design tokens Files NOT to touch: - `src/basketball_api/routes/register.py` — Phase 3a owns this - `src/basketball_api/services/email.py` — Phase 3b owns this ### Acceptance Criteria **Admin roster view** (`/tenants/{slug}/roster/view` with admin auth): - [ ] Player cards showing: photo (or placeholder), name, parent name, school, position, graduating class, height, tryout number, payment status, profile completeness indicator - [ ] Profile completeness = which optional fields are filled (photo, school, position, DOB, etc.) — show as a percentage or checklist - [ ] Assign tryout number: input field per player, POST to save. Can assign individually. - [ ] Bulk assign: button to auto-assign sequential numbers to all players missing a number (sorted by name or registration order) - [ ] Visual distinction between: paid + profile complete, paid + profile incomplete, paid + no profile - [ ] Search by player name (client-side filter, instant) - [ ] Total count: "34 registered, 28 profiles complete, 6 pending" - [ ] Mobile-responsive — works on Marcus's phone - [ ] Westside red/black branded **Coach roster view** (same URL with coach auth): - [ ] Player cards: tryout number, photo, name, school, position, graduating class, height - [ ] Filter by position (dropdown) - [ ] Search by player name - [ ] Read-only — no edit controls, no payment info - [ ] Mobile-responsive - [ ] Westside red/black branded **QR code:** - [ ] `GET /tenants/{slug}/roster/qr` — generates a printable page with QR code linking to `https://basketball-api.tail5b443a.ts.net/register` - [ ] QR code is large enough to scan from a table (minimum 200x200px) - [ ] Page includes text: "Scan to register for tryouts" + the URL as fallback **API endpoints:** - [ ] `POST /tenants/{slug}/roster/assign-number` — body: `{"player_id": N, "tryout_number": M}`. Admin-only. - [ ] `POST /tenants/{slug}/roster/bulk-assign` — auto-assigns sequential numbers to all players without one. Admin-only. Returns count assigned. - [ ] Both endpoints auth-protected (admin role via pal-e-auth) ### Test Expectations - [ ] Unit test: admin roster view returns all players with correct fields - [ ] Unit test: coach roster view excludes payment info and edit controls - [ ] Unit test: assign-number updates the correct player's tryout_number - [ ] Unit test: bulk-assign gives sequential numbers, skips players who already have one - [ ] Unit test: assign endpoints require admin auth (coach gets 403) - [ ] Unit test: search filter works (if server-side) or HTML contains search input (if client-side) - Run command: `pytest tests/ -v` ### Constraints - Use same Westside red/black CSS brand as Phase 3a (extract from `~/west-side-basketball/css/style.css`) - Player cards must show photos — use `player.photo_url` if set, otherwise a generic placeholder silhouette - QR code generation: use `qrcode` Python library (add to dependencies if not present) or inline SVG - Admin vs coach view: same route, different rendering based on auth role. Don't create separate routes. - Profile completeness logic: count filled optional fields (photo_url, date_of_birth, current_school, position, target_schools, hometown, team_preference) out of total. Display as "5/7 complete" or similar. - Client-side search is fine (JavaScript filter on the rendered cards) — keeps it simple, no server roundtrip ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes - [ ] Ruff format + lint clean ### Related - `project-westside-basketball` - `plan-2026-03-08-tryout-prep` → Phase 4 - Depends on: Issue #19 (Phase 3a — brand CSS must be applied first) - Used by: Marcus + coaches on tryout day (March 13)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#21
No description provided.