Skip to content

Patient Workout Management (Therapist Perspective)

Overview

The Okta-Health system provides physical therapists with comprehensive tools to create, edit, and manage patient workout plans. This document covers all therapist-side workout management operations from the doctor dashboard.

Key Concepts

Concept Description
Workout A single exercise session scheduled for a specific date
Exercise An individual movement within a workout (reps-based or time-based)
Plan A collection of workouts spanning multiple days (up to 10 days)
Template A reusable workout configuration that can be applied to any patient
Exercise Block Workout structure category: WARM_UP, MAIN_SESSION, SUPPLEMENTAL_WORK, COOL_DOWN

Creating Patient Workouts

Initial Plan Creation (New Patient)

For new patients, therapists create an initial multi-day plan using the Initial Plan Creation Modal.

Component: OktaPT-FE/components/plan-creation/InitialPlanCreationModal.tsx State Hook: OktaPT-FE/lib/hooks/useInitialPlanState.ts AI Generation Hook: OktaPT-FE/lib/hooks/useAIInitialPlanGeneration.ts

API Endpoint Method Auth Purpose
/v2/doctor/create-initial-plan POST Required Create initial patient plan

Features: - Days 1-10 scheduling with day picker (PlanDaySelector.tsx) - Copy day functionality (duplicate exercises to another day) - Clear day functionality (remove all exercises from a day) - AI-generated plan support with manual customization - Exercise block organization (warm-up, main session, etc.)

Request Body:

{
  "patientId": 123,
  "startDate": "2024-01-15",
  "endDate": "2024-01-24",
  "workouts": [
    {
      "dateScheduled": "2024-01-15",
      "exercises": [
        {
          "exerciseId": 1,
          "exerciseType": "REPS_BASED",
          "sets": 3,
          "reps": 10,
          "exerciseBlock": "MAIN_SESSION"
        }
      ]
    }
  ]
}

Single Workout Creation

For ad-hoc workouts outside of the initial plan flow.

Component: OktaPT-FE/components/WorkoutCreationModal.tsx

API Endpoint Method Auth Purpose
/create-workout POST Required Create single workout

Backend Location: OktaPT-API/src/routes/legacy.ts

Request Body:

{
  "patientId": 123,
  "dateScheduled": "2024-01-20",
  "exercises": [
    {
      "exerciseId": 1,
      "exerciseType": "REPS_BASED",
      "sets": 3,
      "reps": 12,
      "weight": 10,
      "exerciseBlock": "MAIN_SESSION",
      "doctorNotesPreExercise": "Focus on form"
    }
  ]
}

Editing Patient Workouts

Bulk Plan Editing (Edit Plan Modal)

Edit upcoming workouts across a 10-day window.

Component: OktaPT-FE/components/plan-creation/EditPlanModal.tsx State Hook: OktaPT-FE/lib/hooks/useEditPlanState.ts

API Endpoint Method Auth Purpose
/v2/doctor/edit-plan PUT Required Bulk edit patient plan

Backend Location: OktaPT-API/src/routes/doctor/controller.ts:1185 (editPlan function)

Key Constraint: Workouts started within the last hour are protected and cannot be modified. This prevents disrupting patients who are actively exercising.

Cross-Therapist Access: Any therapist within the same clinic (tenant) can edit any patient's plan, not just the therapist assigned to that patient. This allows clinics to cover for each other when a therapist is unavailable.

How It Works: 1. Fetches existing workouts for the date range 2. Loads them into the day selector for editing 3. On save, deletes non-protected incomplete workouts in the range 4. Creates new workouts from the updated configuration

AI-Assisted Plan Editing

Therapists can modify patient workout plans using natural language instructions instead of manually editing each exercise.

Component: OktaPT-FE/components/plan-creation/ai-edit/AIEditPlanPanel.tsx State Hook: OktaPT-FE/lib/hooks/useAIPlanEdit.ts Streaming Hook: OktaPT-FE/lib/hooks/useAIPlanEditStream.ts

API Endpoint Method Auth Purpose
/v2/ai/therapist-plan-edit POST Required Generate AI-modified workout plan

How to Access: 1. Open the Edit Plan Modal for a patient 2. Click the "AI Assistant" button in the modal header 3. The AI chat panel slides in from the right

