@openmrs/esm-fast-data-entry-app 1.0.1-pre.93 → 1.1.0

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.
Files changed (178) hide show
  1. package/__mocks__/react-i18next.js +9 -14
  2. package/dist/12.js +1 -0
  3. package/dist/12.js.map +1 -0
  4. package/dist/132.js +1 -1
  5. package/dist/151.js +2 -0
  6. package/dist/151.js.LICENSE.txt +5 -0
  7. package/dist/151.js.map +1 -0
  8. package/dist/195.js +1 -0
  9. package/dist/195.js.map +1 -0
  10. package/dist/197.js +1 -0
  11. package/dist/221.js +1 -0
  12. package/dist/221.js.map +1 -0
  13. package/dist/259.js +1 -0
  14. package/dist/259.js.map +1 -0
  15. package/dist/265.js +1 -0
  16. package/dist/265.js.map +1 -0
  17. package/dist/269.js +1 -0
  18. package/dist/269.js.map +1 -0
  19. package/dist/300.js +1 -0
  20. package/dist/335.js +1 -0
  21. package/dist/367.js +1 -0
  22. package/dist/367.js.map +1 -0
  23. package/dist/384.js +1 -0
  24. package/dist/384.js.map +1 -0
  25. package/dist/540.js +2 -0
  26. package/dist/540.js.map +1 -0
  27. package/dist/55.js +1 -0
  28. package/dist/579.js +1 -0
  29. package/dist/579.js.map +1 -0
  30. package/dist/595.js +1 -1
  31. package/dist/595.js.LICENSE.txt +34 -2
  32. package/dist/595.js.map +1 -0
  33. package/dist/602.js +1 -0
  34. package/dist/602.js.map +1 -0
  35. package/dist/616.js +1 -0
  36. package/dist/616.js.map +1 -0
  37. package/dist/626.js +2 -0
  38. package/dist/626.js.map +1 -0
  39. package/dist/652.js +1 -0
  40. package/dist/77.js +1 -0
  41. package/dist/77.js.map +1 -0
  42. package/dist/773.js +2 -0
  43. package/dist/{68.js.LICENSE.txt → 773.js.LICENSE.txt} +13 -2
  44. package/dist/773.js.map +1 -0
  45. package/dist/88.js +1 -0
  46. package/dist/88.js.map +1 -0
  47. package/dist/930.js +1 -0
  48. package/dist/930.js.map +1 -0
  49. package/dist/961.js +2 -0
  50. package/dist/961.js.map +1 -0
  51. package/dist/983.js +1 -0
  52. package/dist/983.js.map +1 -0
  53. package/dist/99.js +1 -0
  54. package/dist/main.js +1 -1
  55. package/dist/main.js.map +1 -0
  56. package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
  57. package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +380 -156
  58. package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -0
  59. package/dist/routes.json +1 -0
  60. package/jest.config.json +2 -1
  61. package/package.json +41 -35
  62. package/prettier.config.js +8 -0
  63. package/src/CancelModal.tsx +9 -15
  64. package/src/CompleteModal.tsx +7 -18
  65. package/src/FormBootstrap.tsx +31 -18
  66. package/src/Root.tsx +7 -12
  67. package/src/add-group-modal/AddGroupModal.tsx +73 -112
  68. package/src/add-group-modal/styles.scss +7 -3
  69. package/src/config-schema.ts +63 -24
  70. package/src/constant.ts +1 -1
  71. package/src/context/FormWorkflowContext.tsx +26 -39
  72. package/src/context/FormWorkflowReducer.ts +50 -74
  73. package/src/context/GroupFormWorkflowContext.tsx +40 -59
  74. package/src/context/GroupFormWorkflowReducer.ts +84 -109
  75. package/src/declarations.d.ts +3 -0
  76. package/src/empty-state/EmptyDataIllustration.tsx +4 -16
  77. package/src/empty-state/EmptyState.tsx +8 -13
  78. package/src/empty-state/styles.scss +14 -14
  79. package/src/form-entry-workflow/FormEntryWorkflow.tsx +43 -55
  80. package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +7 -7
  81. package/src/form-entry-workflow/form-review-card/index.ts +1 -1
  82. package/src/form-entry-workflow/form-review-card/styles.scss +9 -11
  83. package/src/form-entry-workflow/index.ts +1 -1
  84. package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +5 -5
  85. package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +14 -27
  86. package/src/form-entry-workflow/patient-banner/index.ts +1 -1
  87. package/src/form-entry-workflow/patient-banner/styles.scss +11 -12
  88. package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +19 -28
  89. package/src/form-entry-workflow/patient-search-header/index.ts +1 -1
  90. package/src/form-entry-workflow/patient-search-header/styles.scss +13 -10
  91. package/src/form-entry-workflow/styles.scss +11 -13
  92. package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +13 -11
  93. package/src/form-entry-workflow/workflow-review/index.ts +1 -1
  94. package/src/form-entry-workflow/workflow-review/styles.scss +0 -4
  95. package/src/forms-app-menu-link.tsx +4 -6
  96. package/src/forms-page/FormsPage.tsx +23 -51
  97. package/src/forms-page/forms-table/FormsTable.tsx +22 -42
  98. package/src/forms-page/forms-table/index.ts +1 -1
  99. package/src/forms-page/forms-table/styles.scss +4 -5
  100. package/src/forms-page/index.ts +1 -1
  101. package/src/forms-page/styles.scss +3 -5
  102. package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +9 -9
  103. package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +77 -117
  104. package/src/group-form-entry-workflow/SessionDetailsForm.tsx +73 -50
  105. package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +20 -28
  106. package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +15 -29
  107. package/src/group-form-entry-workflow/attendance-table/index.ts +1 -1
  108. package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +45 -0
  109. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +5 -5
  110. package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +13 -21
  111. package/src/group-form-entry-workflow/group-display-header/index.ts +1 -1
  112. package/src/group-form-entry-workflow/group-display-header/styles.scss +20 -20
  113. package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +24 -35
  114. package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +13 -15
  115. package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +22 -38
  116. package/src/group-form-entry-workflow/group-search/compact-group-result.scss +16 -17
  117. package/src/group-form-entry-workflow/group-search/compact-group-search.scss +7 -8
  118. package/src/group-form-entry-workflow/group-search/group-search.scss +20 -23
  119. package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +20 -21
  120. package/src/group-form-entry-workflow/group-search-header/index.ts +1 -1
  121. package/src/group-form-entry-workflow/group-search-header/styles.scss +8 -8
  122. package/src/group-form-entry-workflow/index.ts +1 -1
  123. package/src/group-form-entry-workflow/styles.scss +13 -16
  124. package/src/hooks/index.ts +7 -6
  125. package/src/hooks/useFormState.ts +3 -3
  126. package/src/hooks/useGetAllForms.ts +7 -15
  127. package/src/hooks/useGetEncounter.ts +3 -3
  128. package/src/hooks/useGetPatient.ts +2 -2
  129. package/src/hooks/useGetPatients.ts +4 -6
  130. package/src/hooks/useGetSystemSetting.ts +3 -5
  131. package/src/hooks/useKeyPress.ts +5 -5
  132. package/src/hooks/usePostEndpoint.ts +10 -10
  133. package/src/hooks/useSearchEndpoint.ts +23 -40
  134. package/src/hooks/useSpecificQuestions.ts +75 -0
  135. package/src/hooks/useStartVisit.ts +18 -28
  136. package/src/index.ts +12 -76
  137. package/src/patient-card/PatientCard.tsx +8 -20
  138. package/src/patient-card/index.ts +1 -1
  139. package/src/patient-card/styles.scss +2 -4
  140. package/src/routes.json +24 -0
  141. package/src/setup-tests.ts +1 -1
  142. package/src/types.ts +25 -0
  143. package/tools/i18next-parser.config.js +19 -19
  144. package/translations/am.json +75 -0
  145. package/translations/ar.json +75 -0
  146. package/translations/en.json +7 -1
  147. package/translations/es.json +75 -0
  148. package/translations/fr.json +33 -8
  149. package/translations/he.json +75 -0
  150. package/translations/km.json +75 -0
  151. package/tsconfig.json +2 -1
  152. package/turbo.json +18 -0
  153. package/webpack.config.js +1 -1
  154. package/dist/153.js +0 -1
  155. package/dist/229.js +0 -1
  156. package/dist/247.js +0 -1
  157. package/dist/255.js +0 -1
  158. package/dist/294.js +0 -2
  159. package/dist/32.js +0 -1
  160. package/dist/327.js +0 -1
  161. package/dist/571.js +0 -1
  162. package/dist/574.js +0 -1
  163. package/dist/617.js +0 -1
  164. package/dist/656.js +0 -2
  165. package/dist/658.js +0 -2
  166. package/dist/658.js.LICENSE.txt +0 -27
  167. package/dist/68.js +0 -2
  168. package/dist/74.js +0 -1
  169. package/dist/757.js +0 -1
  170. package/dist/776.js +0 -1
  171. package/dist/804.js +0 -1
  172. package/dist/820.js +0 -1
  173. package/dist/935.js +0 -2
  174. package/dist/openmrs-esm-fast-data-entry-app.old +0 -1
  175. package/src/declarations.d.tsx +0 -2
  176. /package/dist/{294.js.LICENSE.txt → 540.js.LICENSE.txt} +0 -0
  177. /package/dist/{656.js.LICENSE.txt → 626.js.LICENSE.txt} +0 -0
  178. /package/dist/{935.js.LICENSE.txt → 961.js.LICENSE.txt} +0 -0
