Skip to content

Mobile Doctor HEP Management

Overview

The mobile app now includes a doctor-only Manage HEP flow for quickly editing a patient's home exercise sessions for the coming week while the doctor is still in the room with the patient.

This feature is designed for: - Fast manual plan edits on mobile - Bulk exercise insertion across multiple upcoming sessions - Per-session exercise customization - Lightweight AI-assisted modifications from the AI Assistant sheet - Patient-specific exercise media, including personalized exercise videos

The goal is to make plan adjustment on mobile feel native, fast, and safe, rather than forcing doctors into the heavier web editing workflow.


Gating

This feature is behind the tenant feature flag:

  • therapistMobileHepManagement

Where It Is Checked

  • Mobile UI: Okta-Mobile/components/doctor/DoctorDashboard.tsx
  • API read endpoint: OktaPT-API/src/routes/doctor/controller.ts
  • API save endpoint: OktaPT-API/src/routes/doctor/controller.ts
  • Shared access helper: OktaPT-API/src/helpers/verifyDoctorPatientAccess.ts

If the flag is disabled: - The Manage HEP button does not appear on the doctor dashboard - The doctor HEP session API returns 403

Tenant-Wide Access

HEP now uses the shared verifyDoctorPatientAccess() helper.

  • If allActivePatientsDashboard is true, doctors can manage any active accepted non-archived patient within the tenant.
  • Otherwise, the doctor must still have a direct active accepted connection to the patient.

This same rule now governs HEP reads, HEP saves, therapist AI edits, therapist AI rebalance, and patient-scoped exercise picker enrichment.


Entry Point

Doctor Dashboard

File: Okta-Mobile/components/doctor/DoctorDashboard.tsx

Each patient card in the in-clinic dashboard now supports: - Start Test as the primary action - Manage HEP as a secondary action when therapistMobileHepManagement is enabled - Record Exercise alongside Manage HEP when therapistPersonalizedExerciseVideo is also enabled

Files: - Okta-Mobile/app/(doctor)/_layout.tsx - Okta-Mobile/app/(doctor)/(hep)/_layout.tsx - Okta-Mobile/app/(doctor)/(hep)/manage.tsx

The HEP editor lives in the doctor route group:

/(doctor)/(hep)/manage

It receives: - patientId - patientName

through Expo Router params.


Screen Design

Main Screen

File: Okta-Mobile/app/(doctor)/(hep)/manage.tsx

The main screen is a single full-screen editor with: - Header: patient name + "Editing the next 7 days", with the save status - A Program / Sessions switch, remembered per device - Program: one card per exercise. Its top section has the picture at the left edge from top to bottom (120 points wide, 104 on phones narrower than 390 points, at least 72 tall); beside it the name, the week as a strip of small day dots (one per session, accent where the exercise is scheduled, a lock on a started session) and a dose chip ("2 × 6", "1 × 20s · 5 kg"). The strip always keeps every session on one row: sessions on the same day sit together and the days a little apart, and the dots are 20 points for a normal week and shrink for more sessions (three a day still fits a 320-point phone), dropping their letters below 16 points. Tapping the strip or the dose chip unfolds an editor across the card, one at a time. The strip unfolds the schedule presets as chips on one row that scrolls sideways and always starts at the common presets (Every session, Every other, Weekdays, Mon · Wed · Fri, Tue · Thu, Custom; only presets that hit an editable session are offered): one tap applies a preset to the whole row and folds the panel, so a schedule is two taps; tapping the preset the row already follows just folds it, and days in a started session always stay. Custom shows the big 44-point day chips, the whole week on one row (a window of more than ten sessions wraps into equal rows), each toggling one day, with Done to fold; an irregular schedule opens straight into them. The dose chip unfolds the full-size Sets × Reps steppers; tapping it again folds them, and a number typed into a stepper is saved even if the panel folds before the field loses focus. There is no schedule sheet any more. The therapist's instructions for the patient run across the card below the picture, up to three lines, and a started session adds a lock line. Tapping the card opens the dosage sheet (where the exercise can also be removed from the program) and a long press anywhere on it opens the row actions; VoiceOver reads the card as one button whose actions are the schedule, the dose, the video and the row actions - Sessions: the week as exercises grouped by day. A day is a slim heading on the background: the date, the session number and exercise count (an empty day shows only its number), and the session's focus on its own line, up to two lines; an Add text button for that day and, on a day with exercises, a more button whose sheet offers Reorder exercises (two or more exercises) and Copy to other sessions. Then one flat row per exercise. The row leads with the exercise's picture filling its left edge (96 by 72 points, a small play, expand or problem badge in its corner), then the name, the dose as every other row says it ("3 × 10 · 5 kg", "2 × 30s", "3 × 12 / 10 / 8"), small chips for a non-main block and a Guidelines set chip when a pain or effort target is set, and the note on one line; a trash at the right removes the exercise. A started session shows an In progress chip and read-only rows; an empty day is a dashed placeholder with Copy previous session when an earlier day has exercises. Days sit 24 points apart and rows 8, so more of the week is on screen at once - At the end of the list, Add to every session (Sessions) or Add exercise (Program), both adding to every editable session, then AI Assistant; the floating + does the same from anywhere

