Coach dashboard: show coach's team schedule from practice_schedules via team_id FK #213

Closed
opened 2026-04-04 19:59:49 +00:00 by forgejo_admin · 5 comments
Contributor

Type

Feature

User Story

story:WS-S27 As a coach, I want to see my team's practice schedule and upcoming events so I know when and where my teams practice and play.

Lineage

  • Story: story:WS-S27
  • Arch: arch:landing-site
  • Blocked by: Nothing (data verified, API exists)
  • Blocks: Nothing

Repo

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

Context

The coach dashboard (/coach) has a Schedule tab that currently shows "Coming soon" placeholder text. The data model already supports this:

  • coaches table links to teams via teams.coach_id
  • practice_schedules table links to teams via practice_schedules.team_id
  • events table links to teams via events.team_id and to divisions via events.division
  • 17 practice schedule records and 8 event records exist in the database
  • Marcus Draney coaches 2 teams (17U Elite Kings and 17U Local Kings)

API strategy (decided): Fetch /public/schedule and filter client-side by team IDs from /coaches/me.

  • /coaches/me returns teams[].id — no backend change needed
  • /public/schedule returns all practices with team_id and all events with team_id/division
  • Frontend filters practices: practices.filter(p => myTeamIds.includes(p.team_id))
  • Frontend filters events: events.filter(e => e.team_id && myTeamIds.includes(e.team_id)) plus division fallback events.filter(e => !e.team_id && myTeamDivisions.includes(e.division))

File Targets

  • src/routes/(app)/coach/+page.svelte — replace Schedule tab placeholder with functional schedule display

Acceptance Criteria

  1. Coach sees practice schedule with day name, 12-hour time, and venue for each assigned team
  2. Coaches with multiple teams (e.g., Marcus with 2) see all team schedules grouped by team
  3. "Coming soon" placeholder removed from Schedule tab
  4. Events/tournaments shown — filtered by team_id match first, then division match for unscoped events
  5. No backend changes — pure frontend, client-side filtering of /public/schedule

Test Expectations

  • svelte-check passes with 0 errors
  • Schedule tab renders practice cards for each team
  • Multi-team coach sees both teams' schedules

Constraints

  • Pure CSS variables, no Tailwind
  • No new API endpoints — use existing /coaches/me + /public/schedule
  • Verify /coaches/me response shape before coding (teams[].id is the key field)

Checklist

  • Fetch /coaches/me to get team IDs on mount
  • Fetch /public/schedule for all practices + events
  • Filter practices by team_id match
  • Filter events by team_id match + division fallback
  • Group display by team name
  • Format times as 12-hour with AM/PM
  • Remove "Coming soon" placeholder
  • basketball-api /coaches/me endpoint (src/basketball_api/routes/coaches_api.py)
  • basketball-api /public/schedule endpoint (src/basketball_api/routes/public.py)
  • westside-landing#209 (public schedule grouping fix — merged)
### Type Feature ### User Story `story:WS-S27` As a coach, I want to see my team's practice schedule and upcoming events so I know when and where my teams practice and play. ### Lineage - **Story:** `story:WS-S27` - **Arch:** `arch:landing-site` - **Blocked by:** Nothing (data verified, API exists) - **Blocks:** Nothing ### Repo `forgejo_admin/westside-landing` (local checkout: `~/westside-app`) ### Context The coach dashboard (`/coach`) has a Schedule tab that currently shows "Coming soon" placeholder text. The data model already supports this: - `coaches` table links to `teams` via `teams.coach_id` - `practice_schedules` table links to `teams` via `practice_schedules.team_id` - `events` table links to `teams` via `events.team_id` and to divisions via `events.division` - 17 practice schedule records and 8 event records exist in the database - Marcus Draney coaches 2 teams (17U Elite Kings and 17U Local Kings) **API strategy (decided):** Fetch `/public/schedule` and filter client-side by team IDs from `/coaches/me`. - `/coaches/me` returns `teams[].id` — no backend change needed - `/public/schedule` returns all practices with `team_id` and all events with `team_id`/`division` - Frontend filters practices: `practices.filter(p => myTeamIds.includes(p.team_id))` - Frontend filters events: `events.filter(e => e.team_id && myTeamIds.includes(e.team_id))` plus division fallback `events.filter(e => !e.team_id && myTeamDivisions.includes(e.division))` ### File Targets - `src/routes/(app)/coach/+page.svelte` — replace Schedule tab placeholder with functional schedule display ### Acceptance Criteria 1. Coach sees practice schedule with day name, 12-hour time, and venue for each assigned team 2. Coaches with multiple teams (e.g., Marcus with 2) see all team schedules grouped by team 3. "Coming soon" placeholder removed from Schedule tab 4. Events/tournaments shown — filtered by `team_id` match first, then `division` match for unscoped events 5. No backend changes — pure frontend, client-side filtering of `/public/schedule` ### Test Expectations - `svelte-check` passes with 0 errors - Schedule tab renders practice cards for each team - Multi-team coach sees both teams' schedules ### Constraints - Pure CSS variables, no Tailwind - No new API endpoints — use existing `/coaches/me` + `/public/schedule` - Verify `/coaches/me` response shape before coding (teams[].id is the key field) ### Checklist - [ ] Fetch `/coaches/me` to get team IDs on mount - [ ] Fetch `/public/schedule` for all practices + events - [ ] Filter practices by team_id match - [ ] Filter events by team_id match + division fallback - [ ] Group display by team name - [ ] Format times as 12-hour with AM/PM - [ ] Remove "Coming soon" placeholder ### Related - basketball-api `/coaches/me` endpoint (`src/basketball_api/routes/coaches_api.py`) - basketball-api `/public/schedule` endpoint (`src/basketball_api/routes/public.py`) - westside-landing#209 (public schedule grouping fix — merged)
Author
Contributor

