Skip to content

Mobile Doctor Dashboard

Overview

The mobile doctor home was redesigned in May 2026 around three ideas: see every patient at a glance, prep for the patients you're seeing today, and drill into a single patient's signals without leaving the dashboard. The new dashboard surfaces compliance grades on every patient row, lets the therapist mark patients as "seeing today," exposes a dedicated patient detail screen with a Quick Analysis view, and adds a one-tap re-onboarding flow for patients who never finished signing up.

Compliance grades and per-patient activity stats come from the same backend service that powers the admin Daily Review tool — see internal/daily-review.md for the grading rubric and payload shape.

Dashboard Layout

components/doctor/DoctorDashboard.tsx renders a SectionList with two sections:

  1. Today's patients — patients the therapist has added to today's caseload via useInClinicPatients(). Each row shows a small indicator dot and a dismiss button.
  2. All patients — the full list, filtered by the scope toggle.

The header above the list contains:

  • The greeting and date (Today, {date})
  • A patient count ({n} patients)
  • A scope toggle: My patients (directly connected) vs All patients (entire tenant — only when the allActivePatientsDashboard feature flag is enabled)
  • A search icon that opens PatientSearchModal
  • An "Add patient seeing today" button that opens TodayPickerModal
  • An "Onboard new patient" button that opens OnboardPatientModal

Skeleton rows (PatientRowSkeleton) appear while usePatientsSummary is loading.

Patient Row

components/doctor/PatientRow.tsx is the workhorse cell. Each row shows:

  • Avatar with initials
  • Patient name + case (most recent injury / operation, or "No case")
  • A "Not onboarded" pill when the patient hasn't completed onboarding
  • A compliance grade chip (ComplianceGrade component, see below)
  • A last-visit chip with relative time ("Today", "Yesterday", "3 days ago", "2 weeks ago", …) and a stale indicator after 14 days
  • Flag chips for elevated pain/exertion, long inactivity, excessive exercises, and never-started states (FlagChip component)
  • A small "today" dot on the left rail when the patient is in today's list, plus a dismiss button on the right

Compliance Grade Chip

components/doctor/ComplianceGrade.tsx renders a single letter (A+, A, B, C, D, F, or a dash for NONE) with palette-tuned background and text colors:

Grade Color family
A+, A Green
B Lime
C Amber
D Orange
F Red
NONE Gray

Sizes (sm, md, lg) and variants (chip background vs bare letter) let the same component fit in row cells, header summaries, and the full-bleed Quick Analysis card.

Seeing Today

useInClinicPatients() persists a per-doctor list of "patients I'm seeing today" in AsyncStorage. TodayPickerModal shows the doctor's full caseload with checkboxes; the modal preloads the full patient list via usePatientsSummary().loadPickerPatients() so it can list patients outside the current scope. Adding a patient surfaces a success toast and the row immediately appears in the Today's patients section at the top of the dashboard.

Dismissing a patient from today's list is a one-tap action on the row (no confirmation) — it only removes them from the today list, not from the caseload.

Patient Detail Screen

app/(doctor)/patient/[id].tsx is the per-patient hub, reachable by tapping any row. It shows:

  • Name, age, and case
  • Care team — the connected therapists, with (you) next to the viewer
  • An "Assign to me" CTA when the viewer is browsing a patient outside their caseload (only with therapistPatientAssignment enabled)
  • A "Patient hasn't onboarded yet" banner with a Re-onboard patient button when applicable
  • Stat tiles: last visit, next session, completion %
  • Action grid (filtered by feature flags):
    • Start test — clinical movement test recording
    • Record exercise video — gated by therapistPersonalizedExerciseVideo
    • Manage HEP — gated by therapistMobileHepManagement (see mobile-doctor-hep-management.md)
    • View videos — opens the personalized video library for this patient (see personalized-exercise-videos.md)
  • A Quick Analysis link that opens patient-analysis/[id].tsx
  • Two list sections:
    • Movement tests — recent clinical assessments (PatientTestRow), with a "See all tests" link
    • Personalized videos — recent personalized videos
  • A pair of Section Info modals (SectionInfoModal) that explain what movement tests and personalized videos are, opened from each section header — useful for therapists trying these features for the first time

Quick Analysis Screen