The screen uses modal/sheet-style subflows for: - Exercise picker - Dosage editor - Video preview - Delete scope confirmation - Save/rebalance confirmation

Changes save on their own. During a save the header's status reads Saving…, then Saved, or offers Retry.

Safe Areas

The HEP-specific add-exercise picker and dosage editor explicitly respect top safe areas on iPhone so header actions stay below the notch / Dynamic Island.

Files: - Okta-Mobile/components/doctor/hep/HepExercisePickerModal.tsx - Okta-Mobile/components/doctor/hep/HepDosageEditorModal.tsx


Session Window

Window Definition

The editor always works on the coming week — today through six days ahead — after missed sessions have been settled and the week has been filled from the plan's schedule.

Server-Side Construction

Endpoint: GET /v2/doctor/patients/:patientId/hep-management

Implementation: OktaPT-API/src/routes/doctor/controller.ts

The API: 1. Verifies doctor access to the patient 2. Settles missed sessions and fills the week with the sessions the plan would add anyway (extendPlan, see Plan Scheduling), so the doctor edits the real future 3. Loads incomplete workouts dated up to six days ahead, ordered by dateWorkoutCurrentlyScheduledFor (at most 21 sessions in the response; the cap of three a day is enforced on save) 4. Marks sessions as protected if they started within the last hour 5. Attaches personalized exercise videos when available 6. Adds a placeholder for every day of the week with no session, so the response has one slot per session plus one per empty day, today .. today + 6, in calendar order 7. Returns planSchedule (how the plan carries on) alongside sessions, and source per session (who scheduled it)

Response Shape

{
  "planSchedule": {
    "kind": "WEEKLY",
    "weekdays": [1, 3, 5],
    "intervalDays": null,
    "cycleDays": null,
    "autoContinue": true,
    "origin": "EXPLICIT",
    "planStartDate": "2026-03-02",
    "updatedAt": "2026-03-01T12:00:00.000Z",
    "updatedById": 7
  },
  "sessions": [
    {
      "slotIndex": 1,
      "dayNumber": 1,
      "date": "2026-03-02T00:00:00.000Z",
      "workoutId": 123,
      "isPlaceholder": false,
      "isProtected": false,
      "source": "CLINICIAN",
      "focus": "",
      "blockNotes": null,
      "exercises": [
        {
          "exerciseInWorkoutId": 456,
          "exerciseId": 12,
          "name": "Bridge",
          "exerciseType": "REPS_BASED",
          "exerciseBlock": "MAIN_SESSION",
          "sets": 3,
          "reps": 10,
          "duration": null,
          "weight": null,
          "holdSeconds": 5,
          "restSeconds": 60,
          "side": "LEFT",
          "tempo": null,
          "distanceMeters": null,
          "asNeeded": false,
          "everyHours": null,
          "thumbnailUrl": "...",
          "videoUrl": null,
          "photoUrl": null,
          "cloudflareStreamId": null,
          "kinescopeVideoId": "abc123",
          "prescribedPainTolerance": 5,
          "prescribedExertionTolerance": 7,
          "note": "Focus on controlled movement through full ROM",
          "personalizedVideo": {
            "id": 99,
            "cloudflareStreamId": "stream_123",
            "updatedAt": "2026-03-01T12:00:00.000Z"
          }
        }
      ]
    }
  ]
}

