Parent dashboard: show player's team schedule from practice_schedules via player_teams FK #214

Closed
opened 2026-04-04 20:00:01 +00:00 by forgejo_admin · 5 comments
Contributor

Type

Feature

User Story

story:WS-S28 As a parent, I want to see my child's team practice schedule so I know when and where to take them.

Lineage

  • Story: story:WS-S28
  • Arch: arch:landing-site
  • Blocked by: Nothing — basketball-api#333 (add team_ids to account response) is merged as PR #334
  • Blocks: Nothing

Repo

forgejo_admin/westside-landing (local checkout: ~/westside-app)

Context

The parent dashboard (/my-players) currently shows placeholder text: "Schedule data will appear here once practice times are confirmed." But 17 practice records and 8 events already exist in the database. The API surface is now complete:

  • GET /account/players returns team_ids: list[int] per player (basketball-api#334, merged 2026-04-04)
  • GET /public/schedule returns all practices with team_id and all events with team_id/division
  • Players connect to teams via player_teams M2M — a player can be on multiple teams

Data flow (decided):

  1. Fetch /account/players on mount → get each player's team_ids
  2. Fetch /public/schedule → get all practices and events
  3. Filter practices: practices.filter(p => playerTeamIds.includes(p.team_id))
  4. Filter events: events.filter(e => e.team_id && playerTeamIds.includes(e.team_id)) plus division fallback

Edge case: Sandra Apaisa has 3 players across 2 teams. Display should group schedules by player, showing each player's team schedule.

File Targets

  • src/routes/(app)/my-players/+page.svelte — replace placeholder text with functional schedule display

Acceptance Criteria

  1. Parent sees practice schedule with day name, 12-hour time, and venue for each player's team
  2. Schedule grouped by player name, then by team if player is on multiple teams
  3. Placeholder "Schedule data will appear here..." removed
  4. Events/tournaments shown — filtered by team_id match first, then division fallback
  5. Multi-player parents (e.g., Sandra with 3 players on 2 teams) see all relevant schedules
  6. No backend changes — pure frontend, client-side filtering of /public/schedule

Test Expectations

  • svelte-check passes with 0 errors
  • Schedule section renders practice cards per player
  • Multi-player parent sees grouped schedules

Constraints

  • Pure CSS variables, no Tailwind
  • No new API endpoints — use existing /account/players (with team_ids) + /public/schedule
  • /account/players response already includes team_ids (basketball-api#334 merged)

Checklist

  • Fetch /account/players to get each player's team_ids on mount
  • Fetch /public/schedule for all practices + events
  • Filter practices by player's team_ids
  • Filter events by team_id match + division fallback
  • Group display by player name, then team
  • Format times as 12-hour with AM/PM
  • Remove placeholder text
  • basketball-api#333 / PR #334 (add team_ids to AccountPlayerResponsemerged)
  • westside-landing#213 (coach dashboard schedule — sibling ticket)
  • westside-landing#209 / PR #216 (public schedule grouping fix — merged)
### Type Feature ### User Story `story:WS-S28` As a parent, I want to see my child's team practice schedule so I know when and where to take them. ### Lineage - **Story:** `story:WS-S28` - **Arch:** `arch:landing-site` - **Blocked by:** Nothing — basketball-api#333 (add `team_ids` to account response) is merged as PR #334 - **Blocks:** Nothing ### Repo `forgejo_admin/westside-landing` (local checkout: `~/westside-app`) ### Context The parent dashboard (`/my-players`) currently shows placeholder text: "Schedule data will appear here once practice times are confirmed." But 17 practice records and 8 events already exist in the database. The API surface is now complete: - `GET /account/players` returns `team_ids: list[int]` per player (basketball-api#334, merged 2026-04-04) - `GET /public/schedule` returns all practices with `team_id` and all events with `team_id`/`division` - Players connect to teams via `player_teams` M2M — a player can be on multiple teams **Data flow (decided):** 1. Fetch `/account/players` on mount → get each player's `team_ids` 2. Fetch `/public/schedule` → get all practices and events 3. Filter practices: `practices.filter(p => playerTeamIds.includes(p.team_id))` 4. Filter events: `events.filter(e => e.team_id && playerTeamIds.includes(e.team_id))` plus division fallback **Edge case:** Sandra Apaisa has 3 players across 2 teams. Display should group schedules by player, showing each player's team schedule. ### File Targets - `src/routes/(app)/my-players/+page.svelte` — replace placeholder text with functional schedule display ### Acceptance Criteria 1. Parent sees practice schedule with day name, 12-hour time, and venue for each player's team 2. Schedule grouped by player name, then by team if player is on multiple teams 3. Placeholder "Schedule data will appear here..." removed 4. Events/tournaments shown — filtered by `team_id` match first, then `division` fallback 5. Multi-player parents (e.g., Sandra with 3 players on 2 teams) see all relevant schedules 6. No backend changes — pure frontend, client-side filtering of `/public/schedule` ### Test Expectations - `svelte-check` passes with 0 errors - Schedule section renders practice cards per player - Multi-player parent sees grouped schedules ### Constraints - Pure CSS variables, no Tailwind - No new API endpoints — use existing `/account/players` (with `team_ids`) + `/public/schedule` - `/account/players` response already includes `team_ids` (basketball-api#334 merged) ### Checklist - [ ] Fetch `/account/players` to get each player's team_ids on mount - [ ] Fetch `/public/schedule` for all practices + events - [ ] Filter practices by player's team_ids - [ ] Filter events by team_id match + division fallback - [ ] Group display by player name, then team - [ ] Format times as 12-hour with AM/PM - [ ] Remove placeholder text ### Related - basketball-api#333 / PR #334 (add `team_ids` to `AccountPlayerResponse` — **merged**) - westside-landing#213 (coach dashboard schedule — sibling ticket) - westside-landing#209 / PR #216 (public schedule grouping fix — **merged**)
Author
Contributor

Alignment update (2026-04-04)

Story relabel: This ticket should be story:WS-S28 (new), not story:WS-S13.

  • WS-S13 (admin) = "view and manage program schedule" (admin CRUD)
  • WS-S28 (parent) = "see my child's team practice schedule" (added to project page)

API strategy decided: Fetch /public/schedule and filter client-side by team IDs from /account/players.

Dependency: basketball-api needs team_ids in AccountPlayerResponse.

  • Current /account/players returns team_name but no team_id
  • basketball-api issue created for this 1-line fix
  • Once team_ids is available: practices.filter(p => myPlayerTeamIds.includes(p.team_id))

Auth architecture updated: Player/parent role now includes "view team schedule" in arch-auth-westside-basketball.

Edge case confirmed: Sandra Apaisa (3 players, 2 teams) should see both team schedules grouped by player.

### Alignment update (2026-04-04) **Story relabel:** This ticket should be `story:WS-S28` (new), not `story:WS-S13`. - WS-S13 (admin) = "view and manage program schedule" (admin CRUD) - WS-S28 (parent) = "see my child's team practice schedule" (added to project page) **API strategy decided:** Fetch `/public/schedule` and filter client-side by team IDs from `/account/players`. **Dependency: basketball-api needs `team_ids` in AccountPlayerResponse.** - Current `/account/players` returns `team_name` but no `team_id` - basketball-api issue created for this 1-line fix - Once `team_ids` is available: `practices.filter(p => myPlayerTeamIds.includes(p.team_id))` **Auth architecture updated:** Player/parent role now includes "view team schedule" in arch-auth-westside-basketball. **Edge case confirmed:** Sandra Apaisa (3 players, 2 teams) should see both team schedules grouped by player.
Author
Contributor

Scope Review: NEEDS_REFINEMENT

Review note: review-809-2026-04-04
Cross-repo backend dependency not scoped — /account/players returns team_name but not team_id, which the frontend needs to filter /public/schedule by team.

  • [BODY] Add backend file target: basketball-api/src/basketball_api/routes/account.py — add team_id to AccountPlayerResponse
  • [BODY] Document the data flow (account/players → public/schedule client-side filter)
  • [BODY] Add AC: "API /account/players response includes team_id for each player"
  • [LABEL] Split: create separate basketball-api issue for the team_id addition, add depends: label
  • [SCOPE] Create architecture note arch-landing-site
## Scope Review: NEEDS_REFINEMENT Review note: `review-809-2026-04-04` Cross-repo backend dependency not scoped — `/account/players` returns `team_name` but not `team_id`, which the frontend needs to filter `/public/schedule` by team. - **[BODY]** Add backend file target: `basketball-api/src/basketball_api/routes/account.py` — add `team_id` to `AccountPlayerResponse` - **[BODY]** Document the data flow (account/players → public/schedule client-side filter) - **[BODY]** Add AC: "API /account/players response includes team_id for each player" - **[LABEL]** Split: create separate basketball-api issue for the `team_id` addition, add `depends:` label - **[SCOPE]** Create architecture note `arch-landing-site`
Author
Contributor

Scope refinement (2026-04-04)

Updated issue body to address review-809 findings:

  1. Backend dependency RESOLVED: basketball-api#333 merged as PR #334. /account/players now returns team_ids: list[int]. No cross-repo work needed.
  2. Data flow documented: /account/players (get team_ids) → /public/schedule (filter client-side). Explicit in body.
  3. No ticket split needed: Backend work is done. This is now a pure frontend ticket in westside-landing only.
  4. Repo clarified: Forgejo repo is westside-landing, local checkout is ~/westside-app.
  5. arch-landing-site note: Flagged for future creation (not blocking this ticket).
### Scope refinement (2026-04-04) Updated issue body to address review-809 findings: 1. **Backend dependency RESOLVED:** basketball-api#333 merged as PR #334. `/account/players` now returns `team_ids: list[int]`. No cross-repo work needed. 2. **Data flow documented:** `/account/players` (get team_ids) → `/public/schedule` (filter client-side). Explicit in body. 3. **No ticket split needed:** Backend work is done. This is now a pure frontend ticket in westside-landing only. 4. **Repo clarified:** Forgejo repo is `westside-landing`, local checkout is `~/westside-app`. 5. **`arch-landing-site` note:** Flagged for future creation (not blocking this ticket).
Author
Contributor

Scope Review: APPROVED

Review note: review-809-2026-04-04

Re-review passes. All prior NEEDS_REFINEMENT findings resolved:

  • Backend team_ids gap: basketball-api PR #334 merged (verified on origin/main, commit 2853efd)
  • Data flow: 4-step client-side filtering documented in issue body
  • Cross-repo split: not needed — backend done, pure frontend remaining
  • Template: all Feature sections present and complete
  • Traceability: story:WS-S28 verified, Forgejo issue open

One non-blocking [SCOPE] recommendation carried forward:

  • Create architecture note arch-landing-site for the westside-landing frontend component

Ticket is ready for dispatch.

## Scope Review: APPROVED Review note: `review-809-2026-04-04` Re-review passes. All prior NEEDS_REFINEMENT findings resolved: - Backend `team_ids` gap: basketball-api PR #334 merged (verified on origin/main, commit `2853efd`) - Data flow: 4-step client-side filtering documented in issue body - Cross-repo split: not needed — backend done, pure frontend remaining - Template: all Feature sections present and complete - Traceability: story:WS-S28 verified, Forgejo issue open One non-blocking [SCOPE] recommendation carried forward: - Create architecture note `arch-landing-site` for the westside-landing frontend component Ticket is ready for dispatch.
Author
Contributor

Validation: PASS

Tiers executed: Tier 1 (Playwright browser validation), Tier 3 (prod deployment + route smoke tests)

Validation note: validation-214-2026-04-04

Checks: 6 PASS, 0 FAIL

Deployment:

  • Woodpecker pipeline #217: success
  • Pod westside-landing-858b9788-pq57l: Running, 0 restarts
  • Image 282741ec7a... matches merge commit 282741e
  • 12 routes tested (/, /schedule, /my-players, /tryouts, /jersey, /teams, /admin, /admin/users, /admin/teams, /coach, /checkout, /about): all HTTP 200

Playwright (5/5):

  1. Parent login via Keycloak: PASS
  2. /my-players loads with schedule content: PASS
  3. Practices grouped by player: PASS
  4. Sandra Apaisa's 3 players visible: PASS
  5. Practice times with day, time, location: PASS

No regressions. No discovered issues.

## Validation: PASS **Tiers executed:** Tier 1 (Playwright browser validation), Tier 3 (prod deployment + route smoke tests) **Validation note:** `validation-214-2026-04-04` **Checks:** 6 PASS, 0 FAIL **Deployment:** - Woodpecker pipeline #217: success - Pod `westside-landing-858b9788-pq57l`: Running, 0 restarts - Image `282741ec7a...` matches merge commit `282741e` - 12 routes tested (/, /schedule, /my-players, /tryouts, /jersey, /teams, /admin, /admin/users, /admin/teams, /coach, /checkout, /about): all HTTP 200 **Playwright (5/5):** 1. Parent login via Keycloak: PASS 2. /my-players loads with schedule content: PASS 3. Practices grouped by player: PASS 4. Sandra Apaisa's 3 players visible: PASS 5. Practice times with day, time, location: PASS No regressions. No discovered issues.
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
ldraney/westside-app#214
No description provided.