Draft
Conversation
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.
c404ca7 to
4852f68
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
ProgressRingcomponent — circular SVG progress indicator with configurable sizeGoalRowcomponent — displays goal title, action completion counts, inline progress bar, and session countGoalsOverviewCardcomponent — collapsible card fetching data viauseGoalProgressList, filtering to InProgress goals, computing aggregate stats and worst-case health signalGoalWithProgresstype andparseGoalProgressResponsevalidator ingoal-progress.tsgoal-progressAPI withlistByRelationship()anduseGoalProgressList()SWR hook forGET /organizations/{org_id}/coaching_relationships/{rel_id}/goal_progressdashboard-container.tsxwith render guard patternScreenshots / Videos Showing UI Changes (if applicable)
Screenshots needed once the backend aggregate endpoint is implemented:
Testing Strategy
progress-ring.test.tsx— SVG rendering, percentage display, stroke-dashoffset math, custom sizegoal-row.test.tsx— title, action counts, session count pluralization, percentage computationgoals-overview-card.test.tsx— loading/error states, InProgress filtering, aggregate percentage, worst health signal, collapsible toggle, disabled "View all goals" button, hook parameter passinggoal-progress.test.ts— extended with aggregate response parsing, validation, edge casesnpx 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.tsConcerns
GET /organizations/{org_id}/coaching_relationships/{rel_id}/goal_progressis implemented (see RelationshipGoalProgress contract v2 on the coordination board). SWR conditional fetching means it won't error — it just won't show data yet.