Protected Session Behavior

A session is treated as protected when: - timeWorkoutStart is set - isWorkoutCompleted is false - the workout started within the last hour

Protected sessions: - remain visible in the list - show an In progress chip with a lock (Sessions), or a locked day dot and a "Session N in progress — unchanged" line (Program) - cannot be edited - are preserved by the save API

This uses the same protection logic as bulk web plan editing.

Repeat from a past session

Outside Manage HEP, a therapist can put a past session back on this week: Repeat beside each row of the patient's sessions list (app/(doctor)/patient-sessions/[id].tsx, done sessions; a separate button, so VoiceOver reaches it) and in the header of the session screen (app/(doctor)/(session-viewer)/view.tsx, for a done or missed session). components/doctor/RepeatSessionSheet.tsx lists today and the six days after with what each holds ("Free", "4 exercises — will be replaced", or locked with "Started by the patient" or "Already over for the patient"), warns before replacing, and then says where the session went, with Open plan to Manage HEP where the clinic has therapistMobileHepManagement (otherwise Done); on iOS the plan opens once the sheet has closed. The same protection applies on the server. Behaviour and endpoints: Repeating a past session.


Plan Schedule

The screen has no schedule control. The server reads the plan's schedule off the days the clinician saves and continues on them (see Plan Scheduling); the header line just says "Editing the next 7 days". The GET response may still carry planSchedule; nothing on mobile reads it.

Manual Editing Flow

Bulk Add

Doctors can tap Add to every session at the end of the Sessions list, Add exercise at the end of the Program list, or the floating +.

This opens the exercise picker, then the dosage editor, then inserts the configured exercises into every editable session in the week.

Per-Session Add

Each day heading has its own Add button that uses the same picker and dosage editor, but inserts only into that session.

Edit Existing Exercise

Tapping the non-thumbnail portion of an exercise row opens the dosage editor for that exercise.

