Skip to main content

ManualEntryForm

ManualEntryForm builds numeric inputs from the SDK's measurementFieldCatalog for one MeasurementTypeKey. It validates required fields and catalog ranges, then passes a typed value to the app's async save callback.

import { MeasurementTypeKey } from "@ovok/core";
import { ManualEntryForm, type ManualEntrySaveInput } from "@ovok/native/ui";

const saveMeasurement = async (input: ManualEntrySaveInput) => {
await measurementRepository.save({ patientId: activePatient.id, ...input });
};

<ManualEntryForm
measurementTypeKey={MeasurementTypeKey.bodyWeight}
saveMeasurement={saveMeasurement}
labelForField={(field) => fieldLabels[field] ?? field}
onSaved={() => navigation.goBack()}
/>

The form does not select a patient, construct a FHIR resource, choose offline behavior, or navigate. Those decisions stay in the app's callback and screen.

Props​

PropTypeDefaultDescription
measurementTypeKeyMeasurementTypeKeyRequiredSelects the catalog fields and validation rules.
saveMeasurement(input: ManualEntrySaveInput) => Promise<unknown>RequiredPersist or enqueue the entered measurement.
initialValuesPartial<Record<string, number>>{}Initial values keyed by catalog field.
recordedAtDateCurrent timeInitial measurement timestamp.
titlestringAdd measurementForm heading.
labelForField(field: string) => stringField keyLocalize or format a field label.
labelForUnit(unit: string) => stringCel becomes °C; other units unchangedFormat the catalog unit.
onSaved(input: ManualEntrySaveInput) => void—Called after saveMeasurement resolves.
testIDstring—Identifier forwarded to the card.
theme, slotsOvokUiProps—Shared theme and primitive overrides.

ManualEntrySaveInput contains:

interface ManualEntrySaveInput {
measurementTypeKey: MeasurementTypeKey;
data: Record<string, number>;
recordedAt: Date;
}

Empty optional fields are omitted from data. Required values and values outside the catalog's minimum/maximum bounds show an inline validation message. The timestamp is entered as ISO 8601 text and must parse to a valid date. The form prevents another save while the previous saveMeasurement promise is pending; rejected saves are shown inline, and onSaved runs after a successful save.

initialValues and recordedAt seed the form state at mount. To load a different measurement later, remount the form with a new key or use a separate app-owned edit screen that manages changing values.

The form's built-in copy is English. Use the label callbacks and title for product language, and use the shared OvokUiProps to apply app theme and slots.

See Reusable flows for a full integration example.