Admin Configuration
Admin CRUD flows for creating and editing Lab Form configurations in livehealth-frontend.
Admin Configuration (CRUD)
The admin configuration flow lets lab admins create, edit, enable/disable, and map Lab Form configurations. The entry point is the LabFormConfiguration list page.
5.1 List Page โ LabFormConfiguration
Component: src/components/LabAdmin/LabForms/components/index.tsx
- Renders an AG Grid table of all configurations for the selected
formType. - Row click โ navigates to the edit page.
- Copy โ duplicates the selected configuration.
- Enable / Disable โ opens
EnableDisableConfigurationModalfor confirmation. - Bulk Instance Mapping โ opens
MapConfigurationsToInstancesModalto bulk-assign configurations to test/profile/promotion instances.
5.2 Add / Edit Page โ AddEditLabFormConfiguration
Component: src/components/LabAdmin/LabForms/components/AddEditConfiguration/index.tsx
Two-tab layout:
- Tab 1: Basic Information โ form metadata fields
- Tab 2: Form Components โ drag-and-drop section/question builder
Lifecycle:
- On mount (edit mode): calls
getLabFormConfig(formType, configId)โ loads config into ReduxLAB_FORMslice. - On tab switch: validation runs on the current tab's fields before proceeding.
- On save: calls
validateLabForm()โ on pass, callscreateLabFormConfiguration()orupdateFormConfiguration().
5.3 Basic Information Tab
Component: src/components/LabAdmin/LabForms/components/AddEditConfiguration/BasicInformation/index.tsx
Fields:
- Name โ process name
- Description โ optional description
- Icon โ icon picker
- Process Type โ dropdown (options vary by
formType):
| Form Type | Available Process Types |
|---|---|
aoe | Bill, Test, Profile, Promotion, Store, Other |
consent | Patient, Bill, Test, Profile, Start Up, Close Down, Other |
additional_patient_info | Patient (locked โ auto-set by backend) |
- Response Preference โ "Capture once for all instances" vs "Capture separately per instance" (applicable to Test, Profile, Promotion types)
- TTL / Expiry โ only shown for
consent+Patientprocess type; value + mode (Day/Month/Year) - Mapped Tests/Profiles/Promotions โ
MappedTestssub-component with AG Grid; shown for instance-dependent process types
Changing the Process Type after questions have been added shows a SwitchProcessTypeConfirmationModal warning, as it may invalidate existing instance mappings.
5.4 Form Components Tab (Drag-and-Drop Builder)
Component: src/components/LabAdmin/LabForms/components/AddEditConfiguration/FormComponents/index.tsx
Two-panel layout:
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Section Sidebar โ Main Content Area โ
โ โ โ
โ Section A โ โบ Section A โ
โ โข Question 1 โ Question 1 โโโโโโโโโโโ [edit] [ร] โ
โ โข Question 2 โ Question 2 โโโโโโโโโโโ [edit] [ร] โ
โ Section B โ [+] Add Question โ
โ โข Question 3 โ โบ Section B โ
โ โ Question 3 โโโโโโโโโโโ [edit] [ร] โ
โ [+] Add Section โ [+] Add Question โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโThe main content area uses react-beautiful-dnd to allow dragging sections and questions to reorder them. Reordering updates the sequence field in the Redux state.
5.5 Sections
Component: src/components/LabAdmin/LabForms/components/AddEditConfiguration/FormComponents/Section/index.tsx
Each section (SectionComponent) manages:
- Name, Icon, Code, Mandatory, Hidden fields
- Import Section โ
ImportSectionModalallows importing a section from another configuration of the same form type - Communication Section โ special type available only for
consentforms; triggersAddCommunicationSectionModalfor confirmation - Delete โ
DeleteSectionModalwith confirmation; removes fromlabFormstate and tracks inremovedSections
Shared Section Guard: If a section is shared across multiple configurations, editing it shows EditExistingSectionModal listing all affected configurations. The user must explicitly acknowledge this before changes are applied.
5.6 Questions
Component: src/components/LabAdmin/LabForms/components/AddEditConfiguration/FormComponents/Question/index.tsx
Each question (QuestionComponent) displays:
- Question text, Code, Field Type selector, Mandatory / Hidden toggles
- Attribute panel โ rendered based on the selected field type (see ยง5.7)
- Conditional Config โ shown if
allow_skippingis enabled; rendersskip_to_conditionsbuilder - Prefilling Config โ shown if
allow_prefillingis enabled; source + source field picker - Delete โ
DeleteQuestionModal; for existing questions, setsis_disabled: trueand tracks inremovedQuestions
Shared Section Guard: If the question belongs to a shared section, editing shows EditExistingQuestionModal. Adding a question to a shared section shows AddQuestionModal.
5.7 Field Types & Attributes
19 supported field types, each with a dedicated attributes component:
| Field Type | Attributes Component | Key Attributes |
|---|---|---|
text | textQuestionAttributes | max_length |
textarea | textQuestionAttributes | max_length |
email | commonQuestionAttributes | placeHolder |
pin | commonQuestionAttributes | placeHolder |
phonenumber | commonQuestionAttributes | placeHolder |
number | numberQuestionAttributes | min_value, max_value |
float | floatQuestionAttributes | min_value, max_value, max_decimal_places |
select | optionsQuestionAttributes | options (add/edit/delete table) |
checkbox | optionsQuestionAttributes | options |
checkbox-group | optionsQuestionAttributes | options |
radiobutton | optionsQuestionAttributes | options (exactly 1 option) |
radiobutton-group | optionsQuestionAttributes | options |
date | dateQuestionAttributes | dateformat, allow_past_dates, allow_future_dates |
time | dateQuestionAttributes | timeformat, allow_past_dates, allow_future_dates |
datetime | dateQuestionAttributes | dateformat, timeformat, date constraints |
file | fileQuestionAttributes | label, allowed_file_types |
image | fileQuestionAttributes | label, allowed_file_types |
camera | fileQuestionAttributes | label |
signature | commonQuestionAttributes | placeHolder |
address | commonQuestionAttributes | placeHolder, address line config |
barcode | commonQuestionAttributes | placeHolder |
Date formats supported: DD-MM-YYYY, MM-DD-YYYY, YYYY-MM-DD, DD/MM/YYYY, MM/DD/YYYY, YYYY/MM/DD
Allowed file types: PDF, JPG, JPEG, PNG, DOC, DOCX, CSV, XLSX, MP4, HEIC
5.8 Presets / Templates
Component: AddConfigViaPresetModal
- Full-screen modal accessible from the list page.
- Left sidebar:
labFormPresetSidebarโ virtualized list of preset categories. - Main area:
labFormPresetListโ AG Grid of presets in the selected category. - Preview button โ
labFormPresetPreviewshows a disabled (read-only) form preview. - Use Template โ copies the preset's structure into a new configuration (loads into Redux
LAB_FORMstate and navigates to the add page).
5.9 Instance Mapping
Two entry points:
Bulk (from list page):
MapConfigurationsToInstancesModal โ select multiple configurations and map them all to a set of instances in one operation.
Inline (from edit page, Basic Information tab):
MappedTests grid โ add/remove individual test, profile, or promotion instances. Changes are tracked in addedInstanceIds / removedInstanceIds Redux state and sent on save.
API call: POST api-v3/account/lab/form/{formType}/linked-instances/bulk
Promotion and Store Mapping Rules
- Promotion: A form can be created with
Promotionprocess type and mapped to a specific promotion (example: Promo 1). In CRM, this can also be managed from CRM โ Promotions โ <Promotion> โ Configuration, where forms of any supported process type can be mapped/unmapped (not limited to Promotion-type forms). - Store: In CRM โ Store โ Configurations โ Checkout, bill and store forms are available by default for mapping, and only
BillandStoreprocess type mappings are allowed. - Booking runtime: For both Promotion and Store flows, all forms mapped to that entity are rendered during booking.
5.10 Validation
validateLabForm() runs before every save. It checks all fields and auto-focuses the first invalid input.
| Rule | Applies To |
|---|---|
| Name required | All |
| Process Type required | All |
| At least 1 section required | All |
| Section name required | All sections |
| At least 1 question per section | All sections |
| Question text required | All questions |
| Question code required + unique within section | All questions |
| Field type required | All questions |
| Options non-empty | select, radiobutton, checkbox-group, radiobutton-group |
| Exactly 1 option | radiobutton |
| Min date โค max date | Date/DateTime fields with constraints |
| TTL value required if TTL mode set | Consent + Patient type only |
| Instance mappings required | Instance-dependent process types |
Errors are stored in Redux.LAB_FORM.validationState and surfaced inline next to each field.
5.11 Save Flow
validateLabForm()
โ
โโโ FAIL โ scroll to first error, abort
โ
โโโ PASS
โ
โโโ NEW CONFIG (no id):
โ stringifyQuestionAttributes()
โ POST api-v3/account/lab/form/{formType}/config/new
โ โ redirect to edit page with new configId
โ
โโโ EXISTING CONFIG (has id):
stringifyQuestionAttributes()
Compute delta in updatedFields
PUT api-v3/account/lab/form/{formType}/config/{configId}/update
โ stay on edit page, refresh configstringifyQuestionAttributes(): Before the API call, the following attributes are serialized from objects to JSON strings:
skip_to_conditionsconfirmation_messagesprefilling_options
Dual-Track State: Every mutation in the form builder maintains two parallel Redux states:
labFormโ full current form (what the user sees in the UI)updatedFieldsโ only the delta of what changed (what is sent to the API)
This minimizes payload size and avoids overwriting unrelated fields on update.