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
| Prop | Type | Default | Description |
|---|---|---|---|
measurementTypeKey | MeasurementTypeKey | Required | Selects the catalog fields and validation rules. |
saveMeasurement | (input: ManualEntrySaveInput) => Promise<unknown> | Required | Persist or enqueue the entered measurement. |
initialValues | Partial<Record<string, number>> | {} | Initial values keyed by catalog field. |
recordedAt | Date | Current time | Initial measurement timestamp. |
title | string | Add measurement | Form heading. |
labelForField | (field: string) => string | Field key | Localize or format a field label. |
labelForUnit | (unit: string) => string | Cel becomes °C; other units unchanged | Format the catalog unit. |
onSaved | (input: ManualEntrySaveInput) => void | — | Called after saveMeasurement resolves. |
testID | string | — | Identifier forwarded to the card. |
theme, slots | OvokUiProps | — | 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.