📄 SPEC.md 12,176 bytes Wednesday 01:44 📋 Raw

SPEC: RTSport Parent Dashboard — Full Retool

Agent Collaboration Protocol v1.3.0
Build Date: 2026-05-06
Refs: coach-retool-spec.md, product-brief.md, phase1-mvp-cut.md

Overview

The Parent Dashboard exists as a skeleton with three bottom-nav tabs (Home, Timeline, Message) — same pattern as the Coach Dashboard. Home is partially wired with loading states. Timeline and Message are empty placeholders. This build fleshes out all three tabs with production-quality, demo-ready interfaces.

Contract

Field Value
API Base Path https://hoffdesk.com/api/v1
Auth Scheme Bearer JWT (localStorage rtsport_token)
Content Type application/json
Error Format { "error": "...", "detail": { ... } }
Existing JS Uses apiRequest(endpoint, options) wrapper in dashboard.html
School ID schl_001 (test data)
Parent Context currentAthleteId variable, child selector for multi-kid families
Design Accent --parent-accent: #8b5cf6 (violet — care/trust)
Existing File /home/hoffmann_admin/.openclaw/shared/build-20260501/frontend/templates/parent/dashboard.html (549 lines)

Shared Constants

Status Enums

Constant Values Used By
AthleteStatus out, restricted, cleared Backend + frontend status cards/badges
CasePhase initial_assessment, active_rehab, return_to_play, full_clearance Backend + frontend progress bars
InjurySeverity mild, moderate, severe Backend + frontend severity badges
TimelineEventType assessment, restriction, milestone, clearance, message Backend + frontend timeline filtering
MessageStatus sent, delivered, read Backend + frontend message bubbles

Feature Flags

Flag Default Description
ENABLE_PARENT_MESSAGING true Controls Message tab visibility
ENABLE_FERPA_FILTER true Strips clinical_notes from parent timeline
ENABLE_MULTI_CHILD true Shows child selector for families with >1 athlete

Endpoints

Home Tab

GET /api/v1/dashboard/parent?school_id=X&athlete_id=Y

Response:

{
  "athlete": {
    "id": "ath_001",
    "first_name": "Jake",
    "last_name": "Larson",
    "sport": "Football",
    "team": "Varsity",
    "grade": 11,
    "jersey_number": 12,
    "current_status": "out"
  },
  "case": {
    "id": "case_001",
    "status": "active",
    "body_part": "Ankle",
    "side": "Right",
    "injury_type": "Sprain",
    "severity": "moderate",
    "opened_date": "2026-04-15",
    "phase": "active_rehab",
    "phase_number": 2,
    "total_phases": 4,
    "estimated_return": "2026-05-20",
    "next_appointment": "2026-05-08T15:30:00Z",
    "restrictions": [
      "No running",
      "Non-contact only",
      "Must wear ankle brace"
    ],
    "milestones": [
      {"label": "Initial Assessment", "status": "done", "completed_date": "2026-04-15"},
      {"label": "Active Rehab", "status": "current", "target_date": "2026-05-10"},
      {"label": "Return to Play", "status": "pending", "target_date": "2026-05-20"},
      {"label": "Full Clearance", "status": "pending", "target_date": "2026-05-25"}
    ],
    "care_team": [
      {"name": "Lisa Johnson, LAT", "role": "Athletic Trainer", "initials": "LJ", "email": "ljohnson@preble.k12.wi.us"},
      {"name": "Coach Andrews", "role": "Head Coach — Football", "initials": "CA", "email": "andrews@preble.k12.wi.us"}
    ]
  },
  "activity_feed": [
    {"type": "milestone", "title": "Advanced to Active Rehab", "date": "2026-05-01", "note": "Range of motion restored. Starting strengthening exercises."},
    {"type": "message", "title": "Message from Lisa Johnson, LAT", "date": "2026-04-28", "note": "Jake is progressing well. We'll re-evaluate next week."},
    {"type": "restriction", "title": "Restrictions Updated", "date": "2026-04-22", "note": "Non-contact practice only. Must wear ankle brace."},
    {"type": "assessment", "title": "Initial Assessment", "date": "2026-04-15", "note": "Right ankle sprain — Grade 2. Moderate swelling."}
  ]
}