Alignment update (2026-04-04)

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

  • WS-S13 (coach) = "view team roster with player photos" (roster, not schedule)
  • WS-S27 (coach) = "see my team's practice schedule and upcoming events" (added to project page)

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

  • /coaches/me already returns teams[].id — no backend change needed
  • /public/schedule returns all practices with team_id field
  • Frontend filters: practices.filter(p => myTeamIds.includes(p.team_id))

Auth architecture updated: Coach role now includes "view team schedule and events" in arch-auth-westside-basketball.

No backend ticket needed — this is pure frontend.

### Alignment update (2026-04-04) **Story relabel:** This ticket should be `story:WS-S27` (new), not `story:WS-S13`. - WS-S13 (coach) = "view team roster with player photos" (roster, not schedule) - WS-S27 (coach) = "see my team's practice schedule and upcoming events" (added to project page) **API strategy decided:** Fetch `/public/schedule` and filter client-side by team IDs from `/coaches/me`. - `/coaches/me` already returns `teams[].id` — no backend change needed - `/public/schedule` returns all practices with `team_id` field - Frontend filters: `practices.filter(p => myTeamIds.includes(p.team_id))` **Auth architecture updated:** Coach role now includes "view team schedule and events" in arch-auth-westside-basketball. **No backend ticket needed** — this is pure frontend.
Author
Contributor

Scope Review: NEEDS_REFINEMENT

Review note: review-808-2026-04-04

Well-scoped feature with thorough context and verified data model, but three issues need resolution before dispatch:

  • Backend approach undecided: /coaches/me returns no schedule data. Either (a) add /coaches/me/schedule endpoint in basketball-api (cross-repo, needs decomposition) or (b) client-side filter /public/schedule by team_id (single-repo). Commit to one approach and update File Targets.
  • AC4 ambiguous: "Events/tournaments if assigned to that team's division" — but Event model uses team_id FK, not division. Clarify filtering logic (team_id match? include program-wide events where team_id=NULL?).
  • Repo name mismatch: Issue filed on westside-landing but file target is in westside-app. Verify these are the same repo or fix the Repo field.
  • [SCOPE] Missing arch-landing-site architecture note in pal-e-docs (4+ board items reference this label).
  • If approach (a) is chosen: route to skill-decompose-ticket for two-repo split.
## Scope Review: NEEDS_REFINEMENT Review note: `review-808-2026-04-04` Well-scoped feature with thorough context and verified data model, but three issues need resolution before dispatch: - **Backend approach undecided:** `/coaches/me` returns no schedule data. Either (a) add `/coaches/me/schedule` endpoint in basketball-api (cross-repo, needs decomposition) or (b) client-side filter `/public/schedule` by team_id (single-repo). Commit to one approach and update File Targets. - **AC4 ambiguous:** "Events/tournaments if assigned to that team's division" — but Event model uses `team_id` FK, not division. Clarify filtering logic (team_id match? include program-wide events where team_id=NULL?). - **Repo name mismatch:** Issue filed on `westside-landing` but file target is in `westside-app`. Verify these are the same repo or fix the Repo field. - **[SCOPE]** Missing `arch-landing-site` architecture note in pal-e-docs (4+ board items reference this label). - If approach (a) is chosen: route to `skill-decompose-ticket` for two-repo split.
Author
Contributor

