Frontend

Frontend responsibilities, state shapes, UI behavior, and key components for Missing Details.

👤 Rucha Mahesh Kulkarni📅 Updated: Mar 16, 2026📁 Missing Details

Frontend

What frontend owns

ConcernFrontend responsibility
Config UXLoad templates/configs, let user add/edit/remove configs, validate obvious input issues
Runtime captureShow checkboxes, inject defaults, remember which config ids were used
UI replayRe-open unresolved missing details into the form using fetchAndPopulateMissingFields(...)
DiscoverabilityShow Missing Data tags in grids and detail flows
Manual resolutionCall patch APIs from modals or action screens

Frontend perspective (runtime)

  • Let staff keep the workflow moving instead of blocking registration or billing because one field is missing.
  • Show a Missing checkbox only for fields the lab has explicitly configured.
  • Auto-fill a known placeholder/default value when the operator marks a field as missing.
  • Keep enough generic state to know which config entry was used, what value was injected, and whether the UI should still show the checkbox or switch to a Missing Data tag.
  • Show unresolved missing details on the waiting list, dashboards, accession pages, and the Missing Data tab.
  • Give staff one-click routes into patient update or order update from the Missing Data tab.

Core frontend state objects

State keyWhat it storesWhy it exists
missingFieldStateWhether a field is currently marked as missingSource of truth for checked/unchecked behavior
missingFieldUIVisibleWhether the checkbox should still be shown vs hiddenLets the UI swap between checkbox and Missing Data label
missingFieldConfigUsedConfig row id keyed by field nameThis is what the backend later receives as selected missing config ids
allowMissingFieldsInRegistrationGate for collection-centre visibilityPrevents unsupported CC flows from showing missing checkboxes

Additional:

State keyWhat it storesWhere it matters
patientMissingFieldEntriesMap of patient/bill id to unresolved field namesCC-specific filtering and prepopulation
currentPatientMissingIdWhich patient is currently being replayed into the formUsed when reopening existing missing records

Checkbox visibility rules

The checkbox renders only if:

  • config has been loaded,
  • the specific field is configured for the lab,
  • the CC gate allows it,
  • and, in some CC replay cases, the field is part of patientMissingFieldEntries[currentPatientMissingId].

Source: MissingFieldsCheckBox/index.tsx

Runtime UI behaviors

  • When operator toggles a Missing checkbox, handleMissingToggle injects the configured value and records the config id that was used.
  • When operator later types a value that differs from the injected placeholder, checkAndResetMissingField(...) clears the missing flags so the frontend does not claim the value is still intentionally missing.
  • On submit, the frontend includes the selected missing config ids in the registration/billing payload (e.g., labMissingFieldIds, labMissingDetailsIds).

Important Missing Details Snippets (Frontend)

These snippets show the common frontend patterns for wiring fields to the Missing checkbox and for rehydrating unresolved missing fields back into the form.

Field + Missing checkbox wiring

Source: RegistrationForm.tsx and missingFields.ts

<Nationality
  nationalityField={(val: JsonObject) => {
    updateRegistrationState("nationality", val);
    updateGenericState(dispatch, "missingFieldUIVisible", {
      ...missingFieldUIVisible,
      [MissingField.NATIONALITY]: false,
    });
    checkAndResetMissingField(
      MissingField.NATIONALITY,
      val?.value || "",
      dispatch
    );
  }}
  otherProps={{
    onFocus: () => {
      updateGenericState(dispatch, "missingFieldUIVisible", {
        ...missingFieldUIVisible,
        [MissingField.NATIONALITY]: true,
      });
    },
  }}
/>

<MissingFieldCustomCheckBox
  id={MissingField.NATIONALITY}
  wrapperClassNames="ml_1_3rem"
  onToggle={(id: string, checked: boolean) =>
    handleMissingToggle(id, checked, dispatch)
  }
/>

Why it matters: focus shows checkbox, typing hides it, typing a real value clears missing state, and the checkbox delegates auto-fill to handleMissingToggle.

Rehydrate unresolved missing fields into the form

Source: missingFields.ts

export const fetchAndPopulateMissingFields = async (
  searchId: number,
  isPatient: boolean = true,
  clearPreviousState: boolean = true,
  dispatch: ThunkDispatch<AppState, void, GenericActionTypes>
): Promise<void> => {
  if (clearPreviousState) {
    dispatch(
      setGenericState({
        missingFieldState: {},
        missingFieldSavedValue: {},
        missingFieldConfigUsed: {},
        patientMissingFieldEntries: {},
        currentPatientMissingId: null,
      })
    );
  }

  const response: JsonObject = await getLabMissingDetails(
    undefined,
    undefined,
    !isPatient ? searchId : undefined,
    isPatient ? searchId : undefined,
    false,
    false
  );

  const unresolvedFields: string[] = (response?.results || [])
    .filter((f: JsonObject) => Number(f?.is_resolved) === 0 && f?.field_name)
    .map((f: JsonObject) => String(f?.field_name).toUpperCase());

  dispatch(
    setGenericState({
      patientMissingFieldEntries: {
        ...patientMissingFieldEntries,
        [searchId]: unresolvedFields,
      },
      currentPatientMissingId: isPatient ? searchId : null,
    })
  );

  for (const field of response?.results) {
    if (!field?.field_name) continue;
    populateMissingFieldState(field.field_name, true, dispatch);
    updateSavedValue(field.field_name, field.field_value, null, dispatch);
    handleMissingToggle(field.field_name, true, dispatch);
  }
};

What it does: clears stale state, fetches unresolved rows, stores unresolved field names for the patient/bill, and replays each unresolved field into the UI.

Manual Resolution Path from Missing Data UI

Key frontend locations & helpers

AreaFunction / componentPathRole
Field checkboxMissingFieldCustomCheckBoxMissingFieldsCheckBox/index.tsxRender/hide checkbox, update generic state
Field enumMissingField enumconstants.tsCanonical field names used across UI helpers
Runtime mutationhandleMissingTogglemissingFields.tsInject default value into form and persist config-used mapping
Replay helperfetchAndPopulateMissingFieldsmissingFields.tsReload unresolved records into UI state
Reset helpercheckAndResetMissingFieldmissingFields.tsClear missing state when user enters a real value
List API helpergetLabMissingDetailshelpers.tsRead unresolved/resolved rows
Patch helperpatchLabMissingDetailsResolutionhelpers.tsManual resolve call
Config preloadfetchLabMissingDetailsConfigurationhelpers.tsLoad active lab config into model state
Primary list screenMissingDetailsTabmissingDetailsTab.tsxMain Missing Data module

Frontend state lifecycle

Summary:

  • Config loaded → Checkbox visible → User marks Missing → Default injected → Tag shown → On real-value input, missing state cleared → Submitted → Restored on later open.

On this page