Timeline Tab

GET /api/v1/dashboard/parent/timeline?school_id=X&athlete_id=Y

Response:

{
  "athlete_name": "Jake Larson",
  "case": {
    "id": "case_001",
    "phase": "active_rehab",
    "phase_number": 2,
    "total_phases": 4
  },
  "events": [
    {"type": "milestone", "title": "Advanced to Active Rehab", "date": "2026-05-01", "description": "Range of motion restored. Starting strengthening exercises — 3x/week.", "icon": "🏃"},
    {"type": "message", "title": "AT Update", "date": "2026-04-28", "description": "Lisa Johnson shared: \"Jake is progressing well. We'll re-evaluate next week.\"", "icon": "💬"},
    {"type": "restriction", "title": "Restrictions Updated", "date": "2026-04-22", "description": "Non-contact practice only. Must wear ankle brace during all activities.", "icon": "⚠️"},
    {"type": "assessment", "title": "Initial Assessment", "date": "2026-04-15", "description": "Right ankle sprain — Grade 2. Moderate swelling. Immobilized, crutches for 3 days.", "icon": "🏥"},
    {"type": "clearance", "title": "Case Opened", "date": "2026-04-15", "description": "Injury reported during football practice. AT notified immediately.", "icon": "📋"}
  ]
}

Messages Tab

GET /api/v1/messages/parent?athlete_id=Y

Response:

{
  "athlete_name": "Jake Larson",
  "conversations": [
    {
      "contact_name": "Lisa Johnson, LAT",
      "contact_role": "Athletic Trainer",
      "contact_initials": "LJ",
      "last_message": "Jake is progressing well. We'll re-evaluate next week.",
      "last_message_time": "2026-04-28T15:30:00Z",
      "unread_count": 1
    }
  ]
}

GET /api/v1/messages/parent/{contact_id}?before=X

Response:

{
  "contact_name": "Lisa Johnson, LAT",
  "messages": [
    {"id": "msg_001", "sender": "at", "text": "Hi, Jake's initial assessment is complete. Grade 2 right ankle sprain.", "timestamp": "2026-04-15T14:00:00Z", "status": "read"},
    {"id": "msg_002", "sender": "parent", "text": "Thank you for letting me know. What's the recovery timeline?", "timestamp": "2026-04-15T14:30:00Z", "status": "read"},
    {"id": "msg_003", "sender": "at", "text": "Jake is progressing well. We'll re-evaluate next week.", "timestamp": "2026-04-28T15:30:00Z", "status": "delivered"}
  ]
}

POST /api/v1/messages/parent/{contact_id}

Request:

{
  "text": "Thanks for the update! Is there anything we should do at home?"
}

Response: 201 Created with message object

Child Selector

GET /api/v1/dashboard/parent/children?school_id=X

Response:

{
  "children": [
    {"id": "ath_001", "first_name": "Jake", "last_name": "Larson", "sport": "Football", "team": "Varsity", "current_status": "out", "has_active_case": true},
    {"id": "ath_005", "first_name": "Emma", "last_name": "Larson", "sport": "Soccer", "team": "JV", "current_status": "cleared", "has_active_case": false}
  ]
}

UI Components

Home Tab

Component Purpose Data Source States
ChildSelector Horizontal scrollable cards, one per child athlete GET /children Loading, 0 children (empty), 1 child (hidden), 2+ (scrollable)
StatusHero Large status card with athlete avatar, status, phase progress GET /parent Loading, healthy (no case), active case
PhaseTracker Progress bar showing recovery phase (e.g. "Phase 2 of 4") GET /parent Show only if active case
RestrictionsCard List of current restrictions with severity GET /parent Show only if restrictions exist
NextAppointment Highlighted card with next AT appointment GET /parent Show if appointment exists
CareTeam Contact cards for AT and coach GET /parent Always shown
ActivityFeed Recent events filtered for parent view GET /parent Loading, empty, populated

