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: manipulationon 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
- Home tab fully functional — Status hero, phase tracker, restrictions, care team, activity feed all render from API data
- Child selector works — Switching children reloads all dashboard data for that athlete
- Timeline tab shows complete recovery journey — Chronological events with icons, dates, descriptions
- Messages tab supports full chat flow — Conversation list → open thread → send message → see reply
- All states handled — Loading, empty, error, populated for every component
- Mobile-first, matches design system — Same violet accent, dark theme, typography, spacing
- 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.loadedflag 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