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
| Concern | Frontend responsibility |
|---|---|
| Config UX | Load templates/configs, let user add/edit/remove configs, validate obvious input issues |
| Runtime capture | Show checkboxes, inject defaults, remember which config ids were used |
| UI replay | Re-open unresolved missing details into the form using fetchAndPopulateMissingFields(...) |
| Discoverability | Show Missing Data tags in grids and detail flows |
| Manual resolution | Call 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
Missingcheckbox 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 Datatag. - Show unresolved missing details on the waiting list, dashboards, accession pages, and the
Missing Datatab. - Give staff one-click routes into patient update or order update from the Missing Data tab.
Core frontend state objects
| State key | What it stores | Why it exists |
|---|---|---|
missingFieldState | Whether a field is currently marked as missing | Source of truth for checked/unchecked behavior |
missingFieldUIVisible | Whether the checkbox should still be shown vs hidden | Lets the UI swap between checkbox and Missing Data label |
missingFieldConfigUsed | Config row id keyed by field name | This is what the backend later receives as selected missing config ids |
allowMissingFieldsInRegistration | Gate for collection-centre visibility | Prevents unsupported CC flows from showing missing checkboxes |
Additional:
| State key | What it stores | Where it matters |
|---|---|---|
patientMissingFieldEntries | Map of patient/bill id to unresolved field names | CC-specific filtering and prepopulation |
currentPatientMissingId | Which patient is currently being replayed into the form | Used 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,
handleMissingToggleinjects the configured value and records theconfig idthat 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
| Area | Function / component | Path | Role |
|---|---|---|---|
| Field checkbox | MissingFieldCustomCheckBox | MissingFieldsCheckBox/index.tsx | Render/hide checkbox, update generic state |
| Field enum | MissingField enum | constants.ts | Canonical field names used across UI helpers |
| Runtime mutation | handleMissingToggle | missingFields.ts | Inject default value into form and persist config-used mapping |
| Replay helper | fetchAndPopulateMissingFields | missingFields.ts | Reload unresolved records into UI state |
| Reset helper | checkAndResetMissingField | missingFields.ts | Clear missing state when user enters a real value |
| List API helper | getLabMissingDetails | helpers.ts | Read unresolved/resolved rows |
| Patch helper | patchLabMissingDetailsResolution | helpers.ts | Manual resolve call |
| Config preload | fetchLabMissingDetailsConfiguration | helpers.ts | Load active lab config into model state |
| Primary list screen | MissingDetailsTab | missingDetailsTab.tsx | Main 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.