Timeline Tab

Component Purpose Data Source States
PhaseHeader Current phase indicator at top GET /timeline Active case, no case (healthy state)
TimelineEvents Vertical timeline with colored dots by event type GET /timeline Loading, empty, populated
EventCard Each event: icon, title, date, description Embedded All event types
FERPAFilterNote Small text: "Clinical notes are not shown in this view" Static Always shown (compliance)

Messages Tab

Component Purpose Data Source States
ConversationList List of care team members to message GET /messages/parent Loading, empty, populated
ChatView Message thread with bubbles GET /messages/parent/{id}, POST Loading, empty, populated
MessageBubble Sent (right, violet) vs received (left, muted) Embedded Timestamps, read receipts
Composer Text input + send button Embedded Empty validation, sending state

States to Handle

Every component handles:
- Loading: Skeleton/spinner while fetching
- Empty: Friendly message with icon ("No active recovery plan" / "No messages yet")
- Error: Actionable message with retry button ("Couldn't load. Tap to retry.")
- Populated: Real data display

Design Constraints

  • Mobile-first: 375-414px primary, scales to tablet
  • Dark theme: Match existing --parent-accent: #8b5cf6, --bg-base: #0f0f17
  • 44px minimum tap targets on all interactive elements
  • Pure CSS — no chart libraries, no heavy animations
  • touch-action: manipulation on interactive elements
  • FERPA compliance: Parent sees only their athlete(s). No clinical notes in timeline.
  • Match existing CSS variables in rtsport.css — don't redefine them

Success Criteria

  1. Home tab fully functional — Status hero, phase tracker, restrictions, care team, activity feed all render from API data
  2. Child selector works — Switching children reloads all dashboard data for that athlete
  3. Timeline tab shows complete recovery journey — Chronological events with icons, dates, descriptions
  4. Messages tab supports full chat flow — Conversation list → open thread → send message → see reply
  5. All states handled — Loading, empty, error, populated for every component
  6. Mobile-first, matches design system — Same violet accent, dark theme, typography, spacing
  7. FERPA-aware — No clinical notes exposed, parent-only visibility badge present

File Structure

Backend (/home/hoffmann_admin/.openclaw/shared/build-20260506-parent/backend/)

rtsport_parent_api.py    ← New endpoints for parent dashboard
seed_parent_data.py       ← Test parent data (at least 2 athletes, 1 with active case)

Mount into live codebase at /home/hoffmann_admin/.openclaw/workspace-socrates/hoffdesk-api/

Frontend (/home/hoffmann_admin/.openclaw/shared/build-20260506-parent/frontend/)

parent-dashboard.html     Full modified dashboard (read existing, replace placeholder sections)
parent-tabs.css            New CSS for parent-specific components
parent-tabs.js             JS for child switching, tab navigation, message sending

Integration Notes

  • The existing dashboard already has loadDashboard(), loadChildren(), switchChild(), renderStatusCard(), etc. — these functions should be enhanced, not thrown away
  • Backend mock data: at least 2 children (1 with active case, 1 healthy), 2 care team members, 4 milestone phases, 5 timeline events
  • Messages can be in-memory (shared dict between coach and parent message endpoints)
  • Child selector: horizontal scroll for 2-4 kids, stacked for 5+. Hide if only 1 child.
  • Timeline tab: use the data.loaded flag pattern already present (avoid re-fetching)

Out of Scope

  • Real-time WebSocket/SSE
  • Push notifications / email alerts
  • File/image attachments in messages
  • Telehealth scheduling
  • Consent forms
  • Multi-school parent accounts