Quick Actions: The AI panel provides quick action buttons for common modifications: - Make easier - Reduce intensity, sets, reps, or weight - Make harder - Increase difficulty parameters - Remove equipment - Filter out exercises requiring specific equipment - Add warm-up - Insert warm-up exercises at the start - Add cool-down - Append stretching/cool-down exercises

File Attachments in Chat: Therapists can attach files mid-conversation to provide additional context for the AI (e.g., a new MRI scan, updated referral notes). Files can be attached via the paperclip button or by dragging and dropping onto the chat panel. Attachment metadata (filename, type) appears as chips in the sent message bubble. Per-message attachments are sent separately from any initial-plan attachments.

Custom Instructions: Therapists can type natural language instructions such as: - "Remove all dumbbell exercises and replace with bodyweight alternatives" - "Add 5 minutes of stretching to each day" - "Make Monday and Wednesday harder, keep Friday light" - "Focus on lower body strengthening for knee rehab"

Review Workflow:

  1. Streaming Preview: As the AI generates modifications, exercises appear progressively with skeleton loading states
  2. Comparison View: Once complete, a side-by-side comparison shows:
  3. Original exercises on the left
  4. Modified exercises on the right
  5. NEW badge for added exercises
  6. CHANGED badge for modified exercises
  7. Exercise thumbnails for visual reference
  8. Accept/Reject: Therapist can accept all changes, reject all, or selectively approve individual modifications

Patient Context: The AI automatically extracts and saves patient attributes mentioned in instructions (e.g., "patient has knee pain" → saves kneeIssues: true). These attributes persist and inform future AI suggestions.

Key Components:

Component Purpose
AIEditPlanPanel.tsx Main chat interface with message history
AIQuickActions.tsx Quick action button grid
AIPlanComparisonView.tsx Before/after comparison display
AIExerciseCard.tsx Individual exercise card with change indicators
AISkeletonCard.tsx Loading placeholder during streaming

Protected Workout Logic:

const ONE_HOUR_AGO = new Date(Date.now() - 60 * 60 * 1000);

// Only preserve if started within last hour
const startedWorkouts = await tx.workout.findMany({
  where: {
    patientId,
    isWorkoutCompleted: false,
    timeWorkoutStart: {
      not: null,
      gte: ONE_HOUR_AGO,
    },
    dateWorkoutCurrentlyScheduledFor: {
      gte: startDateObj,
      lte: endDateObj,
    },
  },
});

Single Workout Editing

Edit individual workout details from the workout details view.

Component: OktaPT-FE/components/doctor/dashboard/WorkoutDetailsModalV2.tsx

API Endpoint Method Auth Purpose
/workout/{workoutId}/exercises POST Required Update workout exercises

Backend Location: OktaPT-API/src/routes/legacy.ts

Capabilities: - Add/remove/reorder exercises (drag and drop to reorder; exercises automatically reposition when their block type is changed) - Change scheduled date - Modify exercise parameters (sets, reps, duration, weight) - Add pre-exercise doctor notes - Set exercise blocks

Request Body:

{
  "dateScheduled": "2024-01-20",
  "formattedExercises": [
    {
      "exerciseInWorkoutId": 456,
      "exerciseId": 1,
      "exerciseType": "REPS_BASED",
      "sets": 3,
      "reps": 12,
      "exerciseBlock": "MAIN_SESSION"
    }
  ]
}

Adding Doctor Notes

Workout-Level Notes

Add notes that apply to the entire workout session.

Component: OktaPT-FE/components/doctor/dashboard/WorkoutNote.tsx

API Endpoint Method Auth Purpose
/workout/{workoutId}/note PATCH Required Add/update workout note

Backend Location: OktaPT-API/src/routes/legacy.ts

Request Body:

{
  "doctorNote": "Take it easy today, focus on stretching"
}

Constraints: - Maximum 1000 characters

Exercise-Level Post-Notes

Add notes after reviewing patient's exercise performance or video.

API Endpoint Method Auth Purpose
/v2/exercises/exercises-in-workout/{id}/doctor-post-notes PATCH Required Add post-exercise note
/v2/exercises/workouts/{workoutId}/exercises/doctor-post-notes PATCH Required Bulk add post-exercise notes