@@ -1,20 +1,25 @@
1
- import {
2
- Layer,
3
- Tile,
4
- TextInput,
5
- TextArea,
6
- DatePicker,
7
- DatePickerInput,
8
- } from "@carbon/react";
9
- import React, { useContext } from "react";
10
- import styles from "./styles.scss";
11
- import { useTranslation } from "react-i18next";
12
- import { Controller, useFormContext } from "react-hook-form";
13
- import { AttendanceTable } from "./attendance-table";
14
- import GroupFormWorkflowContext from "../context/GroupFormWorkflowContext";
15
- import useGetPatients from "../hooks/useGetPatients";
1
+ import { Layer, Tile, TextInput, TextArea, DatePicker, DatePickerInput } from '@carbon/react';
2
+ import React, { useContext } from 'react';
3
+ import { useConfig } from '@openmrs/esm-framework';
4
+ import { useParams } from 'react-router-dom';
5
+ import styles from './styles.scss';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Controller, useFormContext } from 'react-hook-form';
8
+ import { AttendanceTable } from './attendance-table';
9
+ import GroupFormWorkflowContext from '../context/GroupFormWorkflowContext';
10
+ import useGetPatients from '../hooks/useGetPatients';
11
+ import ConfigurableQuestionsSection from './configurable-questions/ConfigurableQuestionsSection';
12
+ import useSpecificQuestions from '../hooks/useSpecificQuestions';
13
+
14
+ interface ParamTypes {
15
+ formUuid?: string;
16
+ }
16
17
 
