Skip to main content

Profile & Settings


Profile​

Route: /profile
File: memberportal/src/pages/ProfilePage.tsx
FHIR Resource: Patient

The Profile page shows the patient's personal information pulled from their Patient FHIR resource:

  • Full name
  • Date of birth
  • Gender
  • Contact information (phone, email)
  • Address

Settings​

Route: /settings
File: memberportal/src/pages/SettingsPage.tsx

The Settings page is the most complex page in the portal. It is organized into sections:

1. Hospital Connections​

Patients can connect to hospitals registered in the system via SMART on FHIR. The Hospital Connections section lists all currently connected hospitals and provides a Connect Hospitals button that opens the HospitalPickerModal.

Connected hospital actions:

  • Sync — triggers a background data refresh for that hospital (POST fhir/referesh/single/{connectionId}). The app polls sync status via useSyncPoller until the job completes.
  • Disconnect — opens a confirmation modal, then calls POST fhir/ehr-import/disconnect/{connectionId}. The hospital is removed from the list; existing synced records remain visible.

HospitalPickerModal​

The picker fetches hospitals from GET fhir/hospitals/search and displays them in a searchable, filterable list.

Search & filters:

ControlBehaviour
Name searchDebounced 400 ms; sends name query param
StateDropdown (country-state-city); sends state param and primes the state cache
CityAutocomplete populated from the selected state; filtered client-side from cache
Zip CodeFree-text; filtered client-side from cache

State endpoint cache: When the patient selects a state with no city/postal/name filter, the full results are stored in stateEndpointCache. Subsequent city, postal, or name changes are applied client-side without a new API call. The cache is cleared when the modal opens or when the state is changed.

Pagination: Results without address filters include _count=50. If hasMore is true the modal uses an IntersectionObserver on a sentinel <div> to automatically call GET {nextUrl} (load-more) as the patient scrolls.

Hospital result card: Each result shows the hospital name, address (city / state / zip from _org), and a Connect button. Already-connected hospitals show a "Connected" badge instead.

Connect flow:

  1. Patient clicks Connect on a hospital.
  2. If the hospital's EHR_VENDOR_EXT_URL extension identifies the vendor as healow, a country check runs first (see Healow geo-restriction below).
  3. POST fhir/ehr-import/hospital-start is called with { hospitalId }.
  4. The server returns { authorizeUrl } and the browser is redirected there to complete OAuth2.
  5. After the patient authenticates, the EHR redirects back and the hospital appears in the connected list.

Healow geo-restriction:

Healow only supports OAuth connections from within the United States. Before redirecting a patient to a Healow hospital's authorization endpoint, the app checks their country:

  1. getCountryCode() is called — it resolves in this priority order:
    • In-memory cache (countryCodeCache ref, lives for the tab session)
    • localStorage key _cc_geo (persists across sessions)
    • HTTP call to https://api.country.is/ with a 3-second timeout
  2. If the resolved country is not US, an error notification is shown and the redirect is cancelled.
  3. On any API error the check fails open (returns 'US') so an outage never blocks a legitimate US patient.

2. Privacy & Security​

Password reset:

  • Patient can request a password reset email.
  • Protected by invisible reCAPTCHA to prevent abuse.
  • Calls POST auth/resetpassword with the patient's email, project ID, and reCAPTCHA token.

Two-Factor Authentication (2FA):

  • Patient can enable or disable TOTP-based 2FA.
  • Enable flow:
    1. GET auth/mfa/status — server returns a TOTP secret and QR code URI.
    2. Patient scans the QR code with their authenticator app (or enters the manual secret).
    3. Patient enters a 6-digit code; POST auth/mfa/enroll verifies it.
    4. 2FA is now active on the account.
  • Disable flow:
    1. Patient enters their current 6-digit code.
    2. POST auth/mfa/disable removes 2FA from the account.

Session Timeout: Patient can choose how long before they are automatically logged out due to inactivity:

  • 15 minutes (default)
  • 30 minutes
  • 60 minutes
  • 4 hours

The setting is saved to localStorage and read by useIdleTimeout.