Skip to content

Add goals overview card to dashboard#336

Draft
jhodapp wants to merge 7 commits intomainfrom
feat/dashboard-goals-overview
Draft

Add goals overview card to dashboard#336
jhodapp wants to merge 7 commits intomainfrom
feat/dashboard-goals-overview

Conversation

@jhodapp
Copy link
Copy Markdown
Member

@jhodapp jhodapp commented Mar 16, 2026

Description

Adds a collapsible Goals Overview Card to the dashboard, positioned between Today's Sessions and the Coaching Sessions list. Shows the coachee's active goals with a circular SVG progress ring, per-goal action progress rows, and an aggregate health signal.

Based on the prototype at src/app/prototype/dashboard-goals/page.tsx, implemented to project coding standards.

Changes

  • New ProgressRing component — circular SVG progress indicator with configurable size
  • New GoalRow component — displays goal title, action completion counts, inline progress bar, and session count
  • New GoalsOverviewCard component — collapsible card fetching data via useGoalProgressList, filtering to InProgress goals, computing aggregate stats and worst-case health signal
  • Extended GoalWithProgress type and parseGoalProgressResponse validator in goal-progress.ts
  • Extended goal-progress API with listByRelationship() and useGoalProgressList() SWR hook for GET /organizations/{org_id}/coaching_relationships/{rel_id}/goal_progress
  • Integrated card into dashboard-container.tsx with render guard pattern

Screenshots / Videos Showing UI Changes (if applicable)

Screenshots needed once the backend aggregate endpoint is implemented:

  • Dashboard with goals overview card expanded (showing goal rows)
  • Dashboard with card collapsed
  • Empty state (no active goals)
  • Loading skeleton state

Testing Strategy

  • 52 unit tests across 4 test files, all passing:
    • progress-ring.test.tsx — SVG rendering, percentage display, stroke-dashoffset math, custom size
    • goal-row.test.tsx — title, action counts, session count pluralization, percentage computation
    • goals-overview-card.test.tsx — loading/error states, InProgress filtering, aggregate percentage, worst health signal, collapsible toggle, disabled "View all goals" button, hook parameter passing
    • goal-progress.test.ts — extended with aggregate response parsing, validation, edge cases
  • ESLint clean on all new/modified files
  • Run: npx vitest run __tests__/components/ui/dashboard/progress-ring.test.tsx __tests__/components/ui/dashboard/goal-row.test.tsx __tests__/components/ui/dashboard/goals-overview-card.test.tsx __tests__/types/goal-progress.test.ts

Concerns

  • Backend dependency: The card renders a loading skeleton until GET /organizations/{org_id}/coaching_relationships/{rel_id}/goal_progress is implemented (see RelationshipGoalProgress contract v2 on the coordination board). SWR conditional fetching means it won't error — it just won't show data yet.
  • "View all goals" button is disabled/no-op until the Goals Page (PR 4a) is implemented.
  • Goal row clicks are non-functional (hover highlight only) — will be wired up when the Goals Page exists.

@jhodapp jhodapp self-assigned this Mar 16, 2026
@jhodapp jhodapp changed the title feat: add goals overview card to dashboard Add goals overview card to dashboard Mar 16, 2026
@jhodapp jhodapp added the feature work Specifically implementing a new feature label Mar 16, 2026
@jhodapp jhodapp moved this to 🏗 In progress in Refactor Coaching Platform Mar 16, 2026
@jhodapp jhodapp added this to the 1.0.0-beta3 milestone Mar 16, 2026
Base automatically changed from feat/goals-sse-health-integration to main March 23, 2026 20:57
jhodapp added 7 commits March 23, 2026 16:01
Add coaching_session_goal_created and coaching_session_goal_deleted SSE
event types and cache invalidation handlers for real-time session-goal
link updates.

Introduce dedicated goal-health module (mirroring backend pattern) with
GoalHealth enum, GoalHealthMetrics interface using ts-results Option<T>
for nullable date fields, parseGoalHealthMetrics boundary parser, and
useGoalHealth SWR hook accepting Option<Id>.

New dependency: ts-results for Rust-inspired Option/Result types.
Replace the ts-results dependency with a lightweight project-local
Option<T> type and add neverthrow for Result<T,E> at async boundaries.
Fix unsafe unwrap() in useGoalHealth, replace require() with ESM import,
and use real Option values in test mocks instead of as-any casts.
Update coding standards with clear guidance on when to use Option vs
Result vs discriminated unions.
…ealthMetrics

The raw type guard is an internal implementation detail. Rewrite tests
to exercise validation logic through the public parseGoalHealthMetrics
function instead.
Align frontend naming with backend rename of GET /goals/:id/health
to GET /goals/:id/progress. Renames GoalHealth → GoalProgress,
GoalHealthMetrics → GoalProgressMetrics, health field → progress,
and all related files, functions, hooks, and tests.
Collapsible card showing active goals with circular progress ring,
per-goal action progress rows, and aggregate health signal. Integrates
between TodaysSessions and CoachingSessionList on the dashboard.

Adds aggregate goal progress API hook (useGoalProgressList) consuming
GET /organizations/{org_id}/coaching_relationships/{rel_id}/goal_progress
with GoalWithProgress types and response parsing.
Update GoalProgressMetrics raw type and validator to match the backend's
actual field names (linked_coaching_session_count, last_coaching_session_date)
and PascalCase enum values. Remove the PROGRESS_MAP normalization layer
now that backend has fixed enum serialization to PascalCase.
Change from w-8 to w-10 so "100%" doesn't wrap to two lines.
@jhodapp jhodapp force-pushed the feat/dashboard-goals-overview branch from c404ca7 to 4852f68 Compare March 23, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature work Specifically implementing a new feature

Projects

Status: 🏗 In progress

Development

Successfully merging this pull request may close these issues.

1 participant