17
18
  const SessionDetailsForm = () => {
19
+ const { specificQuestions } = useConfig();
20
+ const { formUuid } = useParams() as ParamTypes;
21
+ const { questions } = useSpecificQuestions(formUuid, specificQuestions);
22
+
18
23
  const { t } = useTranslation();
19
24
  const {
20
25
  register,
@@ -22,66 +27,56 @@ const SessionDetailsForm = () => {
22
27
  control,
23
28
  } = useFormContext();
24
29
 
25
- const { patientUuids } = useContext(GroupFormWorkflowContext);
26
- const { patients, isLoading } = useGetPatients(patientUuids);
30
+ const { activeGroupMembers } = useContext(GroupFormWorkflowContext);
31
+ const { patients, isLoading } = useGetPatients(activeGroupMembers);
27
32
 
28
33
  return (
29
34
  <div>
30
35
  {!isLoading && (
31
36
  <div className={styles.formSection}>
32
- <h4>{t("sessionDetails", "1. Session details")}</h4>
37
+ <h4>{t('sessionDetails', '1. Session details')}</h4>
33
38
  <div>
34
- <p>
35
- {t(
36
- "allFieldsRequired",
37
- "All fields are required unless marked optional"
38
- )}
39
- </p>
39
+ <p>{t('allFieldsRequired', 'All fields are required unless marked optional')}</p>
40
40
  </div>
41
41
  <Layer>
42
42
  <Tile className={styles.formSectionTile}>
43
43
  <Layer>
44
44
  <div
45
45
  style={{
46
- display: "flex",
47
- flexDirection: "column",
48
- rowGap: "1.5rem",
46
+ display: 'flex',
47
+ flexDirection: 'column',
48
+ rowGap: '1.5rem',
49
49
  }}
50
50
  >
51
51
  <TextInput
52
52
  id="text"
53
53
  type="text"
54
- labelText={t("sessionName", "Session Name")}
55
- {...register("sessionName", { required: true })}
54
+ labelText={t('sessionName', 'Session Name')}
55
+ {...register('sessionName', { required: true })}
56
56
  invalid={errors.sessionName}
57
- invalidText={"This field is required"}
57
+ invalidText={t('requiredField', 'This field is required')}
58
58
  />
59
59
  <TextInput
60
60
  id="text"
61
61
  type="text"
62
- labelText={t("practitionerName", "Practitioner Name")}
63
- {...register("practitionerName", { required: true })}
62
+ labelText={t('practitionerName', 'Practitioner Name')}
63
+ {...register('practitionerName', { required: true })}
64
64
  invalid={errors.practitionerName}
65
- invalidText={"This field is required"}
65
+ invalidText={t('requiredField', 'This field is required')}
66
66
  />
67
67
  <Controller
68
68
  name="sessionDate"
69
69
  control={control}
70
70
  rules={{ required: true }}
71
71
  render={({ field }) => (
72
- <DatePicker
73
- datePickerType="single"
74
- size="md"
75
- maxDate={new Date()}
76
- {...field}
77
- >
72
+ <DatePicker datePickerType="single" size="md" maxDate={new Date()} {...field}>
78
73
  <DatePickerInput
79
74
  id="session-date"
80
- labelText={t("sessionDate", "Session Date")}
75
+ labelText={t('sessionDate', 'Session Date')}
81
76
  placeholder="mm/dd/yyyy"
82
77
  size="md"
83
78
  invalid={errors.sessionDate}
84
- invalidText={"This field is required"}
79
+ invalidText={t('requiredField', 'This field is required')}
85
80
  />
86
81
  </DatePicker>
87
82
  )}
@@ -89,21 +84,21 @@ const SessionDetailsForm = () => {
89
84
  <TextArea
90
85
  id="text"
91
86
  type="text"
92
- labelText={t("sessionNotes", "Session Notes")}
93
- {...register("sessionNotes", { required: true })}
87
+ labelText={t('sessionNotes', 'Session Notes')}
88
+ {...register('sessionNotes', { required: true })}
94
89
  invalid={errors.sessionNotes}
95
- invalidText={"This field is required"}
90
+ invalidText={t('requiredField', 'This field is required')}
96
91
  />
97
92
  </div>
98
93
  </Layer>
99
94
  </Tile>
100
95
  </Layer>
101
- <h4>{t("sessionParticipants", "2. Session participants")}</h4>
96
+ <h4>{t('sessionParticipants', '2. Session participants')}</h4>
102
97
  <div>
103
98
  <p>
104
99
  {t(
105
- "markAbsentPatients",
106
- "The patients in this group. Patients that are not present in the session should be marked as absent."
100
+ 'markAbsentPatients',
101
+ 'The patients in this group. Patients that are not present in the session should be marked as absent.',
107
102
  )}
108
103
  </p>
109
104
  </div>
@@ -112,9 +107,9 @@ const SessionDetailsForm = () => {
112
107
  <Layer>
113
108
  <div
114
109
  style={{
115
- display: "flex",
116
- flexDirection: "column",
117
- rowGap: "1.5rem",
110
+ display: 'flex',
111
+ flexDirection: 'column',
112
+ rowGap: '1.5rem',
118
113
  }}
119
114
  >
120
115
  <AttendanceTable patients={patients} />
@@ -122,6 +117,34 @@ const SessionDetailsForm = () => {
122
117
  </Layer>
123
118
  </Tile>
124
119
  </Layer>
120
+ {questions?.length > 0 ? (
121
+ <>
122
+ <h4>{t('sessionSpecificDetails', '3. Specific details')}</h4>
123
+ <div>
124
+ <p>
125
+ {t(
126
+ 'sessionSpecificDetailsDescription',
127
+ 'They will be mapped to form responses for all patients as pre-filled data.',
128
+ )}
129
+ </p>
130
+ </div>
131
+ <Layer>
132
+ <Tile className={styles.formSectionTile}>
133
+ <Layer>
134
+ <div
135
+ style={{
136
+ display: 'flex',
137
+ flexDirection: 'column',
138
+ rowGap: '1.5rem',
139
+ }}
140
+ >
141
+ <ConfigurableQuestionsSection register={register} specificQuestions={questions} />
142
+ </div>
143
+ </Layer>
144
+ </Tile>
145
+ </Layer>
146
+ </>
147
+ ) : null}
125
148
  </div>
126
149
  )}
127
150
  </div>
@@ -1,24 +1,24 @@
1
- import { Button } from "@carbon/react";
2
- import React, { useContext, useEffect, useState } from "react";
3
- import styles from "./styles.scss";
4
- import { useTranslation } from "react-i18next";
5
- import GroupFormWorkflowContext from "../context/GroupFormWorkflowContext";
6
- import { FormProvider, useForm, useFormContext } from "react-hook-form";
7
- import CancelModal from "../CancelModal";
8
- import SessionDetailsForm from "./SessionDetailsForm";
1
+ import { Button } from '@carbon/react';
2
+ import React, { useContext, useEffect, useState } from 'react';
3
+ import styles from './styles.scss';
4
+ import { useTranslation } from 'react-i18next';
5
+ import GroupFormWorkflowContext from '../context/GroupFormWorkflowContext';
6
+ import { FormProvider, useForm, useFormContext } from 'react-hook-form';
7
+ import CancelModal from '../CancelModal';
8
+ import SessionDetailsForm from './SessionDetailsForm';
9
9
 
10
10
  const NewGroupWorkflowButtons = () => {
11
11
  const { t } = useTranslation();
12
12
  const context = useContext(GroupFormWorkflowContext);
13
13
  const { workflowState, patientUuids } = context;
14
14
  const [cancelModalOpen, setCancelModalOpen] = useState(false);
15
- if (workflowState !== "NEW_GROUP_SESSION") return null;
15
+ if (workflowState !== 'NEW_GROUP_SESSION') return null;
16
16
 
17
17
  return (
18
18
  <>
19
19
  <div className={styles.rightPanelActionButtons}>
20
20
  <Button kind="secondary" type="submit" disabled={!patientUuids.length}>
21
- {t("createNewSession", "Create New Session")}
21
+ {t('createNewSession', 'Create New Session')}
22
22
  </Button>
23
23
  <Button
24
24
  kind="tertiary"
@@ -26,14 +26,10 @@ const NewGroupWorkflowButtons = () => {
26
26
  setCancelModalOpen(true);
27
27
  }}
28
28
  >
29
- {t("cancel", "Cancel")}
29
+ {t('cancel', 'Cancel')}
30
30
  </Button>
31
31
  </div>
32
- <CancelModal
33
- open={cancelModalOpen}
34
- setOpen={setCancelModalOpen}
35
- context={context}
36
- />
32
+ <CancelModal open={cancelModalOpen} setOpen={setCancelModalOpen} context={context} />
37
33
  </>
38
34
  );
39
35
  };
@@ -48,22 +44,20 @@ const GroupIdField = () => {
48
44
  const { activeGroupUuid } = useContext(GroupFormWorkflowContext);
49
45
 
50
46
  useEffect(() => {
51
- if (activeGroupUuid) setValue("groupUuid", activeGroupUuid);
47
+ if (activeGroupUuid) setValue('groupUuid', activeGroupUuid);
52
48
  }, [activeGroupUuid, setValue]);
53
49
 
54
50
  return (
55
51
  <>
56
52
  <input
57
53
  hidden
58
- {...register("groupUuid", {
54
+ {...register('groupUuid', {
59
55
  value: activeGroupUuid,
60
- required: t("chooseGroupError", "Please choose a group."),
56
+ required: t('chooseGroupError', 'Please choose a group.'),
61
57
  })}
62
58
  />
63
59
  {errors.groupUuid && !activeGroupUuid && (
64
- <div className={styles.formError}>
65
- {errors.groupUuid.message as string}
66
- </div>
60
+ <div className={styles.formError}>{errors.groupUuid.message as string}</div>
67
61
  )}
68
62
  </>
69
63
  );
@@ -71,9 +65,7 @@ const GroupIdField = () => {
71
65
 
72
66
  const SessionMetaWorkspace = () => {
73
67
  const { t } = useTranslation();
74
- const { setSessionMeta, workflowState } = useContext(
75
- GroupFormWorkflowContext
76
- );
68
+ const { setSessionMeta, workflowState } = useContext(GroupFormWorkflowContext);
77
69
  const methods = useForm();
78
70
 
79
71
  const onSubmit = (data) => {
@@ -81,7 +73,7 @@ const SessionMetaWorkspace = () => {
81
73
  setSessionMeta({ ...rest, sessionDate: sessionDate[0] });
82
74
  };
83
75
 
84
- if (workflowState !== "NEW_GROUP_SESSION") return null;
76
+ if (workflowState !== 'NEW_GROUP_SESSION') return null;
85
77
 
86
78
  return (
87
79
  <FormProvider {...methods}>
@@ -92,9 +84,9 @@ const SessionMetaWorkspace = () => {
92
84
  <SessionDetailsForm />
93
85
  </div>
94
86
  <div className={styles.rightPanel}>
95
- <h4>{t("newGroupSession", "New Group Session")}</h4>
87
+ <h4>{t('newGroupSession', 'New Group Session')}</h4>
96
88
  <GroupIdField />
97
- <hr style={{ width: "100%" }} />
89
+ <hr style={{ width: '100%' }} />
98
90
  <NewGroupWorkflowButtons />
99
91
  </div>
100
92
  </div>
@@ -1,5 +1,5 @@
1
- import React, { useCallback, useContext, useMemo, useState } from "react";
2
- import { Edit } from "@carbon/react/icons";
1
+ import React, { useCallback, useContext, useMemo, useState } from 'react';
2
+ import { Edit } from '@carbon/react/icons';
3
3
 
4
4
  import {
5
5
  Checkbox,
@@ -11,15 +11,13 @@ import {
11
11
  TableBody,
12
12
  TableCell,
13
13
  Button,
14
- } from "@carbon/react";
15
- import { useTranslation } from "react-i18next";
16
- import GroupFormWorkflowContext from "../../context/GroupFormWorkflowContext";
17
- import AddGroupModal from "../../add-group-modal/AddGroupModal";
14
+ } from '@carbon/react';
15
+ import { useTranslation } from 'react-i18next';
16
+ import GroupFormWorkflowContext from '../../context/GroupFormWorkflowContext';
17
+ import AddGroupModal from '../../add-group-modal/AddGroupModal';
18
18
 
19
19
  const PatientRow = ({ patient }) => {
20
- const { patientUuids, addPatientUuid, removePatientUuid } = useContext(
21
- GroupFormWorkflowContext
22
- );
20
+ const { patientUuids, addPatientUuid, removePatientUuid } = useContext(GroupFormWorkflowContext);
23
21
  const givenName = patient?.name?.[0]?.given?.[0];
24
22
  const familyName = patient?.name?.[0]?.family;
25
23
  const identifier = patient?.identifier?.[0]?.value;
@@ -50,11 +48,7 @@ const PatientRow = ({ patient }) => {
50
48
 
51
49
  return (
52
50
  <TableRow>
53
- <TableCell>
54
- {patient.display ||
55
- patient.displayName ||
56
- [givenName, familyName].join(" ")}
57
- </TableCell>
51
+ <TableCell>{patient.display || patient.displayName || [givenName, familyName].join(' ')}</TableCell>
58
52
  <TableCell>{identifier}</TableCell>
59
53
  <TableCell>
60
54
  <Checkbox
@@ -71,19 +65,13 @@ const PatientRow = ({ patient }) => {
71
65
 
72
66
  const AttendanceTable = ({ patients }) => {
73
67
  const { t } = useTranslation();
74
- const { activeGroupUuid, activeGroupName, activeGroupMembers } = useContext(
75
- GroupFormWorkflowContext
76
- );
68
+ const { activeGroupUuid, activeGroupName, activeGroupMembers } = useContext(GroupFormWorkflowContext);
77
69
 
78
70
  const [isOpen, setOpen] = useState(false);
79
71
 
80
- const headers = [
81
- t("name", "Name"),
82
- t("identifier", "Patient ID"),
83
- t("patientIsPresent", "Patient is present"),
84
- ];
72
+ const headers = [t('name', 'Name'), t('identifier', 'Patient ID'), t('patientIsPresent', 'Patient is present')];
85
73
 
86
- const handleCancel = useCallback(() => {
74
+ const onPostCancel = useCallback(() => {
87
75
  setOpen(false);
88
76
  }, []);
89
77
 
@@ -99,14 +87,14 @@ const AttendanceTable = ({ patients }) => {
99
87
  }, [activeGroupMembers, patients]);
100
88
 
101
89
  if (!activeGroupUuid) {
102
- return <div>{t("selectGroupFirst", "Please select a group first")}</div>;
90
+ return <div>{t('selectGroupFirst', 'Please select a group first')}</div>;
103
91
  }
104
92
 
105
93
  return (
106
94
  <div>
107
95
  <span style={{ flexGrow: 1 }} />
108
96
  <Button kind="ghost" onClick={() => setOpen(true)}>
109
- {t("editGroup", "Edit Group")}&nbsp;
97
+ {t('editGroup', 'Edit Group')}&nbsp;
110
98
  <Edit size={20} />
111
99
  </Button>
112
100
  <AddGroupModal
@@ -116,7 +104,7 @@ const AttendanceTable = ({ patients }) => {
116
104
  isCreate: false,
117
105
  groupName: activeGroupName,
118
106
  isOpen: isOpen,
119
- handleCancel: handleCancel,
107
+ onPostCancel: onPostCancel,
120
108
  onPostSubmit: onPostSubmit,
121
109
  }}
122
110
  />
@@ -130,9 +118,7 @@ const AttendanceTable = ({ patients }) => {
130
118
  </TableHead>
131
119
  <TableBody>
132
120
  {activeGroupMembers.map((patientUuid, index) => {
133
- const patient = patients.find(
134
- (patient) => patient.id === patientUuid
135
- );
121
+ const patient = patients.find((patient) => patient.id === patientUuid);
136
122
  return <PatientRow patient={patient} key={index} />;
137
123
  })}
138
124
  </TableBody>
@@ -1 +1 @@
1
- export { default as AttendanceTable } from "./AttendanceTable";
1
+ export { default as AttendanceTable } from './AttendanceTable';
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { TextInput, Select, SelectItem } from '@carbon/react';
3
+ import { type FieldValues, type UseFormRegister } from 'react-hook-form';
4
+ import { type SpecificQuestion } from '../../types';
5
+
6
+ interface ConfigurableQuestionsSectionProps {
7
+ specificQuestions: Array<SpecificQuestion>;
8
+ register?: UseFormRegister<FieldValues>;
9
+ }
10
+
11
+ const ConfigurableQuestionsSection: React.FC<ConfigurableQuestionsSectionProps> = ({ register, specificQuestions }) => {
12
+ return (
13
+ <>
14
+ {specificQuestions?.map((specificQuestion) => (
15
+ <div key={specificQuestion.question.id}>
16
+ {specificQuestion?.answers?.length > 0 ? (
17
+ <Select
18
+ {...register(specificQuestion.question.id, { required: false })}
19
+ id={specificQuestion.question.id}
20
+ labelText={specificQuestion.question.display}
21
+ readOnly={!!specificQuestion.question.disabled}
22
+ defaultValue={specificQuestion.question.defaultAnswer}
23
+ >
24
+ <SelectItem value="" text="" />
25
+ {specificQuestion.answers.map((answer) => (
26
+ <SelectItem key={answer.value} value={answer.value} text={answer.display} />
27
+ ))}
28
+ </Select>
29
+ ) : (
30
+ <TextInput
31
+ id={specificQuestion.question.id}
32
+ {...register(specificQuestion.question.id, { required: false })}
33
+ type="text"
34
+ labelText={specificQuestion.question.display}
35
+ readOnly={!!specificQuestion.question.disabled}
36
+ defaultValue={specificQuestion.question.defaultAnswer}
37
+ />
38
+ )}
39
+ </div>
40
+ ))}
41
+ </>
42
+ );
43
+ };
44
+
45
+ export default ConfigurableQuestionsSection;
@@ -1,9 +1,9 @@
1
- import React from "react";
2
- import { render } from "@testing-library/react";
3
- import GroupDisplayHeader from "./GroupDisplayHeader";
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import GroupDisplayHeader from './GroupDisplayHeader';
4
4
 
5
- describe("PatientBanner", () => {
6
- it("renders placeholder information when no data is present", () => {
5
+ describe('PatientBanner', () => {
6
+ it('renders placeholder information when no data is present', () => {
7
7
  render(<GroupDisplayHeader />);
8
8
  });
9
9
  });
@@ -1,19 +1,13 @@
1
- import React, { useContext } from "react";
2
- import { Button } from "@carbon/react";
3
- import { Events, Close } from "@carbon/react/icons";
4
- import styles from "./styles.scss";
5
- import { useTranslation } from "react-i18next";
6
- import GroupFormWorkflowContext from "../../context/GroupFormWorkflowContext";
1
+ import React, { useContext } from 'react';
2
+ import { Button } from '@carbon/react';
3
+ import { Events, Close } from '@carbon/react/icons';
4
+ import styles from './styles.scss';
5
+ import { useTranslation } from 'react-i18next';
6
+ import GroupFormWorkflowContext from '../../context/GroupFormWorkflowContext';
7
7
 
8
8
  const GroupDisplayHeader = () => {
9
- const {
10
- activeGroupName,
11
- activeGroupUuid,
12
- patientUuids,
13
- activeSessionMeta,
14
- unsetGroup,
15
- destroySession,
16
- } = useContext(GroupFormWorkflowContext);
9
+ const { activeGroupName, activeGroupUuid, patientUuids, activeSessionMeta, unsetGroup, destroySession } =
10
+ useContext(GroupFormWorkflowContext);
17
11
  const { t } = useTranslation();
18
12
 
19
13
  if (!activeGroupUuid) {
@@ -31,29 +25,27 @@ const GroupDisplayHeader = () => {
31
25
  </div>
32
26
  <div className={styles.groupInfoRow}>
33
27
  <span>
34
- {patientUuids.length} {t("members", "members")}
28
+ {patientUuids.length} {t('members', 'members')}
35
29
  </span>
36
30
  </div>
37
31
  </div>
38
32
  {activeSessionMeta?.sessionNotes && (
39
33
  <div className={styles.groupMeataContent}>
40
34
  <div className={`${styles.groupInfoRow} ${styles.sessionNotesLabel}`}>
41
- {t("sessionNotes", "Session Notes")}
42
- </div>
43
- <div className={styles.groupInfoRow}>
44
- {activeSessionMeta.sessionNotes}
35
+ {t('sessionNotes', 'Session Notes')}
45
36
  </div>
37
+ <div className={styles.groupInfoRow}>{activeSessionMeta.sessionNotes}</div>
46
38
  </div>
47
39
  )}
48
40
  <span style={{ flexGrow: 1 }} />
49
41
  <span>
50
42
  <Button kind="ghost" onClick={() => unsetGroup()}>
51
- {t("changeGroup", "Choose a different group")} <Close size={20} />
43
+ {t('changeGroup', 'Choose a different group')} <Close size={20} />
52
44
  </Button>
53
45
  </span>
54
46
  <span>
55
47
  <Button kind="ghost" onClick={() => destroySession()}>
56
- {t("cancel", "Cancel")} <Close size={20} />
48
+ {t('cancel', 'Cancel')} <Close size={20} />
57
49
  </Button>
58
50
  </span>
59
51
  </div>
@@ -1,3 +1,3 @@
1
- import GroupDisplayHeader from "./GroupDisplayHeader";
1
+ import GroupDisplayHeader from './GroupDisplayHeader';
2
2
 
3
3
  export default GroupDisplayHeader;
@@ -1,26 +1,26 @@
1
- @use '@carbon/styles/scss/spacing';
2
- @use '@carbon/styles/scss/type';
3
- @import '~@openmrs/esm-styleguide/src/vars';
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
4
 
5
5
  .container {
6
- height: spacing.$spacing-11;
6
+ height: layout.$spacing-11;
7
7
  display: flex;
8
8
  align-items: center;
9
- background-color: $ui-02;
10
- border-top: 0.0125rem solid $ui-03;
11
- border-bottom: 0.0125rem solid $ui-03;
12
- padding: 0 spacing.$spacing-05;
9
+ background-color: colors.$white-0;
10
+ border-top: 0.0125rem solid colors.$gray-20;
11
+ border-bottom: 0.0125rem solid colors.$gray-20;
12
+ padding: 0 layout.$spacing-05;
13
13
  }
14
14
 
15
15
  .photoPlaceholder {
16
- height: spacing.$spacing-09;
17
- width: spacing.$spacing-09;
16
+ height: layout.$spacing-09;
17
+ width: layout.$spacing-09;
18
18
  }
19
19
 
20
20
  .groupAvatar {
21
- width: spacing.$spacing-09;
22
- height: spacing.$spacing-09;
23
- margin: spacing.$spacing-03 spacing.$spacing-05 spacing.$spacing-03 0;
21
+ width: layout.$spacing-09;
22
+ height: layout.$spacing-09;
23
+ margin: layout.$spacing-03 layout.$spacing-05 layout.$spacing-03 0;
24
24
  border-radius: 1px;
25
25
  }
26
26
 
@@ -30,29 +30,29 @@
30
30
  }
31
31
 
32
32
  .groupInfoContent {
33
- margin-left: spacing.$spacing-05;
34
- margin-right: spacing.$spacing-10;
33
+ margin-left: layout.$spacing-05;
34
+ margin-right: layout.$spacing-10;
35
35
  }
36
36
 
37
37
  .groupInfoRow {
38
38
  display: flex;
39
39
  align-items: center;
40
40
  & > button {
41
- min-height: spacing.$spacing-07;
41
+ min-height: layout.$spacing-07;
42
42
  }
43
43
  @include type.type-style('body-compact-02');
44
- color: $text-02;
44
+ color: colors.$gray-70;
45
45
  column-gap: 0.8rem;
46
46
 
47
47
  }
48
48
  .sessionNotesLabel {
49
49
  @include type.type-style('label-01');
50
- margin-bottom: spacing.$spacing-01
50
+ margin-bottom: layout.$spacing-01
51
51
  }
52
52
 
53
53
  .groupEditBtn {
54
- color: $ui-05;
55
- margin: spacing.$spacing-03;
54
+ color: colors.$gray-100;
55
+ margin: layout.$spacing-03;
56
56
  }
57
57
 
58
58
  .groupMetaContent {