@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2716 → 5.4.2-pre.2722
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/805.js +1 -0
- package/dist/805.js.map +1 -0
- package/dist/kenyaemr-esm-patient-clinical-view-app.js +2 -2
- package/dist/kenyaemr-esm-patient-clinical-view-app.js.buildmanifest.json +27 -27
- package/dist/main.js +27 -27
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/config-schema.ts +97 -0
- package/src/contact-list/contact-tracing-history.component.tsx +18 -15
- package/src/maternal-and-child-health/partography/components/pulse-bp-graph.component.tsx +1 -0
- package/src/maternal-and-child-health/partography/components/temperature-graph.component.tsx +218 -0
- package/src/maternal-and-child-health/partography/components/uterine-contractions-graph.component.tsx +209 -0
- package/src/maternal-and-child-health/partography/forms/cervical-contractions-form.component.tsx +211 -0
- package/src/maternal-and-child-health/partography/forms/cervix-form.component.tsx +354 -0
- package/src/maternal-and-child-health/partography/forms/drugs-iv-fluids-form.component.tsx +321 -0
- package/src/maternal-and-child-health/partography/forms/fetal-heart-rate-form.component.tsx +275 -0
- package/src/maternal-and-child-health/partography/forms/index.ts +9 -0
- package/src/maternal-and-child-health/partography/forms/membrane-amniotic-fluid-form.component.tsx +330 -0
- package/src/maternal-and-child-health/partography/forms/oxytocin-form.component.tsx +207 -0
- package/src/maternal-and-child-health/partography/forms/pulse-bp-form.component.tsx +174 -0
- package/src/maternal-and-child-health/partography/forms/temperature-form.component.tsx +210 -0
- package/src/maternal-and-child-health/partography/forms/time-picker-dropdown.component.tsx +218 -0
- package/src/maternal-and-child-health/partography/forms/time-picker-dropdown.scss +107 -0
- package/src/maternal-and-child-health/partography/forms/time-picker-with-clock.component.tsx +174 -0
- package/src/maternal-and-child-health/partography/forms/time-picker-with-clock.scss +178 -0
- package/src/maternal-and-child-health/partography/forms/urine-test-form.component.tsx +255 -0
- package/src/maternal-and-child-health/partography/forms/useCervixData.ts +16 -0
- package/src/maternal-and-child-health/partography/graphs/cervical-contractions-graph.component.tsx +266 -0
- package/src/maternal-and-child-health/partography/graphs/cervix-graph.component.tsx +429 -0
- package/src/maternal-and-child-health/partography/graphs/drugs-iv-fluids-graph-wrapper.component.tsx +163 -0
- package/src/maternal-and-child-health/partography/graphs/drugs-iv-fluids-graph.component.tsx +82 -0
- package/src/maternal-and-child-health/partography/graphs/fetal-heart-rate-graph.component.tsx +359 -0
- package/src/maternal-and-child-health/partography/graphs/index.ts +10 -0
- package/src/maternal-and-child-health/partography/graphs/membrane-amniotic-fluid-graph.component.tsx +266 -0
- package/src/maternal-and-child-health/partography/graphs/oxytocin-graph-wrapper.component.tsx +190 -0
- package/src/maternal-and-child-health/partography/graphs/oxytocin-graph.component.tsx +126 -0
- package/src/maternal-and-child-health/partography/graphs/partograph-graph.component.tsx +266 -0
- package/src/maternal-and-child-health/partography/graphs/pulse-bp-graph-wrapper.component.tsx +298 -0
- package/src/maternal-and-child-health/partography/graphs/pulse-bp-graph.component.tsx +267 -0
- package/src/maternal-and-child-health/partography/graphs/temperature-graph.component.tsx +242 -0
- package/src/maternal-and-child-health/partography/graphs/urine-test-graph.component.tsx +246 -0
- package/src/maternal-and-child-health/partography/partograph.component.tsx +2141 -118
- package/src/maternal-and-child-health/partography/partography-dashboard.meta.ts +8 -0
- package/src/maternal-and-child-health/partography/partography-data-form.scss +163 -0
- package/src/maternal-and-child-health/partography/partography.resource.ts +233 -326
- package/src/maternal-and-child-health/partography/partography.scss +1341 -3
- package/src/maternal-and-child-health/partography/resources/blood-pressure.resource.ts +96 -0
- package/src/maternal-and-child-health/partography/resources/cervical-dilation.resource.ts +109 -0
- package/src/maternal-and-child-health/partography/resources/cervix.resource.ts +362 -0
- package/src/maternal-and-child-health/partography/resources/descent-of-head.resource.ts +101 -0
- package/src/maternal-and-child-health/partography/resources/drugs-fluids.resource.ts +88 -0
- package/src/maternal-and-child-health/partography/resources/fetal-heart-rate.resource.ts +122 -0
- package/src/maternal-and-child-health/partography/resources/maternal-pulse.resource.ts +77 -0
- package/src/maternal-and-child-health/partography/resources/membrane-amniotic-fluid.resource.ts +108 -0
- package/src/maternal-and-child-health/partography/resources/oxytocin.resource.ts +159 -0
- package/src/maternal-and-child-health/partography/resources/progress-events.resource.ts +6 -0
- package/src/maternal-and-child-health/partography/resources/pulse-bp-combined.resource.ts +53 -0
- package/src/maternal-and-child-health/partography/resources/temperature.resource.ts +84 -0
- package/src/maternal-and-child-health/partography/resources/uterine-contractions.resource.ts +173 -0
- package/src/maternal-and-child-health/partography/table/temperature-table.component.tsx +99 -0
- package/src/maternal-and-child-health/partography/table/uterine-contractions-table.component.tsx +86 -0
- package/src/maternal-and-child-health/partography/types/index.ts +319 -101
- package/dist/397.js +0 -1
- package/dist/397.js.map +0 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button, SkeletonText } from '@carbon/react';
|
|
4
|
+
import { Add, ChartColumn, Table as TableIcon } from '@carbon/react/icons';
|
|
5
|
+
import styles from '../partography.scss';
|
|
6
|
+
import UterineContractionsTable from '../table/uterine-contractions-table.component';
|
|
7
|
+
|
|
8
|
+
interface UterineContractionsTableRow {
|
|
9
|
+
id: string;
|
|
10
|
+
date: string;
|
|
11
|
+
timeSlot: string;
|
|
12
|
+
contractionCount: string;
|
|
13
|
+
contractionLevel: string;
|
|
14
|
+
protein?: string;
|
|
15
|
+
acetone?: string;
|
|
16
|
+
volume?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface UterineContractionsGraphProps {
|
|
20
|
+
tableData: UterineContractionsTableRow[];
|
|
21
|
+
viewMode: 'graph' | 'table';
|
|
22
|
+
currentPage: number;
|
|
23
|
+
pageSize: number;
|
|
24
|
+
totalItems: number;
|
|
25
|
+
controlSize: 'sm' | 'md';
|
|
26
|
+
onPageChange: (page: number) => void;
|
|
27
|
+
onPageSizeChange: (size: number) => void;
|
|
28
|
+
onAddData?: () => void;
|
|
29
|
+
onViewModeChange?: (mode: 'graph' | 'table') => void;
|
|
30
|
+
isAddButtonDisabled?: boolean;
|
|
31
|
+
isLoading?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const UterineContractionsGraph: React.FC<UterineContractionsGraphProps> = ({
|
|
35
|
+
tableData,
|
|
36
|
+
viewMode,
|
|
37
|
+
currentPage,
|
|
38
|
+
pageSize,
|
|
39
|
+
totalItems,
|
|
40
|
+
controlSize,
|
|
41
|
+
onPageChange,
|
|
42
|
+
onPageSizeChange,
|
|
43
|
+
onAddData,
|
|
44
|
+
onViewModeChange,
|
|
45
|
+
isAddButtonDisabled = false,
|
|
46
|
+
isLoading = false,
|
|
47
|
+
}) => {
|
|
48
|
+
const { t } = useTranslation();
|
|
49
|
+
|
|
50
|
+
// Only show rows with both date and timeSlot
|
|
51
|
+
const filteredTableData = tableData.filter((item) => item.date && item.timeSlot);
|
|
52
|
+
const timeColumns = filteredTableData.map((item) => item.timeSlot || '--');
|
|
53
|
+
const yAxisLabels = ['5', '4', '3', '2', '1'];
|
|
54
|
+
|
|
55
|
+
// Carbon skeleton for loading state
|
|
56
|
+
const renderSkeleton = () => (
|
|
57
|
+
<div className={styles.membraneGrid}>
|
|
58
|
+
<div className={styles.gridContainer}>
|
|
59
|
+
<div className={styles.gridHeader}>
|
|
60
|
+
<div className={styles.gridCell}>
|
|
61
|
+
<SkeletonText width="60px" />
|
|
62
|
+
</div>
|
|
63
|
+
{[...Array(6)].map((_, idx) => (
|
|
64
|
+
<div key={idx} className={styles.gridCell}>
|
|
65
|
+
<SkeletonText width="60px" />
|
|
66
|
+
</div>
|
|
67
|
+
))}
|
|
68
|
+
</div>
|
|
69
|
+
<div className={styles.gridRow}>
|
|
70
|
+
<div className={styles.gridRowLabel}>
|
|
71
|
+
<SkeletonText width="80px" />
|
|
72
|
+
</div>
|
|
73
|
+
{[...Array(6)].map((_, idx) => (
|
|
74
|
+
<div key={idx} className={styles.gridCell}>
|
|
75
|
+
<SkeletonText width="40px" />
|
|
76
|
+
</div>
|
|
77
|
+
))}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Empty state for no data
|
|
84
|
+
const renderEmptyGraph = () => (
|
|
85
|
+
<div className={styles.membraneGrid}>
|
|
86
|
+
<div className={styles.gridContainer}>
|
|
87
|
+
<div className={styles.gridHeader}>
|
|
88
|
+
<div className={styles.gridCell}>{t('time', 'Time')}</div>
|
|
89
|
+
{[...Array(6)].map((_, idx) => (
|
|
90
|
+
<div key={idx} className={styles.gridCell}>
|
|
91
|
+
--
|
|
92
|
+
</div>
|
|
93
|
+
))}
|
|
94
|
+
</div>
|
|
95
|
+
<div className={styles.gridRow}>
|
|
96
|
+
<div className={styles.gridRowLabel}>{t('contractions', 'Contractions')}</div>
|
|
97
|
+
{[...Array(6)].map((_, idx) => (
|
|
98
|
+
<div key={idx} className={styles.gridCell}>
|
|
99
|
+
--
|
|
100
|
+
</div>
|
|
101
|
+
))}
|
|
102
|
+
</div>
|
|
103
|
+
<div style={{ textAlign: 'center', marginTop: '2rem', width: '100%' }}>
|
|
104
|
+
<p>{t('noContractionData', 'No contraction data available')}</p>
|
|
105
|
+
<Button kind="primary" size={controlSize} renderIcon={Add} onClick={onAddData}>
|
|
106
|
+
{t('addFirstDataPoint', 'Add first data point')}
|
|
107
|
+
</Button>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div className={styles.fetalHeartRateSection}>
|
|
115
|
+
<div className={styles.fetalHeartRateContainer}>
|
|
116
|
+
<div className={styles.fetalHeartRateHeader}>
|
|
117
|
+
<div className={styles.fetalHeartRateHeaderLeft}>
|
|
118
|
+
<h3 className={styles.fetalHeartRateTitle}>Uterine Contractions</h3>
|
|
119
|
+
<div className={styles.fetalHeartRateControls}>
|
|
120
|
+
<span className={styles.legendText}>
|
|
121
|
+
Contractions per 10 min | Bar Heights: 0=None, 2=Mild, 3=Moderate, 5=Strong
|
|
122
|
+
</span>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
<div className={styles.fetalHeartRateHeaderRight}>
|
|
126
|
+
<div className={styles.fetalHeartRateActions}>
|
|
127
|
+
<div className={styles.viewSwitcher}>
|
|
128
|
+
<Button
|
|
129
|
+
kind={viewMode === 'graph' ? 'primary' : 'secondary'}
|
|
130
|
+
size={controlSize}
|
|
131
|
+
hasIconOnly
|
|
132
|
+
iconDescription={t('graphView', 'Graph View')}
|
|
133
|
+
onClick={() => onViewModeChange?.('graph')}
|
|
134
|
+
className={styles.viewButton}>
|
|
135
|
+
<ChartColumn />
|
|
136
|
+
</Button>
|
|
137
|
+
<Button
|
|
138
|
+
kind={viewMode === 'table' ? 'primary' : 'secondary'}
|
|
139
|
+
size={controlSize}
|
|
140
|
+
hasIconOnly
|
|
141
|
+
iconDescription={t('tableView', 'Table View')}
|
|
142
|
+
onClick={() => onViewModeChange?.('table')}
|
|
143
|
+
className={styles.viewButton}>
|
|
144
|
+
<TableIcon />
|
|
145
|
+
</Button>
|
|
146
|
+
</div>
|
|
147
|
+
<Button
|
|
148
|
+
kind="primary"
|
|
149
|
+
size={controlSize}
|
|
150
|
+
renderIcon={Add}
|
|
151
|
+
iconDescription="Add uterine contractions data"
|
|
152
|
+
disabled={isAddButtonDisabled}
|
|
153
|
+
onClick={onAddData}
|
|
154
|
+
className={styles.addButton}>
|
|
155
|
+
Add
|
|
156
|
+
</Button>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
{viewMode === 'graph' ? (
|
|
161
|
+
isLoading ? (
|
|
162
|
+
renderSkeleton()
|
|
163
|
+
) : filteredTableData.length === 0 ? (
|
|
164
|
+
renderEmptyGraph()
|
|
165
|
+
) : (
|
|
166
|
+
<div className={styles.membraneGrid}>
|
|
167
|
+
<div className={styles.gridContainer}>
|
|
168
|
+
{/* Header row with time columns */}
|
|
169
|
+
<div className={styles.gridHeader}>
|
|
170
|
+
<div className={styles.gridCell}>{t('time', 'Time')}</div>
|
|
171
|
+
{timeColumns.map((timeColumn, idx) => (
|
|
172
|
+
<div key={idx} className={styles.gridCell}>
|
|
173
|
+
{timeColumn}
|
|
174
|
+
</div>
|
|
175
|
+
))}
|
|
176
|
+
</div>
|
|
177
|
+
{/* Contractions row */}
|
|
178
|
+
<div className={styles.gridRow}>
|
|
179
|
+
<div className={styles.gridRowLabel}>{t('contractions', 'Contractions')}</div>
|
|
180
|
+
{filteredTableData.map((item, idx) => (
|
|
181
|
+
<div key={`contraction-${idx}`} className={styles.gridCell}>
|
|
182
|
+
{item.contractionCount !== undefined && item.contractionCount !== null
|
|
183
|
+
? item.contractionCount
|
|
184
|
+
: '--'}
|
|
185
|
+
</div>
|
|
186
|
+
))}
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
)
|
|
191
|
+
) : (
|
|
192
|
+
<div className={styles.tableContainer}>
|
|
193
|
+
<UterineContractionsTable
|
|
194
|
+
tableData={filteredTableData}
|
|
195
|
+
currentPage={currentPage}
|
|
196
|
+
pageSize={pageSize}
|
|
197
|
+
totalItems={filteredTableData.length}
|
|
198
|
+
controlSize={controlSize}
|
|
199
|
+
onPageChange={onPageChange}
|
|
200
|
+
onPageSizeChange={onPageSizeChange}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export default UterineContractionsGraph;
|
package/src/maternal-and-child-health/partography/forms/cervical-contractions-form.component.tsx
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
4
|
+
import { Button, Modal, Grid, Column, Dropdown } from '@carbon/react';
|
|
5
|
+
import styles from '../partography.scss';
|
|
6
|
+
import { CONTRACTION_STRONG_UUID } from '../types';
|
|
7
|
+
import { MOULDING_NONE_CONCEPT, MOULDING_SLIGHT_CONCEPT, MOULDING_MODERATE_CONCEPT } from '../../../config-schema';
|
|
8
|
+
|
|
9
|
+
type CervicalContractionsFormData = {
|
|
10
|
+
contractionLevel: string;
|
|
11
|
+
contractionCount: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CervicalContractionsFormProps = {
|
|
15
|
+
isOpen: boolean;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
onSubmit: (data: { contractionLevel: string; contractionCount: string; timeSlot: string }) => void;
|
|
18
|
+
onDataSaved?: () => void;
|
|
19
|
+
patient?: {
|
|
20
|
+
uuid: string;
|
|
21
|
+
name: string;
|
|
22
|
+
gender: string;
|
|
23
|
+
age: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const CervicalContractionsForm: React.FC<CervicalContractionsFormProps> = ({
|
|
28
|
+
isOpen,
|
|
29
|
+
onClose,
|
|
30
|
+
onSubmit,
|
|
31
|
+
onDataSaved,
|
|
32
|
+
patient,
|
|
33
|
+
}) => {
|
|
34
|
+
const { t } = useTranslation();
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
control,
|
|
38
|
+
handleSubmit,
|
|
39
|
+
reset,
|
|
40
|
+
setError,
|
|
41
|
+
clearErrors,
|
|
42
|
+
formState: { errors },
|
|
43
|
+
} = useForm<CervicalContractionsFormData>({
|
|
44
|
+
defaultValues: {
|
|
45
|
+
contractionLevel: '',
|
|
46
|
+
contractionCount: '',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const contractionLevelOptions = useMemo(
|
|
51
|
+
() => [
|
|
52
|
+
{
|
|
53
|
+
value: 'none',
|
|
54
|
+
label: t('noContractions', 'No Contractions'),
|
|
55
|
+
concept: MOULDING_NONE_CONCEPT,
|
|
56
|
+
visual: '0',
|
|
57
|
+
visualClass: 'none',
|
|
58
|
+
title: t('none', 'None'),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
value: 'mild',
|
|
62
|
+
label: t('mildContractions', 'Mild Contractions'),
|
|
63
|
+
concept: MOULDING_SLIGHT_CONCEPT,
|
|
64
|
+
visual: '1',
|
|
65
|
+
visualClass: 'mild',
|
|
66
|
+
title: t('mild', 'Mild'),
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
value: 'moderate',
|
|
70
|
+
label: t('moderateContractions', 'Moderate Contractions'),
|
|
71
|
+
concept: MOULDING_MODERATE_CONCEPT,
|
|
72
|
+
visual: '2',
|
|
73
|
+
visualClass: 'moderate',
|
|
74
|
+
title: t('moderate', 'Moderate'),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: 'strong',
|
|
78
|
+
label: t('strongContractions', 'Strong Contractions'),
|
|
79
|
+
concept: CONTRACTION_STRONG_UUID,
|
|
80
|
+
visual: '3',
|
|
81
|
+
visualClass: 'strong',
|
|
82
|
+
title: 'Strong',
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
[t],
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const contractionCountItems = useMemo(
|
|
89
|
+
() => [
|
|
90
|
+
{ id: '1', text: t('oneContraction', '1 contraction') },
|
|
91
|
+
{ id: '2', text: t('twoContractions', '2 contractions') },
|
|
92
|
+
{ id: '3', text: t('threeContractions', '3 contractions') },
|
|
93
|
+
{ id: '4', text: t('fourContractions', '4 contractions') },
|
|
94
|
+
{ id: '5', text: t('fiveContractions', '5 contractions') },
|
|
95
|
+
],
|
|
96
|
+
[t],
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const handleFormSubmit = (data: CervicalContractionsFormData) => {
|
|
100
|
+
const currentTime = new Date().toLocaleTimeString('en-GB', {
|
|
101
|
+
hour: '2-digit',
|
|
102
|
+
minute: '2-digit',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
onSubmit({
|
|
106
|
+
contractionLevel: data.contractionLevel,
|
|
107
|
+
contractionCount: data.contractionCount,
|
|
108
|
+
timeSlot: currentTime,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
reset();
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const handleClose = () => {
|
|
115
|
+
reset();
|
|
116
|
+
clearErrors();
|
|
117
|
+
onClose();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<Modal
|
|
122
|
+
open={isOpen}
|
|
123
|
+
onRequestClose={handleClose}
|
|
124
|
+
primaryButtonText={t('save', 'Save')}
|
|
125
|
+
secondaryButtonText={t('cancel', 'Cancel')}
|
|
126
|
+
onRequestSubmit={handleSubmit(handleFormSubmit)}
|
|
127
|
+
onSecondarySubmit={handleClose}
|
|
128
|
+
className={styles.cervixModal}
|
|
129
|
+
size="lg">
|
|
130
|
+
<div className={styles.contractionsFormContainer}>
|
|
131
|
+
<div className={styles.formMainSection}>
|
|
132
|
+
<div className={styles.formSectionLeft}>
|
|
133
|
+
<h3 className={styles.sectionTitle}>{t('cervicalContractionsData', 'Cervical Contractions')}</h3>
|
|
134
|
+
<h4 className={styles.sectionTitle}>{t('contractionLevel', 'Select Contraction Level')}</h4>
|
|
135
|
+
<p className={styles.sectionDescription}>
|
|
136
|
+
{t('contractionLevelDescription', 'Choose the intensity of uterine contractions observed')}
|
|
137
|
+
</p>
|
|
138
|
+
|
|
139
|
+
<Controller
|
|
140
|
+
name="contractionLevel"
|
|
141
|
+
control={control}
|
|
142
|
+
rules={{ required: t('contractionLevelRequired', 'Please select contraction level') }}
|
|
143
|
+
render={({ field, fieldState }) => (
|
|
144
|
+
<>
|
|
145
|
+
<div className={styles.contractionLevelSelector}>
|
|
146
|
+
{contractionLevelOptions.map((option) => (
|
|
147
|
+
<div
|
|
148
|
+
key={option.value}
|
|
149
|
+
className={`${styles.contractionLevelOption} ${
|
|
150
|
+
field.value === option.value ? styles.contractionLevelSelected : ''
|
|
151
|
+
}`}
|
|
152
|
+
onClick={() => field.onChange(option.value)}
|
|
153
|
+
onKeyDown={(e) => {
|
|
154
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
field.onChange(option.value);
|
|
157
|
+
}
|
|
158
|
+
}}
|
|
159
|
+
role="button"
|
|
160
|
+
tabIndex={0}
|
|
161
|
+
aria-pressed={field.value === option.value}
|
|
162
|
+
title={option.label}>
|
|
163
|
+
<div className={styles.contractionLevelTitle}>{option.title}</div>
|
|
164
|
+
<div className={`${styles.contractionLevelButton} ${styles[option.visualClass]}`}>
|
|
165
|
+
{option.visual}
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
))}
|
|
169
|
+
</div>
|
|
170
|
+
{fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
|
|
171
|
+
</>
|
|
172
|
+
)}
|
|
173
|
+
/>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<div className={styles.formSectionRight}>
|
|
177
|
+
<Controller
|
|
178
|
+
name="contractionCount"
|
|
179
|
+
control={control}
|
|
180
|
+
rules={{ required: t('contractionCountRequired', 'Please select number of contractions') }}
|
|
181
|
+
render={({ field, fieldState }) => (
|
|
182
|
+
<>
|
|
183
|
+
<Dropdown
|
|
184
|
+
id="contraction-count-dropdown"
|
|
185
|
+
titleText={t('chooseCount', 'Number of Contractions')}
|
|
186
|
+
label={t('chooseCount', 'Choose count')}
|
|
187
|
+
items={contractionCountItems}
|
|
188
|
+
itemToString={(item) => (item ? item.text : '')}
|
|
189
|
+
selectedItem={
|
|
190
|
+
field.value
|
|
191
|
+
? {
|
|
192
|
+
id: field.value,
|
|
193
|
+
text: `${field.value} contraction${field.value === '1' ? '' : 's'}`,
|
|
194
|
+
}
|
|
195
|
+
: null
|
|
196
|
+
}
|
|
197
|
+
onChange={({ selectedItem }) => field.onChange(selectedItem?.id || '')}
|
|
198
|
+
className={styles.contractionCountDropdown}
|
|
199
|
+
/>
|
|
200
|
+
{fieldState.error && <div className={styles.errorMessage}>{fieldState.error.message}</div>}
|
|
201
|
+
</>
|
|
202
|
+
)}
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</Modal>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export default CervicalContractionsForm;
|