Review: Bug: player profile page doesn't display parent phone number

review-737-2026-04-03 Doc

review ready

Verdict: READY

Template Completeness

  • [x] Type — Bug
  • [x] Lineage — Standalone, discovered during admin CRM audit
  • [x] Repo — forgejo_admin/westside-landing
  • [x] What Broke — detailed root cause with line references
  • [x] Repro Steps — step-by-step with real player data
  • [x] Expected Behavior — clear target state
  • [x] Environment — cluster/namespace identified
  • [x] Acceptance Criteria — 5 criteria, all testable
  • [x] Related — companion issue referenced

Traceability

  • [x] story:WS-S12 — "As an admin, I want to manage user accounts (reset passwords, view profiles) so that I can support parents directly"
  • [x] story note verified — found in project-westside-basketball user-stories section under Admin (Marcus)
  • [x] arch:westside-app — references the SvelteKit frontend
  • [ ] arch note MISSING — [SCOPE] Create architecture note arch-westside-app for component westside-app (pre-existing gap, not specific to this ticket)
  • [x] Forgejo issue — forgejo_admin/westside-landing#203, open

File Targets

  • [x] src/routes/(app)/players/[id]/+page.svelte — verified exists (576 lines)
  • [x] Line 540: template checks player.parent_phone — confirmed at line 540
  • [x] Line 56: player = await apiFetch(`/players/${id}`) — confirmed at line 56, assigns raw API response with no field mapping
  • [x] Line 45: mock data uses flat parent_phone shape — confirmed
  • [x] API response shape verified: basketball-api/src/basketball_api/routes/players.py returns nested parent: { id, name, email, phone } via PlayerProfileResponse (line 40) and ParentInfo (line 25)

Repo Placement

Correct. The fix belongs in westside-landing (the SvelteKit frontend). The data shape mismatch is on the consumer side — the API returns a well-structured nested response; the frontend needs to map player.parent.phone to player.parent_phone (or update template references). Companion issue basketball-api#276 is separate (admin list endpoint, different code path).

Dependencies

  • [x] Board item #736 (basketball-api#276: "parent phone missing from /admin/players list endpoint") — companion but not a blocker. That issue is about the admin list endpoint; this issue is about the individual player profile page. They use different API endpoints and different response schemas.
  • No unresolved blockers.

Acceptance Criteria

All 5 criteria are testable by an agent:
  • [x] AC1: Phone link in Admin Actions — verifiable via DOM inspection after login
  • [x] AC2: Specific player 111 phone — verifiable with known data
  • [x] AC3: Parent name/email still display — regression check
  • [x] AC4: Mock player 999 still renders — route to /players/999
  • [x] AC5: Coach roster unaffected — uses different endpoint/data shape, no risk

Blast Radius

  • parent_email has the same bug: Line 546 checks player.parent_email but API returns player.parent.email. The issue only mentions phone, but email is equally broken with real API data.
  • parent_name has the same bug: Not rendered in Admin Actions card, but the fallback error handler (line 76) sets flat parent_name: '' — inconsistent with API shape.
  • Coach page (/coach/+page.svelte) uses flat parent_phone but consumes a different endpoint (/roster) that returns flat fields — no blast radius there.
  • Admin players page (/admin/players/+page.svelte) uses flat parent_name/parent_phone from /admin/players endpoint which also returns flat — no blast radius there.
  • Rollback is straightforward — single file, UI-only change.

Decomposition Assessment

Apply the three-thing limit and five-minute rule:
  • 1 file target, 1 repo — well under the 3-file threshold
  • 5 acceptance criteria — at the limit but all are simple verification checks
  • Estimated agent work: <5 minutes (add field mapping after apiFetch on line 56)
  • No independent subtasks to parallelize
  • No decomposition needed.

Recommendation

  • [BODY] Add note to issue body: "parent_email (line 546) and parent_name (line 76 fallback) have the same nested-vs-flat mismatch. Fix should map all three parent fields from player.parent.{name, email, phone} after the apiFetch call on line 56."
  • [SCOPE] Create architecture note arch-westside-app for component westside-app (pre-existing gap across multiple tickets, not a blocker for this one).