Frontend

Frontend architecture, component responsibilities, data fetching, filter flow, heatmap rendering, and export behavior for Antimicrobiogram.

👤 Rucha M Kulkarni📅 Updated: May 18, 2026📁 Antimicrobiogram

Frontend

This page explains the Antimicrobiogram frontend from the point of view of an engineer reading the React code.

Primary files

FileResponsibility
apps/livehealth-frontend/src/components/Finance/MIS/Components/TestValues/index.tsxParent container, tab wiring, feature gating
apps/livehealth-frontend/src/components/Finance/MIS/Components/TestValues/components/OrganismAntibioticResultsView.tsxMain Antimicrobiogram UI
apps/livehealth-frontend/src/components/Finance/MIS/Components/TestValues/helpers.tsFetch helpers, heatmap builders, export helpers
apps/livehealth-frontend/src/components/Finance/MIS/Components/TestValues/constants.tsColors, labels, date format constants
apps/livehealth-frontend/src/components/Finance/MIS/Components/TestValues/utils/interface.tsType contracts used by the screen

Feature gating

The frontend checks one session-level switch:

Boolean(sessionState?.is_antimicrobiogram_enabled)

That single flag controls whether the Organism/Antibiotic Results tab is added to the Test Values tab list. This is a clean product choice because it keeps the rest of the screen untouched for labs that do not use the feature.

Parent screen behavior

The Antimicrobiogram UI is mounted from TestValues/index.tsx. That parent file does three important things:

  1. decides whether the Organism/Antibiotic Results main tab should exist
  2. owns the sub-tab state for:
    • Microbiology
    • Molecular
    • Antimicrobiogram
  3. hands rendering over to OrganismAntibioticResultsView when the tab is active

This means the feature does not live in isolation. It is intentionally part of a broader organism/antibiotic result exploration surface.

Main component state

OrganismAntibioticResultsView owns the key runtime state for the feature.

Data state

rawResults, sensitivityResults, dataLoading

Filter state

selectedSample, selectedService, selectedOrganization, selectedPatient, dateField, startDate, endDate

Export state

exporting, downloadOpen

Grid state

  • antimicrobiogramGridApiRef

This is a good state split. It keeps fetching, filtering, and export concerns separate enough to reason about without making the component over-abstracted.

Fetch lifecycle

The fetch flow is driven by loadOrganismAntibioticResults(...), which wraps fetchOrganismAntibioticResults(...).

Common request behavior

Every request sends:

  • response_type=both
  • date range as Unix seconds
  • optional sample_type

The endpoint is:

  • /api-v3/report/organism-antibiotic-results/

Result-type behavior by sub-tab

Sub-tabRequest behavior
Microbiologysends result_type=MICROBIOLOGY
Molecularsends result_type=MOLECULAR
Antimicrobiogramdoes not send result_type, so the backend can return both source families

Date behavior

Raw result tabs can switch between:

  • report_date
  • bill_time

The Antimicrobiogram heatmap always uses:

  • report_date_from
  • report_date_to

That keeps the matrix experience simpler.

useEffect-driven refresh model

The screen refetches when important inputs change:

  • sub-tab
  • date field
  • date range
  • selected sample
  • selected service
  • selected organization

This means the page behaves like a report screen, not like a static cached table.

Filter behavior

Not every filter behaves the same way, and that is intentional.

FilterRaw result tabsAntimicrobiogram
Date rangeserver refetchserver refetch
Sample typeserver refetchserver refetch
Serviceclient filterserver refetch
Patientclient filternot shown
Organizationnot shownserver refetch

This pattern makes sense:

  • raw tabs behave like a data explorer
  • Antimicrobiogram behaves like a scoped report

Default organization selection

The Antimicrobiogram sub-tab is organization-wise, so the frontend needs a sensible default.

The flow is:

  1. fetch the result set
  2. derive organization options from organization_id and organization_name
  3. sort the options
  4. if no organization is selected yet, select the first available one
  5. refetch with organization_id

This gives a nice first-load experience because the user does not land on an empty or ambiguous lab-wide view. The page immediately narrows itself to a specific organization with data.

Option building

The frontend builds filter options from the fetched rows using buildUniqueOptions(...).

It derives:

  • patient options
  • service options
  • sample options
  • organization options

This means the filters are data-backed and only show values that actually exist in the currently fetched result set.

Heatmap rendering

The Antimicrobiogram matrix is built from the backend sensitivity payload, then narrowed using the filtered result set.

The transformation steps are:

  1. gather all visible antibiotics across the sensitivity rows
  2. sort antibiotic names alphabetically
  3. assign synthetic column ids like antibiotic_0, antibiotic_1, and so on
  4. create one row per organism
  5. attach the full aggregated antibiotic cell object into the correct synthetic field

Each cell object carries:

  • name
  • total_tested
  • sensitive_count
  • resistant_count
  • intermediate_count
  • sensitivity_pct
  • resistant_pct
  • intermediate_pct

That is a nice design because the renderer can stay focused on display while the data object still keeps the deeper grouped values attached to it.

Heatmap headers

The heatmap has custom headers for both the organism column and the antibiotic columns.

Organism header

The organism header shows:

  • Organism Group
  • N=<total>

Antibiotic headers

Each antibiotic column header shows the antibiotic name in a compact heatmap-style cell.

This makes the matrix dense but still readable.

Color system

The heatmap colors are defined in constants.ts.

RangeMeaningColor family
>= 90%high sensitivitygreen
70% - 89%medium sensitivityamber
< 70%low sensitivityred
no dataemptywhite

The same thresholds drive:

  • cell background colors
  • cell text colors
  • legend swatches
  • Excel export cell styles

That consistency is important. The export looks and feels like the on-screen report instead of becoming a disconnected spreadsheet dump.

Export behavior

Excel export is implemented through the visible ag-Grid instance and exportAntimicrobiogramToExcel(...).

What gets exported

  • all heatmap columns
  • matrix cell values as formatted strings such as 46.02% (N=415)
  • metadata rows
  • legend rows

Metadata rows included

  • organization name
  • period
  • sample type
  • service
  • generated-on timestamp

Sheet details

  • file name prefix = Antimicrobiogram_YYYYMMDD_HHmm
  • sheet name = Antimicrobiogram

This gives the exported sheet enough context to be meaningful even after it leaves the app.

Why the frontend implementation is good

The frontend design is strong for a few reasons:

  • it keeps feature gating simple through session state
  • it reuses one view for raw rows and matrix rendering
  • it uses the backend summary table rather than trying to aggregate raw report values in the browser
  • it makes organization scoping automatic
  • it keeps export logic close to the rendered grid

In short, the frontend is doing exactly what it should do: present, filter, and export already shaped data instead of owning the reporting computation itself.

Quick engineer mental model

If you are new to the code, this is the easiest way to think about the UI:

  1. index.tsx decides whether the feature exists on the page
  2. OrganismAntibioticResultsView.tsx owns the runtime behavior
  3. helpers.ts turns the API payload into a heatmap-friendly shape
  4. ag-Grid renders the rows and columns
  5. the same grid powers Excel export

That is the full frontend story.

On this page