Form Rendering Engine
Component hierarchy, field type mapping, and architectural patterns for the patient UI form renderer.
Form Rendering Engine
The patient UI form renderer turns a backend JSON config into a fully interactive multi-section form. The same engine is reused for both Consent and AOE form types.
10.1 Component Hierarchy
Navigation state machine: The ConsentNavigation class (PatientConsentNavigation.ts) manages multi-process navigation via the useConsentNavigation() hook. It tracks the current process/subprocess, navigation history, process order (including dynamically inserted child processes), and start/end process detection.
10.2 Field Type Mapping
Defined in ControlMapper.tsx — each backend field_type maps to a lazy-loaded React component:
Backend field_type | Frontend Component | Notes |
|---|---|---|
Text | Input | Also handles Email, Number, TextArea via HTML type prop |
Date | DatePicker | Uses react-datetime; format from dateformat attribute |
DateTime | DatePicker | Split date/time formats; type detected in calculateFormConfig() |
Time | DatePicker | Time-only picker |
Image | Image | Display-only image |
Signature | CustomSignature | react-signature-canvas; uploads to S3 |
Upload / Camera / File | Upload | File input + webcam; validates count/size; uploads to S3 |
ContactNumber | PhoneNumber | International phone number input |
CheckBox | CheckBoxGroup | Multi-select; totalColumns = 1 default |
RadioButton | RadioButtonGroup | Single-select; totalColumns = 1 default |
SelectableButton | SelectableButtonGroup | Button-style selector |
Address | GoogleAddress | Google Places autocomplete; singleLineAddress = true |
Select | Select | Dropdown |
Calendar | DateSelectionCalendar | Full calendar widget |
Button | Button | Action button |
Type transformation in calculateFormConfig(): Text fields with type: "datetime-local" are promoted to DateTime; type: "date" to Date; type: "time" to Time. Upload-type fields get presigned URL config and S3 path prepared.
Fallback: In prepareFieldConfig(), if field_type is not in the VALID_TYPES array, it falls back to "Text".
10.8 Key Architectural Patterns
| Pattern | Description |
|---|---|
| Config-driven rendering | Entire form structure determined by JSON config — no hard-coded fields |
| Generic reducer factory | All Redux slices use createNamedReducer with action type conventions |
| Component method bridge | triggerFormAction(name, params) bridges parent-child — parent registers ALLOWED_COMPONENT_METHODS, any child invokes by name |
| Lazy loading | All field controls are React.lazy() imported in ControlMapper.tsx |
| Iteration model | For repeatable processes, iteration counter tracks fill count; previous values stacked in iterationValues |
| Navigation state machine | ConsentNavigation class manages multi-process flows — branching, backtracking, dynamic child process insertion, abort/restart |
| CSS Modules + Bootstrap | CSS Modules for scoped styles; Reactstrap for grid layout; var(--crmPrimary) for lab branding |