Since 2026-10-26 the dosage editor ends with More: the rest of the prescription (Hold, Rest between sets, Distance in the clinic's unit, Tempo, Every N hours, Side chips, As needed). The row reads them after the dose ("3 × 10 · hold 5 s · left side"); the save sends them with every exercise (holdSeconds, restSeconds, side, tempo, distanceMeters, asNeeded, everyHours) and the session's blockNotes, which an older API ignores.

Editable fields: - tracking type (REPS_BASED / TIME_BASED) - sets - reps or duration - weight (kg in the OKTA apps, lbs in the OTERA apps; the rows show it with its unit) - exercise block - prescribed pain tolerance - prescribed exertion tolerance - clinical note

Delete Existing Exercise

Trash removes an exercise from the current session.

If the same exerciseId appears in later editable sessions in the week, the doctor is prompted to choose: - This session only - This and future sessions

If there are no future matches, only the current-session removal prompt is shown.

Reordering

Reorder exercises in a day's more sheet, or the reorder button above the Program list, opens HepReorderModal: drag the handle. A session keeps exercises within their block; the Program order applies to every session. New exercises append to the end of the session.


Exercise Picker

Component: Okta-Mobile/components/doctor/hep/HepExercisePickerModal.tsx

The picker reuses the mobile exercise-library patterns: - search - tag filters - exercise cards - thumbnails

Shared components reused: - Okta-Mobile/components/exercises/ExerciseCard.tsx - Okta-Mobile/components/exercises/TagFilterSheet.tsx - Okta-Mobile/hooks/useExercises.ts

Picker Behavior

  • Card body press: select / deselect exercise
  • Thumbnail press: open video preview if the exercise has a playable video source
  • Scope controls:
  • Personalized pill is shown first when personalized videos are enabled for the tenant
  • Browse button opens a bottom sheet with All Exercises, My Private, and Favorites
  • the picker defaults to Personalized when the patient has personalized videos, otherwise All Exercises
  • Exercise cards with patient-specific media show a Personalized badge

Patient-Specific Media in Picker

The HEP screen owns a patient-scoped exercise catalog and refreshes it whenever the picker opens.

The picker requests exercises with patientId, so exercise results are enriched with: - personalizedVideo when that patient has a custom exercise demo

That means a doctor sees patient-specific thumbnails and playback directly in the picker, without needing to save and reload.

API Support

The exercises endpoint now accepts optional patientId:

GET /v2/exercises?lang=en&patientId=123

Implementation: OktaPT-API/src/routes/exercises/exercises.ts

When a doctor passes patientId, the backend: 1. verifies access to that patient 2. loads exercise results 3. attaches personalized video metadata for that patient's exercises


Exercise Media Behavior

Priority Rules

The HEP flow uses the same media priority as the rest of mobile:

  1. personalizedVideo.cloudflareStreamId
  2. kinescopeVideoId
  3. cloudflareStreamId
  4. videoUrl (YouTube)
  5. photoUrl

Cross-reference: - docs/personalized-exercise-videos.md - docs/exercise-media-rendering.md

Thumbnail Clickability

In the HEP flow, thumbnails are clickable anywhere a playable video source exists:

  • Current session exercise rows
  • Exercise picker cards

Non-thumbnail taps keep their original behavior: - HEP session row body = edit exercise - picker card body = select exercise

Initial Kinescope Fix

Some HEP session payloads could arrive with a thumbnail URL but without all raw video source IDs fully populated.

To keep thumbnail playback working immediately on first load, the mobile normalization layer now infers missing playable IDs from known thumbnail URL patterns: - Kinescope poster URL → infer kinescopeVideoId - Cloudflare thumbnail URL → infer cloudflareStreamId

Implementation: Okta-Mobile/lib/doctorHepUtils.ts

Preview Modal

Thumbnail playback uses:

  • Okta-Mobile/components/workout/ExerciseMediaPreviewModal.tsx
  • Okta-Mobile/components/workout/WorkoutVideoPlayer.tsx

This is a generic fullscreen preview modal for HEP media playback that supports: - personalized Cloudflare videos - Cloudflare Stream - Kinescope - YouTube


Personalized Videos in HEP

This feature fully supports patient-specific personalized exercise videos.

Where Personalized Videos Appear

If a patient has a personalized video for an exercise, that personalized media should be visible: - in the current HEP session list - in the add-exercise picker - immediately after adding the exercise to the plan - in thumbnail previews and fullscreen playback

Backend Support

The HEP session API uses:

  • attachPersonalizedVideos() from OktaPT-API/src/services/personalizedVideoService.ts

to attach patient-specific personalizedVideo objects to workout exercises.

Mobile Preservation

When an exercise is selected from the picker and added into the local HEP draft, the app preserves: - personalizedVideo - cloudflareStreamId - kinescopeVideoId - videoUrl - photoUrl - thumbnailUrl

in local state so the correct media is shown immediately, not only after save/reload.

Implementation: Okta-Mobile/lib/doctorHepUtils.ts


AI Editing

With the planAssistant flag the AI Assistant sheet talks to the plan assistant instead: the plan stays on the screen, a strip under the header shows the reply as it comes with Stop, each change lands on the view as it is made (the row lights up), Undo AI reverts the whole answer, and a question or an exercise to pick reopens the sheet with the options as chips. Internals in plan-assistant internals. The rest of this section is the older flow, kept where the flag is off.

AI Assistant sheet

The AI Assistant row at the end of either list opens a sheet with one multiline request:

  • Okta-Mobile/components/doctor/hep/HepAiSheet.tsx

Doctors can type natural language requests such as: - symptoms the patient is reporting - day-specific changes - adding or removing certain movements - intensity adjustments

Endpoint

POST /v2/ai/therapist-plan-edit

Request Shape

The mobile app sends: - patientId - currentPlan - userMessage - conversationHistory (currently empty in this mobile flow)

Apply Behavior

AI updates are applied only after the stream completes successfully.

The screen then shows: - a compact change summary - an Undo AI action that restores the previous local plan snapshot - immediate thumbnail/video hydration for AI-added exercises from the patient-scoped exercise catalog

Streaming

The mobile screen uses the shared XHR/SSE-like streaming hook:

  • Okta-Mobile/hooks/useStreamingRequest.ts

During streaming: - the keyboard is dismissed immediately - the normal session list is replaced with skeleton session cards - the skeleton session area remains vertically scrollable - workouts_count marks cards as ready as the AI completes each session

The mobile streaming hook stores both section and section_streaming events in streamingSections, which is how HEP consumes change_overview and workouts_count from the therapist-plan-edit stream.


Save Flow

Primary Save Endpoint

The HEP editor saves through:

PUT /v2/doctor/patients/:patientId/hep-management

This is a dedicated mobile persistence path for the week the screen shows. It avoids the heavier shared web edit-plan rewrite flow and updates sessions by workoutId when available.

Save Payload

The mobile app converts the local week into: - sessions[] - slotIndex - dayNumber - workoutId - full ISO date - focus - exercises

Empty placeholder sessions are still sent, but the backend treats them as: - delete the existing workout if workoutId is present - no-op if the slot is still a placeholder

Protected sessions are preserved by the backend even if they became protected after the screen first loaded.

When HEP performs the follow-up save after a background rebalance, the payload also includes: - notifyDoctorOnCompletion: true

The save carries no schedule; the server reads it off the saved days (a rule set explicitly through the API earlier stands). On save the server drops system-scheduled sessions after the saved window so they are regenerated from the new plan. Sessions the doctor changes are marked source: CLINICIAN.

focus now persists through Workout.doctorNote, so AI-generated or pre-existing session focus text survives save/reload.

Mobile adapter: Okta-Mobile/services/doctorHepService.ts


Unsaved Changes Guard

The HEP editor prevents accidental loss of unsaved edits through a multi-layer navigation guard.

Dirty Tracking

The useDoctorHepEditor hook exposes an isDirty flag that becomes true whenever any exercise is added, removed, or modified since the last save (or since the initial load). The hook also exposes getUnsavedSummary(), which returns a human-readable list of pending changes (e.g. "Added 2 exercises", "Removed 1 exercise", "Changed dosage on 3 exercises").

While isDirty is true:

  • iOS swipe-back gesture is disabled at every stack level. Because the manage screen is nested inside (hep) → (doctor) → root Stack, the gesture is disabled on the current navigator and both parent navigators via navigation.getParent().
  • Android hardware back button is intercepted with React Native's BackHandler.

Confirmation Dialog

When the user attempts to leave (back button, swipe, or explicit navigation) with unsaved changes, an Alert is shown with:

  • Title: "Unsaved Changes"
  • Body: the output of getUnsavedSummary(), or a generic fallback message
  • Actions:
  • Save and Exit (preferred) — calls the save endpoint, then navigates away
  • Discard Changes — navigates away without saving
  • Cancel — returns to the editor

Once the editor is saved (or changes are discarded), the gesture and back-button guards are re-enabled automatically.


Save-Time AI Rebalance

Why It Exists

After manual editing, some sessions may end up: - below target (fewer than 3 exercises) - above target (more than 5 exercises)

The doctor can choose to let AI rebalance the plan around the changes they just made.

Trigger

After a successful manual save, the app checks only the first 5 editable session slots for rebalance issues.

If any session is outside the target range, it prompts with: - Rebalance plan? - {{count}} sessions are outside the target of 3-5 exercises per day. Let us rebalance the plan for you.

Actions: - No - Yes

Rebalance Endpoint

POST /v2/ai/therapist-plan-rebalance

Request Shape

{
  "patientId": 123,
  "currentPlan": [...],
  "lockedChanges": [
    {
      "dayNumber": 1,
      "lockedAddedExerciseIds": [12],
      "lockedModifiedExerciseIds": [44],
      "lockedRemovedExerciseIds": [87]
    }
  ],
  "rules": {
    "minExercisesPerSession": 3,
    "maxExercisesPerSession": 5
  }
}

AI Scope

Both AI edit and AI rebalance remain intentionally scoped to the first 5 session slots in the HEP window, even though the screen displays and saves the whole week. Manual editing continues to work across the full week.

Locked-Change Contract

The rebalance endpoint is constrained to preserve doctor edits.

It must: - not remove locked added exercises - not re-add locked removed exercises - not modify dosage or block for locked modified exercises - return every session in the input window - enforce 3-5 exercises per workout in the response

Response Schema

Defined in:

  • OktaPT-API/lib/openai_response_formats/pt_therapist_plan_rebalance_schema.ts

UX

The rebalance flow is now a background handoff rather than an in-place blocking flow.

After the initial manual save succeeds: 1. the app immediately marks the editor clean and shows a lightweight saved acknowledgement 2. if any editable sessions are outside the 3-5 exercise target, it then prompts the doctor to rebalance 3. if the doctor chooses Yes, mobile starts the rebalance request in the background 4. the doctor is immediately routed back to the in-clinic dashboard 5. the in-clinic dashboard shows a green top toast: The rebalanced plan will be emailed to you shortly. 6. if rebalance succeeds, mobile saves the rebalanced plan again with notifyDoctorOnCompletion: true 7. the backend then sends the doctor a PLAN_UPDATE notification/email that the updated plan is ready

If the doctor chooses No: - the initial manual save stands as-is - the HEP screen shows the normal saved toast before the user leaves

If the background rebalance fails: - the original manual save still stands - the failure is logged on mobile - no follow-up success notification is sent


Local State Architecture

Types

File: Okta-Mobile/types/doctorHep.ts

Main types: - DoctorHepSession - DoctorHepExercise - DoctorHepEditLedgerEntry - DoctorHepSaveResult

Hook

File: Okta-Mobile/hooks/useDoctorHepEditor.ts

Responsibilities: - load initial 5-session window - maintain local working plan - track dirty state - track locked add/edit/remove exercise IDs for AI rebalance - apply AI updates - support AI undo - save through the doctor HEP service

Utilities

File: Okta-Mobile/lib/doctorHepUtils.ts

Responsibilities: - normalize HEP session payloads - build new exercise drafts with defaults - preserve media metadata - convert local state to API payloads - apply AI plan results to local sessions - summarize session count violations for rebalance


Components

HepSessionCard

File: Okta-Mobile/components/doctor/hep/HepSessionCard.tsx

One day of the Sessions view (the name is historical: it is a heading over rows, not a card). Shows: - the date (formatSessionDate, in UTC so the calendar day is right in every timezone; the copy sheet, the post-upload notice and the day chips of lib/hepProgram/cadence.ts format in UTC the same way) - session number and exercise count on one Meta line (sessionMeta: one exercise in the singular, nothing for an empty day), the focus on the next, up to two lines - Add (this day only) and the more button on a day with exercises, or an In progress chip when the session is protected - one HepExerciseRow per exercise, or the empty placeholder with Copy previous session

HepSessionActionsSheet

File: Okta-Mobile/components/doctor/hep/HepSessionActionsSheet.tsx

The day's more sheet on the shared Sheet: Reorder exercises (two or more exercises) and Copy to other sessions. The screen closes the sheet first and opens the chosen modal from the sheet's onDismiss on iOS (two modals cannot be presented at once), at once on Android; the floating + stays hidden in between. The sheet keeps showing its day while it slides away, and records RTM activity like the other HEP sheets.

HepExerciseRow

File: Okta-Mobile/components/doctor/hep/HepExerciseRow.tsx

The design system's Media row. Shows: - the picture, flush with the row's left edge (HepExerciseThumbnail, 96 by 72, with a play, expand or problem badge in the corner; processing and failed personalized videos keep their states) - exercise name (two lines at most) - the dose and weight (formatHepDose, built on formatDose in lib/setPlan.ts, also used by the Program card) - chips for a non-main block and, when a pain or effort target is set, Guidelines set - the note on one line - a trash (or a chevron when read-only)

VoiceOver reads the row as one button (name, dose, block and note) with Delete Exercise and the picture's action (Watch video, View photo) as its actions.

Interaction split: - thumbnail press = preview - row press = edit - trash = remove (with the single / future-sessions prompt)

HepProgramRow

File: Okta-Mobile/components/doctor/hep/program/HepProgramRow.tsx

One exercise of the Program view: the picture (HepExerciseThumbnail), the name, the day strip (stripDotLayout sizes the dots from the screen width before the first frame, so they never wrap or clip), the dose chip, chips for the block, dose variants and guidelines, the note and the lock line. The strip unfolds the presets and, for Custom, HepSessionDots; the dose chip unfolds two HepDoseSteppers, which save a typed number on blur, on Done, or when they unmount with the field still focused. The card is a Pressable with onAccessibilityTap (VoiceOver's double-tap would otherwise land in the middle of the card, on the strip) and offers the schedule, the dose, the video and the row actions as accessibility actions, named with the translated labels because iOS speaks the action's name.

HepExercisePickerModal

File: Okta-Mobile/components/doctor/hep/HepExercisePickerModal.tsx

Uses the exercise-library UI pattern for patient-aware exercise selection.

HepDosageEditorModal

File: Okta-Mobile/components/doctor/hep/HepDosageEditorModal.tsx

Edits: - type - sets - reps / duration - weight - block - prescribed pain tolerance - prescribed exertion tolerance - clinical note

HepAiSheet

File: Okta-Mobile/components/doctor/hep/HepAiSheet.tsx

The AI Assistant's sheet: one multiline request and a send button. The result shows in HepAiSummaryBanner above the list, with Undo.


Translations

All HEP strings were added to: - Okta-Mobile/locales/en.json - Okta-Mobile/locales/ru.json

Key namespace: - hepManagement

Supporting additions were also made to: - common.yes - common.no - inClinic.manageHep

Cross-reference: - docs/mobile-translations.md


Verification

Implementation was verified with:

npm test -- --runTestsByPath src/routes/__tests__/doctor-hep-management.test.ts

in: - OktaPT-API

and:

npx tsc --noEmit

in: - Okta-Mobile

and:

npm run build

in: - OktaPT-API

This confirms the mobile HEP codepaths type-check and the backend HEP codepaths build successfully.


Key Files

Mobile

  • Okta-Mobile/app/(doctor)/(hep)/manage.tsx
  • Okta-Mobile/app/(doctor)/(hep)/_layout.tsx
  • Okta-Mobile/components/doctor/DoctorDashboard.tsx
  • Okta-Mobile/components/doctor/hep/HepSessionCard.tsx
  • Okta-Mobile/components/doctor/hep/HepExerciseRow.tsx
  • Okta-Mobile/components/doctor/hep/HepExercisePickerModal.tsx
  • Okta-Mobile/components/doctor/hep/HepDosageEditorModal.tsx
  • Okta-Mobile/components/doctor/hep/HepAiSheet.tsx
  • Okta-Mobile/components/workout/ExerciseMediaPreviewModal.tsx
  • Okta-Mobile/hooks/useDoctorHepEditor.ts
  • Okta-Mobile/hooks/useExercises.ts
  • Okta-Mobile/lib/doctorHepUtils.ts
  • Okta-Mobile/services/doctorHepService.ts
  • Okta-Mobile/services/exerciseService.ts
  • Okta-Mobile/types/doctorHep.ts
  • Okta-Mobile/types/exercise.ts
  • Okta-Mobile/locales/en.json
  • Okta-Mobile/locales/ru.json

API

  • OktaPT-API/src/routes/doctor/index.ts
  • OktaPT-API/src/routes/doctor/controller.ts
  • OktaPT-API/src/routes/__tests__/doctor-hep-management.test.ts
  • OktaPT-API/src/routes/ai/index.ts
  • OktaPT-API/src/routes/ai/controllers.ts
  • OktaPT-API/src/routes/exercises/exercises.ts
  • OktaPT-API/src/services/personalizedVideoService.ts
  • OktaPT-API/lib/openai_response_formats/pt_therapist_plan_rebalance_schema.ts
  • OktaPT-API/prisma/migrations/20260301120000_add_workout_patient_incomplete_schedule_index/migration.sql

  • docs/mobile-ui-ux-design.md
  • docs/mobile-keyboard-handling.md
  • docs/mobile-exercise-management.md
  • docs/patient-workout-management.md
  • docs/therapist-ai-plan-generation.md
  • docs/personalized-exercise-videos.md
  • docs/exercise-media-rendering.md
  • docs/ai-integration-guide.md
  • docs/feature-flags.md