Backend Location: OktaPT-API/src/routes/exercises/doctorFeedback.ts

Single Exercise Request:

{
  "doctorNotesPostExercise": "Great form! Keep it up"
}

Bulk Request:

{
  "exercises": [
    {
      "exerciseInWorkoutId": 123,
      "doctorNotesPostExercise": "Improve hip mobility"
    }
  ]
}

Deleting/Clearing Workouts

Clear Day (Within Plan Editor)

UI Components: - OktaPT-FE/components/plan-creation/PlanDaySelector.tsx - Day picker with clear button - OktaPT-FE/components/plan-creation/DayButton.tsx - Individual day with trash icon

How It Works: 1. Therapist clicks trash icon on a day card 2. window.confirm() dialog asks for confirmation 3. Workout is removed from local state 4. On plan save, the backend handles deletion

Backend Deletion on Save

When saving an edited plan, the backend:

  1. Identifies workouts started within the last hour (protected)
  2. Deletes ExerciseInWorkout records for non-protected workouts
  3. Deletes Workout records for non-protected workouts
  4. Creates new workouts from the submitted configuration

Deletion Logic (in transaction):

// Delete exercises first (foreign key constraint)
await tx.exerciseInWorkout.deleteMany({
  where: {
    workout: {
      patientId,
      isWorkoutCompleted: false,
      id: { notIn: preservedWorkoutIds },
      dateWorkoutCurrentlyScheduledFor: {
        gte: startDateObj,
        lte: endDateObj,
      },
    },
  },
});

// Then delete workouts
await tx.workout.deleteMany({
  where: {
    patientId,
    isWorkoutCompleted: false,
    id: { notIn: preservedWorkoutIds },
    dateWorkoutCurrentlyScheduledFor: {
      gte: startDateObj,
      lte: endDateObj,
    },
  },
});

Workout Templates

Reusable workout configurations that can be applied to any patient.

Backend Location: OktaPT-API/src/routes/workouts/templates.ts

API Endpoint Method Auth Purpose
/v2/workouts/templates GET Required List all templates
/v2/workouts/templates POST Required Create new template
/v2/workouts/templates/{id} PUT Required Update template
/v2/workouts/templates/{id} DELETE Required Soft delete template (sets isActive: false)
/v2/workouts/templates/{id}/create-workout POST Required Create workout from template

Template Visibility

  • Private templates: Only visible to the creator
  • Public templates: Visible to all therapists in the tenant

Creating a Template

{
  "name": "Lower Body Strength",
  "description": "Focus on quad and glute activation",
  "category": "strength",
  "difficultyLevel": "INTERMEDIATE",
  "estimatedDuration": 45,
  "suitableConditions": ["knee_rehab", "hip_mobility"],
  "isPublic": false,
  "exercises": [
    {
      "exerciseId": 1,
      "exerciseType": "REPS_BASED",
      "sets": 3,
      "reps": 10,
      "exerciseBlock": "MAIN_SESSION"
    }
  ]
}

Creating Workout from Template

{
  "patientId": 123,
  "dateScheduled": "2024-01-20"
}

Key Constraints & Rules

Workout Locking

Condition Can Edit? Rationale
Not started Yes Patient hasn't begun
Started > 1 hour ago Yes Likely abandoned
Started within 1 hour No Patient may be exercising
Completed No Historical record

Plan Edit Window

  • Only the upcoming 10 days can be edited via the plan editor
  • Past workouts cannot be modified through the plan editor
  • Completed workouts are preserved regardless of date

Exercise Configuration

Required fields for each exercise: - exerciseId - Reference to exercise definition - exerciseType - Either REPS_BASED or TIME_BASED - sets - Minimum 1 (auto-corrected from 0)

Optional fields: - reps - For REPS_BASED exercises - duration - For TIME_BASED exercises (in seconds) - weight - In kilograms - exerciseBlock - Workout structure category - prescribedPainToleranceLevel - 1-10 scale - prescribedPhysicalExertionLevel - 1-10 scale - doctorNotesPreExercise - Instructions for patient

Legacy Code Notes

WorkoutDetailsModal.tsx (Legacy)

Path: OktaPT-FE/components/doctor/dashboard/WorkoutDetailsModal.tsx Status: Superseded by WorkoutDetailsModalV2.tsx

