@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2793 → 5.4.2-pre.2803
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/dist/127.js +1 -1
- package/dist/40.js +1 -1
- package/dist/{189.js → 791.js} +1 -1
- package/dist/791.js.map +1 -0
- package/dist/916.js +1 -1
- package/dist/kenyaemr-esm-patient-clinical-view-app.js +3 -3
- package/dist/kenyaemr-esm-patient-clinical-view-app.js.buildmanifest.json +36 -36
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/config-schema.ts +8 -2
- package/src/maternal-and-child-health/partography/forms/cervical-contractions-form.component.tsx +63 -28
- package/src/maternal-and-child-health/partography/forms/cervix-form.component.tsx +52 -108
- package/src/maternal-and-child-health/partography/forms/drugs-iv-fluids-form.component.tsx +110 -100
- package/src/maternal-and-child-health/partography/forms/fetal-heart-rate-form.component.tsx +7 -7
- package/src/maternal-and-child-health/partography/forms/membrane-amniotic-fluid-form.component.tsx +72 -75
- package/src/maternal-and-child-health/partography/forms/oxytocin-form.component.tsx +14 -19
- package/src/maternal-and-child-health/partography/forms/pulse-bp-form.component.tsx +34 -28
- package/src/maternal-and-child-health/partography/forms/temperature-form.component.tsx +10 -9
- package/src/maternal-and-child-health/partography/forms/time-picker-dropdown.component.tsx +10 -10
- package/src/maternal-and-child-health/partography/forms/urine-test-form.component.tsx +7 -6
- package/src/maternal-and-child-health/partography/graphs/cervical-contractions-graph.component.tsx +51 -61
- package/src/maternal-and-child-health/partography/graphs/drugs-iv-fluids-graph-wrapper.component.tsx +0 -6
- package/src/maternal-and-child-health/partography/graphs/drugs-iv-fluids-graph.component.tsx +3 -3
- package/src/maternal-and-child-health/partography/graphs/fetal-heart-rate-graph.component.tsx +53 -30
- package/src/maternal-and-child-health/partography/graphs/membrane-amniotic-fluid-graph.component.tsx +25 -3
- package/src/maternal-and-child-health/partography/graphs/oxytocin-graph-wrapper.component.tsx +102 -97
- package/src/maternal-and-child-health/partography/graphs/oxytocin-graph.component.tsx +21 -22
- package/src/maternal-and-child-health/partography/graphs/pulse-bp-graph.component.tsx +21 -24
- package/src/maternal-and-child-health/partography/graphs/temperature-graph.component.tsx +23 -26
- package/src/maternal-and-child-health/partography/graphs/urine-test-graph.component.tsx +1 -1
- package/src/maternal-and-child-health/partography/partograph.component.tsx +323 -171
- package/src/maternal-and-child-health/partography/partography-data-form.scss +23 -0
- package/src/maternal-and-child-health/partography/partography.resource.ts +70 -56
- package/src/maternal-and-child-health/partography/partography.scss +65 -6
- package/src/maternal-and-child-health/partography/resources/fetal-heart-rate.resource.ts +5 -10
- package/src/maternal-and-child-health/partography/resources/oxytocin.resource.ts +5 -3
- package/src/maternal-and-child-health/partography/types/index.ts +40 -37
- package/translations/am.json +1 -1
- package/translations/en.json +1 -1
- package/translations/sw.json +1 -1
- package/dist/189.js.map +0 -1
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"wrapComponent","route":"case-management"}],"extensions":[{"name":"hiv-care-and-treatment-dashboard-link","component":"hivCareAndTreatmentLink","slot":"patient-chart-dashboard-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","path":"hiv-care-and-treatment-dashboard","layoutMode":"anchored"}},{"name":"hiv-care-and-treatment-dashboard","slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","component":"hivCareAndTreatment","order":0,"online":true,"offline":false},{"name":"relationship-dashboard-link","component":"relationshipsLink","order":24,"online":true,"offline":false,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationship-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationship-dashboard","slot":"patient-chart-relationship-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"clinical-encounter-dashboard-link","component":"clinicalEncounterLink","order":25,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter-dashboard","slot":"patient-chart-clinical-encounter-slot","component":"clinicalEncounter","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-dashboard-link","component":"maternalAndChildHealthDashboardLink","order":26,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-maternal-and-child-health-slot","path":"maternal-and-child-health","layoutMode":"anchored"}},{"name":"maternal-and-child-health-dashboard","slot":"patient-chart-maternal-and-child-health-slot","component":"maternalAndChildHealthDashboard","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-partograph","slot":"maternal-and-child-health-partograph-slot","component":"partograph","order":0,"online":true,"offline":false},{"name":"contact-list-dashboard-link","component":"contactListLink","order":27,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-contact-list-slot","path":"contact-list","layoutMode":"anchored"}},{"name":"contact-list-dashboard","slot":"patient-chart-contact-list-slot","component":"contactList","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"special-clinics-dashboard-link","component":"specialClinicsDashboardLink","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinics-slot","path":"special-clinics","layoutMode":"anchored"}},{"name":"special-clinics-dashboard","slot":"patient-chart-special-clinics-slot","component":"specialClinicsDashboard","order":0,"online":true,"offline":false},{"name":"patient-complaints","slot":"ewf-patient-summary-slot","component":"patientComplaints","order":0,"online":true,"offline":false}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"contact-list-form","component":"contactListForm","title":"Contact List Form","type":"form"},{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"add-patient-case-form","component":"addPatientCaseForm","title":"Add patient case Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"contact-list-update-form","component":"contactListUpdateForm","title":"Contact List Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[{"component":"wrapComponent","route":"case-management"}],"extensions":[{"name":"hiv-care-and-treatment-dashboard-link","component":"hivCareAndTreatmentLink","slot":"patient-chart-dashboard-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","path":"hiv-care-and-treatment-dashboard","layoutMode":"anchored"}},{"name":"hiv-care-and-treatment-dashboard","slot":"patient-chart-hiv-care-and-treatment-dashboard-slot","component":"hivCareAndTreatment","order":0,"online":true,"offline":false},{"name":"relationship-dashboard-link","component":"relationshipsLink","order":24,"online":true,"offline":false,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationship-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationship-dashboard","slot":"patient-chart-relationship-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"clinical-encounter-dashboard-link","component":"clinicalEncounterLink","order":25,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter-dashboard","slot":"patient-chart-clinical-encounter-slot","component":"clinicalEncounter","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-dashboard-link","component":"maternalAndChildHealthDashboardLink","order":26,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-maternal-and-child-health-slot","path":"maternal-and-child-health","layoutMode":"anchored"}},{"name":"maternal-and-child-health-dashboard","slot":"patient-chart-maternal-and-child-health-slot","component":"maternalAndChildHealthDashboard","order":0,"online":true,"offline":false},{"name":"maternal-and-child-health-partograph","slot":"maternal-and-child-health-partograph-slot","component":"partograph","order":0,"online":true,"offline":false},{"name":"contact-list-dashboard-link","component":"contactListLink","order":27,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-contact-list-slot","path":"contact-list","layoutMode":"anchored"}},{"name":"contact-list-dashboard","slot":"patient-chart-contact-list-slot","component":"contactList","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"special-clinics-dashboard-link","component":"specialClinicsDashboardLink","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinics-slot","path":"special-clinics","layoutMode":"anchored"}},{"name":"special-clinics-dashboard","slot":"patient-chart-special-clinics-slot","component":"specialClinicsDashboard","order":0,"online":true,"offline":false},{"name":"patient-complaints","slot":"ewf-patient-summary-slot","component":"patientComplaints","order":0,"online":true,"offline":false}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"contact-list-form","component":"contactListForm","title":"Contact List Form","type":"form"},{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"add-patient-case-form","component":"addPatientCaseForm","title":"Add patient case Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"contact-list-update-form","component":"contactListUpdateForm","title":"Contact List Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.2-pre.2803"}
|
package/package.json
CHANGED
package/src/config-schema.ts
CHANGED
|
@@ -2,6 +2,7 @@ export const FETAL_HEART_RATE_GRAPH_UUIDS = {
|
|
|
2
2
|
fetalHeartRate: 'FETAL_HEART_RATE_CONCEPT',
|
|
3
3
|
fetalHeartRateHour: 'FETAL_HEART_RATE_HOUR_CONCEPT',
|
|
4
4
|
fetalHeartRateTime: 'FETAL_HEART_RATE_TIME_CONCEPT',
|
|
5
|
+
fetalHeartRateNew: 'FETAL_HEART_RATE_NEW_CONCEPT',
|
|
5
6
|
};
|
|
6
7
|
import { Type } from '@openmrs/esm-framework';
|
|
7
8
|
import _default from 'react-hook-form/dist/logic/appendErrors';
|
|
@@ -447,7 +448,7 @@ export const AMNIOTIC_ABSENT_CONCEPT = '163747AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
|
447
448
|
export const AMNIOTIC_BLOOD_STAINED_CONCEPT = '1077AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
448
449
|
export const AMNIOTIC_MEMBRANE_INTACT_CONCEPT = 'd1787a76-7310-4223-a645-9fd410d418c1';
|
|
449
450
|
|
|
450
|
-
//
|
|
451
|
+
//Contractions Graph
|
|
451
452
|
export const UTERINE_CONTRACTIONS_CONCEPT = '163750AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
452
453
|
export const CONTRACTION_LEVEL_MILD_CONCEPT = '1498AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
453
454
|
export const CONTRACTION_LEVEL_MODERATE_CONCEPT = '1499AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
@@ -456,12 +457,15 @@ export const UTERINE_CONTRACTION_FREQUENCY_CONCEPT = '166529AAAAAAAAAAAAAAAAAAAA
|
|
|
456
457
|
export const UTERINE_CONTRACTION_DURATION_CONCEPT = '159368AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
457
458
|
|
|
458
459
|
// Oxytocin Graph
|
|
460
|
+
|
|
461
|
+
export const OXYTOCIN_TIME_CONCEPT = 'bb3724c9-fbcc-49c5-9702-6cde0be325ca';
|
|
462
|
+
export const OXYTOCIN_DROPS_PER_MINUTE_CONCEPT = '1d109b10-7b30-4bfa-8a7c-6ecb73357fc2';
|
|
459
463
|
export const OXYTOCIN_DOSE_CONCEPT = '81369AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
460
464
|
export const ROUTE_CONCEPT = '8878f9c0-a1ce-47ec-a88f-69ef0f6576ba';
|
|
461
465
|
export const FREQUENCY_CONCEPT = 'fd9f82fd-f327-4502-ac8e-5d9144dbd504';
|
|
462
466
|
|
|
463
467
|
// Drugs IV Fluids Graph
|
|
464
|
-
export const MEDICATION_CONCEPT = '
|
|
468
|
+
export const MEDICATION_CONCEPT = 'c3082af8-f935-40c5-aa5b-74c684e81aea';
|
|
465
469
|
export const IV_FLUIDS_CONCEPT = '161911AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
466
470
|
export const DOSAGE_CONCEPT = 'b71ddb80-2d7f-4bde-a44b-236e62d4c1b6';
|
|
467
471
|
export const DRUG_DOSE_CONCEPT = '162384AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
@@ -478,6 +482,8 @@ export const GLUCOSE_LEVEL_CONCEPT = '887AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
|
478
482
|
export const KETONE_LEVEL_CONCEPT = '165438AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
479
483
|
export const URINE_VOLUME_CONCEPT = '159660AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
480
484
|
export const URINE_CHARACTERISTICS_CONCEPT = '56AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
|
485
|
+
export const TIME_RESULTS_RETURNED = '67c3d4c6-465e-4c12-9b7f-d8587ca90603';
|
|
486
|
+
export const TIME_SAMPLE_COLLECTED = 'c554f157-2e16-4585-af29-c48f5e765ce0';
|
|
481
487
|
|
|
482
488
|
// Cervix / Cervical Monitoring During Labor
|
|
483
489
|
export const CERVIX_CONCEPT = '162261AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
|
package/src/maternal-and-child-health/partography/forms/cervical-contractions-form.component.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { useForm, Controller } from 'react-hook-form';
|
|
4
4
|
import { contractionLevelOptions as baseContractionLevelOptions } from '../types';
|
|
5
|
-
import { Modal,
|
|
5
|
+
import { Modal, Select, SelectItem } from '@carbon/react';
|
|
6
6
|
import styles from '../partography.scss';
|
|
7
7
|
|
|
8
8
|
type CervicalContractionsFormData = {
|
|
@@ -56,6 +56,8 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
|
|
|
56
56
|
const handleFormSubmit = async (data: CervicalContractionsFormData) => {
|
|
57
57
|
clearErrors();
|
|
58
58
|
let hasErrors = false;
|
|
59
|
+
|
|
60
|
+
// Validate contraction level
|
|
59
61
|
if (!data.contractionLevel || data.contractionLevel.trim() === '') {
|
|
60
62
|
setError('contractionLevel', {
|
|
61
63
|
type: 'manual',
|
|
@@ -63,15 +65,58 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
|
|
|
63
65
|
});
|
|
64
66
|
hasErrors = true;
|
|
65
67
|
}
|
|
68
|
+
|
|
69
|
+
// Validate contraction count
|
|
66
70
|
if (!data.contractionCount || data.contractionCount.trim() === '') {
|
|
67
71
|
setError('contractionCount', {
|
|
68
72
|
type: 'manual',
|
|
69
73
|
message: t('contractionCountRequired', 'Please select number of contractions'),
|
|
70
74
|
});
|
|
71
75
|
hasErrors = true;
|
|
76
|
+
} else {
|
|
77
|
+
const countValue = parseInt(data.contractionCount);
|
|
78
|
+
if (isNaN(countValue) || countValue < 1 || countValue > 5) {
|
|
79
|
+
setError('contractionCount', {
|
|
80
|
+
type: 'manual',
|
|
81
|
+
message: t('contractionCountRange', 'Contraction count must be between 1 and 5'),
|
|
82
|
+
});
|
|
83
|
+
hasErrors = true;
|
|
84
|
+
}
|
|
72
85
|
}
|
|
86
|
+
|
|
87
|
+
// Clinical validation warnings
|
|
88
|
+
if (!hasErrors) {
|
|
89
|
+
const countValue = parseInt(data.contractionCount);
|
|
90
|
+
|
|
91
|
+
// Warning for high contraction frequency
|
|
92
|
+
if (countValue >= 5) {
|
|
93
|
+
const proceedWithHighFrequency = window.confirm(
|
|
94
|
+
t(
|
|
95
|
+
'highContractionWarning',
|
|
96
|
+
'High contraction frequency (5 per 10 minutes) detected. This may indicate hyperstimulation. Do you want to proceed?',
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
if (!proceedWithHighFrequency) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Warning for strong contractions with high frequency
|
|
105
|
+
if (data.contractionLevel === 'strong' && countValue >= 4) {
|
|
106
|
+
const proceedWithIntensePattern = window.confirm(
|
|
107
|
+
t(
|
|
108
|
+
'intenseContractionWarning',
|
|
109
|
+
'Strong contractions with high frequency detected. This requires close monitoring. Do you want to proceed?',
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
if (!proceedWithIntensePattern) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
73
118
|
if (hasErrors) {
|
|
74
|
-
alert(t('formValidationError', 'Please
|
|
119
|
+
alert(t('formValidationError', 'Please correct the validation errors before submitting.'));
|
|
75
120
|
return;
|
|
76
121
|
}
|
|
77
122
|
const currentTime = new Date().toLocaleTimeString('en-GB', {
|
|
@@ -111,7 +156,7 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
|
|
|
111
156
|
preventCloseOnClickOutside={isSaving}>
|
|
112
157
|
<div className={styles.contractionsFormContainer} style={{ maxWidth: 600, margin: 0, padding: '0 8px' }}>
|
|
113
158
|
<h3 className={styles.sectionTitle} style={{ marginBottom: 0 }}>
|
|
114
|
-
{t('cervicalContractionsData', '
|
|
159
|
+
{t('cervicalContractionsData', 'Contractions')}
|
|
115
160
|
</h3>
|
|
116
161
|
|
|
117
162
|
<Controller
|
|
@@ -162,31 +207,21 @@ const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
|
|
|
162
207
|
rules={{ required: t('contractionCountRequired', 'Please select number of contractions') }}
|
|
163
208
|
render={({ field, fieldState }) => (
|
|
164
209
|
<>
|
|
165
|
-
<
|
|
166
|
-
id="contraction-count-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
id: field.value,
|
|
181
|
-
text: `${field.value} contraction${field.value === '1' ? '' : 's'}`,
|
|
182
|
-
}
|
|
183
|
-
: null
|
|
184
|
-
}
|
|
185
|
-
onChange={({ selectedItem }) => field.onChange(selectedItem?.id || '')}
|
|
186
|
-
className={styles.contractionCountDropdown}
|
|
187
|
-
style={{ minWidth: 280, borderRadius: 24, background: '#eee', fontWeight: 600 }}
|
|
188
|
-
/>
|
|
189
|
-
{fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
|
|
210
|
+
<Select
|
|
211
|
+
id="contraction-count-select"
|
|
212
|
+
value={field.value}
|
|
213
|
+
onChange={(e) => field.onChange(e.target.value)}
|
|
214
|
+
invalid={!!fieldState.error}
|
|
215
|
+
invalidText={fieldState.error?.message}
|
|
216
|
+
style={{ minWidth: 280 }}
|
|
217
|
+
helperText={t('contractionCountHelper', 'Normal range: 2-4 contractions per 10 minutes')}>
|
|
218
|
+
<SelectItem value="" text={t('chooseAnOption', 'Choose an option')} />
|
|
219
|
+
<SelectItem value="1" text={t('oneContraction', '1 contraction')} />
|
|
220
|
+
<SelectItem value="2" text={t('twoContractions', '2 contractions')} />
|
|
221
|
+
<SelectItem value="3" text={t('threeContractions', '3 contractions')} />
|
|
222
|
+
<SelectItem value="4" text={t('fourContractions', '4 contractions')} />
|
|
223
|
+
<SelectItem value="5" text={t('fiveContractions', '5 contractions (High - Monitor closely)')} />
|
|
224
|
+
</Select>
|
|
190
225
|
</>
|
|
191
226
|
)}
|
|
192
227
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo, useEffect, useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { useForm, Controller } from 'react-hook-form';
|
|
4
4
|
import { Button, Modal, Grid, Column, NumberInput, Select, SelectItem } from '@carbon/react';
|
|
@@ -40,7 +40,14 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
40
40
|
}) => {
|
|
41
41
|
const { t } = useTranslation();
|
|
42
42
|
|
|
43
|
-
const {
|
|
43
|
+
const {
|
|
44
|
+
control,
|
|
45
|
+
handleSubmit,
|
|
46
|
+
reset,
|
|
47
|
+
setError,
|
|
48
|
+
clearErrors,
|
|
49
|
+
formState: { errors },
|
|
50
|
+
} = useForm<CervixFormData>({
|
|
44
51
|
defaultValues: {
|
|
45
52
|
hour: '',
|
|
46
53
|
time: '',
|
|
@@ -86,37 +93,39 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
86
93
|
});
|
|
87
94
|
}, [usedHours]);
|
|
88
95
|
|
|
96
|
+
// Clear any errors when form opens
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (isOpen) {
|
|
99
|
+
reset({
|
|
100
|
+
hour: '',
|
|
101
|
+
time: '',
|
|
102
|
+
cervicalDilation: '',
|
|
103
|
+
descent: '',
|
|
104
|
+
});
|
|
105
|
+
clearErrors();
|
|
106
|
+
}
|
|
107
|
+
}, [isOpen, clearErrors, reset]);
|
|
89
108
|
const onSubmitForm = async (data: CervixFormData) => {
|
|
109
|
+
clearErrors();
|
|
110
|
+
|
|
111
|
+
// Basic validation
|
|
90
112
|
if (!data.hour || data.hour === '') {
|
|
91
|
-
setError('hour', {
|
|
92
|
-
type: 'manual',
|
|
93
|
-
message: 'Hour selection is required',
|
|
94
|
-
});
|
|
113
|
+
setError('hour', { type: 'manual', message: 'Hour selection is required' });
|
|
95
114
|
return;
|
|
96
115
|
}
|
|
97
116
|
|
|
98
117
|
if (!data.time || data.time === '') {
|
|
99
|
-
setError('time', {
|
|
100
|
-
type: 'manual',
|
|
101
|
-
message: 'Time selection is required',
|
|
102
|
-
});
|
|
103
|
-
console.warn('[CervixForm] Attempted to submit with empty time value:', data);
|
|
118
|
+
setError('time', { type: 'manual', message: 'Time selection is required' });
|
|
104
119
|
return;
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
if (!data.cervicalDilation || data.cervicalDilation === '') {
|
|
108
|
-
setError('cervicalDilation', {
|
|
109
|
-
type: 'manual',
|
|
110
|
-
message: 'Cervical dilation is required',
|
|
111
|
-
});
|
|
123
|
+
setError('cervicalDilation', { type: 'manual', message: 'Cervical dilation is required' });
|
|
112
124
|
return;
|
|
113
125
|
}
|
|
114
126
|
|
|
115
127
|
if (!data.descent || data.descent === '') {
|
|
116
|
-
setError('descent', {
|
|
117
|
-
type: 'manual',
|
|
118
|
-
message: 'Descent of head is required',
|
|
119
|
-
});
|
|
128
|
+
setError('descent', { type: 'manual', message: 'Descent of head is required' });
|
|
120
129
|
return;
|
|
121
130
|
}
|
|
122
131
|
|
|
@@ -125,26 +134,17 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
125
134
|
const descentOfHead = parseInt(data.descent);
|
|
126
135
|
|
|
127
136
|
if (isNaN(hourValue)) {
|
|
128
|
-
setError('hour', {
|
|
129
|
-
type: 'manual',
|
|
130
|
-
message: 'Invalid hour value',
|
|
131
|
-
});
|
|
137
|
+
setError('hour', { type: 'manual', message: 'Invalid hour value' });
|
|
132
138
|
return;
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
if (isNaN(cervicalDilation)) {
|
|
136
|
-
setError('cervicalDilation', {
|
|
137
|
-
type: 'manual',
|
|
138
|
-
message: 'Invalid cervical dilation value',
|
|
139
|
-
});
|
|
142
|
+
setError('cervicalDilation', { type: 'manual', message: 'Invalid cervical dilation value' });
|
|
140
143
|
return;
|
|
141
144
|
}
|
|
142
145
|
|
|
143
146
|
if (isNaN(descentOfHead)) {
|
|
144
|
-
setError('descent', {
|
|
145
|
-
type: 'manual',
|
|
146
|
-
message: 'Invalid descent of head value',
|
|
147
|
-
});
|
|
147
|
+
setError('descent', { type: 'manual', message: 'Invalid descent of head value' });
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -157,33 +157,21 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
if (cervicalDilation > 10) {
|
|
160
|
-
setError('cervicalDilation', {
|
|
161
|
-
type: 'manual',
|
|
162
|
-
message: 'Cervical dilation cannot exceed 10cm',
|
|
163
|
-
});
|
|
160
|
+
setError('cervicalDilation', { type: 'manual', message: 'Cervical dilation cannot exceed 10cm' });
|
|
164
161
|
return;
|
|
165
162
|
}
|
|
166
163
|
|
|
167
164
|
if (descentOfHead < 1) {
|
|
168
|
-
setError('descent', {
|
|
169
|
-
type: 'manual',
|
|
170
|
-
message: 'Descent of head cannot be less than 1 (most descended)',
|
|
171
|
-
});
|
|
165
|
+
setError('descent', { type: 'manual', message: 'Descent of head cannot be less than 1 (most descended)' });
|
|
172
166
|
return;
|
|
173
167
|
}
|
|
168
|
+
|
|
174
169
|
if (descentOfHead > 5) {
|
|
175
|
-
setError('descent', {
|
|
176
|
-
type: 'manual',
|
|
177
|
-
message: 'Descent of head cannot exceed 5',
|
|
178
|
-
});
|
|
170
|
+
setError('descent', { type: 'manual', message: 'Descent of head cannot exceed 5' });
|
|
179
171
|
return;
|
|
180
172
|
}
|
|
181
173
|
|
|
182
|
-
|
|
183
|
-
if (!data.time || data.time.trim() === '') {
|
|
184
|
-
alert('Time cannot be empty. Please select a valid time.');
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
174
|
+
// All validation passed, submit the form
|
|
187
175
|
onSubmit({
|
|
188
176
|
hour: hourValue,
|
|
189
177
|
time: data.time,
|
|
@@ -197,6 +185,7 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
197
185
|
|
|
198
186
|
const handleClose = () => {
|
|
199
187
|
reset();
|
|
188
|
+
clearErrors();
|
|
200
189
|
onClose();
|
|
201
190
|
};
|
|
202
191
|
|
|
@@ -225,9 +214,6 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
225
214
|
<Controller
|
|
226
215
|
name="hour"
|
|
227
216
|
control={control}
|
|
228
|
-
rules={{
|
|
229
|
-
required: 'Hour selection is required',
|
|
230
|
-
}}
|
|
231
217
|
render={({ field, fieldState }) => (
|
|
232
218
|
<Select
|
|
233
219
|
id="hour-select"
|
|
@@ -248,9 +234,6 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
248
234
|
<Controller
|
|
249
235
|
name="time"
|
|
250
236
|
control={control}
|
|
251
|
-
rules={{
|
|
252
|
-
required: 'Time selection is required',
|
|
253
|
-
}}
|
|
254
237
|
render={({ field, fieldState }) => (
|
|
255
238
|
<TimePickerDropdown
|
|
256
239
|
id="time-input"
|
|
@@ -269,40 +252,20 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
269
252
|
<Controller
|
|
270
253
|
name="cervicalDilation"
|
|
271
254
|
control={control}
|
|
272
|
-
rules={{
|
|
273
|
-
required: 'Cervical dilation is required',
|
|
274
|
-
validate: {
|
|
275
|
-
isNumber: (value) => !isNaN(parseFloat(value)) || 'Must be a valid number',
|
|
276
|
-
minValue: (value) => {
|
|
277
|
-
const numValue = parseFloat(value);
|
|
278
|
-
return (
|
|
279
|
-
numValue >= validationLimits.cervicalDilationMin ||
|
|
280
|
-
`Cannot be less than previous measurement (${validationLimits.cervicalDilationMin}cm)`
|
|
281
|
-
);
|
|
282
|
-
},
|
|
283
|
-
maxValue: (value) => {
|
|
284
|
-
const numValue = parseFloat(value);
|
|
285
|
-
return numValue <= 10 || 'Cannot exceed 10cm';
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
}}
|
|
289
255
|
render={({ field, fieldState }) => (
|
|
290
256
|
<>
|
|
291
257
|
<NumberInput
|
|
292
258
|
id="cervical-dilation-input"
|
|
293
259
|
label="Cervical Dilation (cm) *"
|
|
294
260
|
placeholder="Enter dilation (min: 4cm, max: 10cm)"
|
|
295
|
-
value={field.value || ''}
|
|
296
|
-
onChange={(e, { value }) => {
|
|
297
|
-
// Only allow whole numbers
|
|
298
|
-
const intValue = String(value).replace(/[^\d]/g, '');
|
|
299
|
-
field.onChange(intValue);
|
|
300
|
-
}}
|
|
301
261
|
min={4}
|
|
302
262
|
max={10}
|
|
303
263
|
step={1}
|
|
264
|
+
value={field.value || ''}
|
|
265
|
+
onChange={(e, { value }) => field.onChange(String(value))}
|
|
304
266
|
invalid={!!fieldState.error}
|
|
305
267
|
invalidText={fieldState.error?.message}
|
|
268
|
+
allowEmpty
|
|
306
269
|
/>
|
|
307
270
|
{existingCervixData.length > 0 && (
|
|
308
271
|
<div className={styles.validationHint}>
|
|
@@ -313,46 +276,27 @@ const CervixForm: React.FC<CervixFormProps> = ({
|
|
|
313
276
|
)}
|
|
314
277
|
/>
|
|
315
278
|
</Column>
|
|
316
|
-
|
|
317
279
|
<Column sm={4} md={8} lg={16}>
|
|
318
|
-
<
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
validate: {
|
|
324
|
-
isNumber: (value) => !isNaN(parseInt(value)) || 'Must be a valid number',
|
|
325
|
-
minValue: (value) => {
|
|
326
|
-
const numValue = parseInt(value);
|
|
327
|
-
return numValue >= 1 || 'Descent of head cannot be less than 1 (most descended)';
|
|
328
|
-
},
|
|
329
|
-
maxValue: (value) => {
|
|
330
|
-
const numValue = parseInt(value);
|
|
331
|
-
return numValue <= 5 || 'Descent of head cannot exceed 5';
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
}}
|
|
335
|
-
render={({ field, fieldState }) => (
|
|
336
|
-
<>
|
|
280
|
+
<div className={styles.formField}>
|
|
281
|
+
<Controller
|
|
282
|
+
name="descent"
|
|
283
|
+
control={control}
|
|
284
|
+
render={({ field, fieldState }) => (
|
|
337
285
|
<NumberInput
|
|
338
286
|
id="descent-input"
|
|
339
287
|
label="Descent of Head *"
|
|
340
|
-
|
|
341
|
-
existingCervixData.length === 0
|
|
342
|
-
? `Default: 5 (high position), can decrement to lower values`
|
|
343
|
-
: `Enter descent (1=most descended, 5=high position)`
|
|
344
|
-
}
|
|
345
|
-
value={field.value || ''}
|
|
346
|
-
onChange={(e, { value }) => field.onChange(String(value))}
|
|
347
|
-
min={1}
|
|
288
|
+
min={0}
|
|
348
289
|
max={5}
|
|
349
290
|
step={1}
|
|
291
|
+
value={field.value || ''}
|
|
292
|
+
onChange={(e, { value }) => field.onChange(String(value))}
|
|
350
293
|
invalid={!!fieldState.error}
|
|
351
294
|
invalidText={fieldState.error?.message}
|
|
295
|
+
allowEmpty
|
|
352
296
|
/>
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
297
|
+
)}
|
|
298
|
+
/>
|
|
299
|
+
</div>
|
|
356
300
|
</Column>
|
|
357
301
|
</Grid>
|
|
358
302
|
</div>
|