Scope refinement (2026-04-04)

Updated issue body to address review-808 findings:

  1. Backend approach committed: Client-side filter of /public/schedule using team IDs from /coaches/me. No backend changes. Was in comments only, now in body.
  2. AC4 events clarified: Filter events by team_id match first, then division fallback for unscoped events. Matches the data model (events have both team_id FK and division enum).
  3. Repo clarified: Forgejo repo is westside-landing, local checkout is ~/westside-app (old name). File path src/routes/(app)/coach/+page.svelte is correct.
### Scope refinement (2026-04-04) Updated issue body to address review-808 findings: 1. **Backend approach committed:** Client-side filter of `/public/schedule` using team IDs from `/coaches/me`. No backend changes. Was in comments only, now in body. 2. **AC4 events clarified:** Filter events by `team_id` match first, then `division` fallback for unscoped events. Matches the data model (events have both `team_id` FK and `division` enum). 3. **Repo clarified:** Forgejo repo is `westside-landing`, local checkout is `~/westside-app` (old name). File path `src/routes/(app)/coach/+page.svelte` is correct.
Author
Contributor

Scope Review: APPROVED

Review note: review-808-2026-04-04 (updated)

Re-review: all 3 prior NEEDS_REFINEMENT issues resolved. Backend approach committed (client-side filter), AC4 event filtering logic specified with code-level detail, repo naming clarified and verified via git remote.

Verified:

  • File target src/routes/(app)/coach/+page.svelte confirmed (lines 149-157, "Coming soon" placeholder)
  • /coaches/me returns teams[].id + teams[].division — both needed for filtering
  • /public/schedule returns practices[].team_id + events[].team_id + events[].division — matches filter strategy
  • story:WS-S27 confirmed in project-westside-basketball user-stories
  • 1 file, 1 repo, 5 ACs — no decomposition needed

Remaining [SCOPE] (non-blocking):

  • Create architecture note arch-landing-site — multiple board items reference this label with no backing note in pal-e-docs
## Scope Review: APPROVED Review note: `review-808-2026-04-04` (updated) Re-review: all 3 prior NEEDS_REFINEMENT issues resolved. Backend approach committed (client-side filter), AC4 event filtering logic specified with code-level detail, repo naming clarified and verified via git remote. **Verified:** - File target `src/routes/(app)/coach/+page.svelte` confirmed (lines 149-157, "Coming soon" placeholder) - `/coaches/me` returns `teams[].id` + `teams[].division` — both needed for filtering - `/public/schedule` returns `practices[].team_id` + `events[].team_id` + `events[].division` — matches filter strategy - story:WS-S27 confirmed in project-westside-basketball user-stories - 1 file, 1 repo, 5 ACs — no decomposition needed **Remaining [SCOPE] (non-blocking):** - Create architecture note `arch-landing-site` — multiple board items reference this label with no backing note in pal-e-docs
Author
Contributor

Validation: PASS

Tiers executed: Tier 3 (Production)
Validation note: validation-213-2026-04-04

8 checks: 8 PASS, 0 FAIL

# Check Result
1 Practice schedule with day, 12h time, venue PASS
2 Multi-team schedules grouped by team PASS
3 "Coming soon" placeholder removed PASS
4 Events filtered by team_id + division PASS
5 No backend changes (frontend only) PASS
6 Woodpecker pipeline #215 green PASS
7 Pod running, 0 restarts PASS
8 Image tag includes PR #217 PASS

Route-level smoke: 9/9 routes return HTTP 200 (/, /about, /staff, /schedule, /sponsors, /tryouts, /teams, /coach, /admin).

No regressions. No discovered issues.

## Validation: PASS Tiers executed: **Tier 3 (Production)** Validation note: `validation-213-2026-04-04` **8 checks: 8 PASS, 0 FAIL** | # | Check | Result | |---|-------|--------| | 1 | Practice schedule with day, 12h time, venue | PASS | | 2 | Multi-team schedules grouped by team | PASS | | 3 | "Coming soon" placeholder removed | PASS | | 4 | Events filtered by team_id + division | PASS | | 5 | No backend changes (frontend only) | PASS | | 6 | Woodpecker pipeline #215 green | PASS | | 7 | Pod running, 0 restarts | PASS | | 8 | Image tag includes PR #217 | PASS | Route-level smoke: 9/9 routes return HTTP 200 (/, /about, /staff, /schedule, /sponsors, /tryouts, /teams, /coach, /admin). 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#213
No description provided.