Differences from V2: - Does not support exerciseBlock field in exercise mapping - Uses PatientSummary type instead of PatientSummaryV2 - Action buttons may be in different positions

Recommendation: Use WorkoutDetailsModalV2.tsx for new development.

API Reference Table

Endpoint Method Auth Purpose
/v2/doctor/create-initial-plan POST Required Create initial patient plan
/v2/doctor/edit-plan PUT Required Bulk edit patient plan
/v2/ai/therapist-plan-edit POST Required Generate AI-modified workout plan
/create-workout POST Required Create single workout
/workout/{id}/exercises POST Required Update workout exercises
/workout/{id}/note PATCH Required Add/update workout note
/v2/exercises/exercises-in-workout/{id}/doctor-post-notes PATCH Required Add post-exercise note
/v2/exercises/workouts/{id}/exercises/doctor-post-notes PATCH Required Bulk add post-exercise notes
/v2/workouts/templates GET Required List templates
/v2/workouts/templates POST Required Create template
/v2/workouts/templates/{id} PUT Required Update template
/v2/workouts/templates/{id} DELETE Required Soft delete template
/v2/workouts/templates/{id}/create-workout POST Required Create workout from template

Database Models

Workout

model Workout {
  id                               Int                 @id @default(autoincrement())
  name                             String?
  category                         String?
  doctor                           User                @relation("DoctorWorkouts", ...)
  doctorId                         Int
  patient                          User?               @relation("PatientWorkouts", ...)
  patientId                        Int?
  isTemplate                       Boolean
  dateWorkoutScheduled             DateTime
  dateWorkoutCurrentlyScheduledFor DateTime            @default(now())
  timeWorkoutStart                 DateTime?
  timeWorkoutEnd                   DateTime?
  isWorkoutCompleted               Boolean
  doctorNote                       String?
  description                      String?
  exercises                        ExerciseInWorkout[]
  tenantId                         Int                 @default(1)
}

ExerciseInWorkout

model ExerciseInWorkout {
  id                              Int           @id @default(autoincrement())
  workout                         Workout       @relation(...)
  workoutId                       Int
  exercise                        Exercise      @relation(...)
  exerciseId                      Int
  exerciseType                    ExerciseType? @default(REPS_BASED)
  plannedSets                     Int
  actualSets                      Int?
  plannedReps                     Int?
  actualReps                      Int?
  plannedWeight                   Float?
  actualWeight                    Float?
  plannedDuration                 Int?
  actualDuration                  Int?
  doctorNotesPreExercise          String?
  doctorNotesPreExerciseAt        DateTime?
  doctorNotesPostExercise         String?
  doctorNotesPostExerciseAt       DateTime?
  prescribedPainToleranceLevel    Int?
  prescribedPhysicalExertionLevel Int?
  isExerciseCompleted             Boolean
  orderInWorkout                  Int
  exerciseBlock                   ExerciseBlock? @default(MAIN_SESSION)
  tenantId                        Int            @default(1)
}

Testing Checklist

Initial Plan Creation

  • [ ] Create plan for new patient with AI generation
  • [ ] Manually add exercises to multiple days
  • [ ] Copy day exercises to another day
  • [ ] Clear a day and verify exercises removed
  • [ ] Save plan and verify workouts created in database

Single Workout Creation

  • [ ] Create workout from doctor dashboard
  • [ ] Select date and add exercises
  • [ ] Verify patient notification sent

Plan Editing

  • [ ] Edit existing patient plan
  • [ ] Verify protected workouts (started within 1 hour) cannot be modified
  • [ ] Add exercises to empty days
  • [ ] Remove exercises from existing days
  • [ ] Save and verify changes persisted

Single Workout Editing

  • [ ] Edit workout exercises
  • [ ] Change scheduled date
  • [ ] Add pre-exercise notes
  • [ ] Verify incomplete workout can be edited
  • [ ] Verify completed workout cannot be edited

Doctor Notes

  • [ ] Add workout-level note
  • [ ] Add post-exercise note after reviewing performance
  • [ ] Verify note length validation (max 1000 chars)

Templates

  • [ ] Create private template
  • [ ] Create public template
  • [ ] Apply template to patient
  • [ ] Edit template exercises
  • [ ] Delete template (verify soft delete)