app/(doctor)/patient-analysis/[id].tsx calls a doctor-scoped endpoint that returns the same DailyReviewPatient payload shape as the admin daily review (one patient). It renders:

  • Compliance grade (lg variant) with the reason string
  • Flags section — chips for any active flags (long inactivity, elevated pain count, elevated exertion count, excessive exercises, has personalized videos, never started). Pain and exertion counts are derived from the last completed session
  • Notes section — the suggestedNotes[] array from the service, rendered as a checklist
  • Next up — upcoming session exercises with planned sets/reps/duration. Exercises with a personalized video are marked
  • Last completed — last completed session exercises with elevated pain/exertion highlighted
  • Footer stats: streak, sessions in last 7 days, sessions in last 14 days
  • A Manage HEP quick action and a View all completed sessions link to patient-sessions/[id].tsx

All Sessions Screen

app/(doctor)/patient-sessions/[id].tsx paginates through the patient's completed workouts, each session expandable to show its exercise list, with elevated pain/exertion exposed inline. The same SessionPreviewCard is used here and on the Quick Analysis "next up" / "last completed" cards.

Patient Re-onboarding

When a patient has been invited but never completed onboarding, the patient detail screen shows a Re-onboard patient CTA. Tapping it opens ReonboardPatientModal (components/doctor/ReonboardPatientModal.tsx):

  1. Loading — the modal asks patientInviteService.generateInviteLink(patientId) for a fresh magic-link URL.
  2. DOB required — if the patient has no DOB on file the backend returns requiresDob: true; the modal collects DOB via DOBFieldInput and retries.
  3. Ready — shows the magic link with three actions:
  4. Send invite email — emails the patient (patientInviteService.sendInviteEmail) when they have an email on file
  5. Copy link — copies the URL to the clipboard
  6. QR code — a react-native-qrcode-svg block under the link for in-clinic scanning
  7. The modal also exposes Generate a new link which calls the same endpoint with a regeneration flag, invalidating any prior token for the patient.

This flow reuses the same /v2/user/generate-invite-link/:patientId and /v2/user/send-invite-email/:patientId endpoints used by web — see internal/patient-onboarding.md for the full token lifecycle.

Translations

~140 new keys were added under these namespaces in Okta-Mobile/locales/{en,ru}.json:

Namespace Coverage
doctorHome Header, scope toggle, today/all sections, search hints, empty states
patientDetail Patient hub strings, action grid labels, care team, re-onboard modal copy, section info modals
quickAnalysis Flags, notes, next-up / last-completed labels, relative counts
inClinic Today picker buttons, dismiss confirmations
personalizedVideo Library picker additions (chooseFromLibrary, videoTooLongMessage, …)

All strings are present in both English and Russian.

Backend Tie-in

The doctor controller (OktaPT-API/src/routes/doctor/controller.ts) imports gradeFromActivity and getPatientSummaryStats from src/services/dailyReviewService.ts so the getMyPatients and getAllTenantPatients endpoints return:

  • Compliance grade and reason
  • Last completed date
  • Next upcoming session date
  • Completed and incomplete workout counts
  • Care team (when therapist assignment is enabled)

usePatientsSummary consumes both endpoints with separate caches, and the patient detail screen calls a single-patient summary endpoint to refresh stats when returning to the screen.

Key Files

File Role
components/doctor/DoctorDashboard.tsx Top-level dashboard list, scope toggle, modals
components/doctor/PatientRow.tsx Patient row cell
components/doctor/PatientRowSkeleton.tsx Loading state
components/doctor/ComplianceGrade.tsx Grade chip / letter
components/doctor/FlagChip.tsx Status flag chip
components/doctor/PatientSearchModal.tsx Tenant-wide patient search
components/doctor/TodayPickerModal.tsx "Seeing today" picker
components/doctor/ReonboardPatientModal.tsx Re-onboarding flow
components/doctor/SectionInfoModal.tsx Explanatory popovers
components/doctor/SessionPreviewCard.tsx Shared session/exercise card
components/doctor/PatientTestRow.tsx Clinical assessment row
app/(doctor)/patient/[id].tsx Patient detail hub
app/(doctor)/patient-analysis/[id].tsx Quick Analysis
app/(doctor)/patient-sessions/[id].tsx All completed sessions
hooks/usePatientsSummary.ts Caseload loader with scope + caching
hooks/useInClinicPatients.ts Today's-list AsyncStorage hook
services/doctorPatientsService.ts getMyPatients, getAllTenantPatients, getPatientSummary
services/patientAnalysisService.ts Quick Analysis payload
services/patientInviteService.ts Re-onboarding endpoints