@epcare/esm-report-builder 0.1.1-pre.13

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 (222) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.js +19 -0
  3. package/.prettierrc +8 -0
  4. package/LICENSE +401 -0
  5. package/README.md +317 -0
  6. package/dist/184.js +2 -0
  7. package/dist/184.js.LICENSE.txt +14 -0
  8. package/dist/184.js.map +1 -0
  9. package/dist/211.js +1 -0
  10. package/dist/211.js.map +1 -0
  11. package/dist/300.js +1 -0
  12. package/dist/311.js +1 -0
  13. package/dist/311.js.map +1 -0
  14. package/dist/44.js +2 -0
  15. package/dist/44.js.LICENSE.txt +30 -0
  16. package/dist/44.js.map +1 -0
  17. package/dist/478.js +2 -0
  18. package/dist/478.js.LICENSE.txt +9 -0
  19. package/dist/478.js.map +1 -0
  20. package/dist/535.js +1 -0
  21. package/dist/535.js.map +1 -0
  22. package/dist/540.js +2 -0
  23. package/dist/540.js.LICENSE.txt +9 -0
  24. package/dist/540.js.map +1 -0
  25. package/dist/710.js +1 -0
  26. package/dist/710.js.map +1 -0
  27. package/dist/729.js +1 -0
  28. package/dist/729.js.map +1 -0
  29. package/dist/872.js +1 -0
  30. package/dist/872.js.map +1 -0
  31. package/dist/917.js +1 -0
  32. package/dist/917.js.map +1 -0
  33. package/dist/961.js +2 -0
  34. package/dist/961.js.LICENSE.txt +19 -0
  35. package/dist/961.js.map +1 -0
  36. package/dist/972.js +2 -0
  37. package/dist/972.js.LICENSE.txt +21 -0
  38. package/dist/972.js.map +1 -0
  39. package/dist/main.js +1 -0
  40. package/dist/main.js.map +1 -0
  41. package/dist/openmrs-esm-report-builder.js +1 -0
  42. package/dist/openmrs-esm-report-builder.js.buildmanifest.json +482 -0
  43. package/dist/openmrs-esm-report-builder.js.map +1 -0
  44. package/dist/routes.json +1 -0
  45. package/e2e/core/env.ts +5 -0
  46. package/e2e/core/global-setup.ts +34 -0
  47. package/e2e/core/test.ts +21 -0
  48. package/e2e/pages/app-shell.page.ts +34 -0
  49. package/e2e/pages/etl-sources.page.ts +35 -0
  50. package/e2e/pages/report-sections.page.ts +20 -0
  51. package/e2e/pages/section-preview.modal.ts +29 -0
  52. package/e2e/specs/etl-sources.spec.ts +51 -0
  53. package/e2e/specs/navigation.spec.ts +13 -0
  54. package/e2e/specs/section-preview-validation.spec.ts +38 -0
  55. package/e2e/specs/section-preview.spec.ts +94 -0
  56. package/e2e/tsconfig.json +11 -0
  57. package/example.env +5 -0
  58. package/jest.config.js +28 -0
  59. package/package.json +102 -0
  60. package/playwright.config.ts +28 -0
  61. package/src/admin-card-link.extension.module.scss +55 -0
  62. package/src/admin-card-link.extension.tsx +24 -0
  63. package/src/components/admin/admin-page.component.tsx +31 -0
  64. package/src/components/admin/age-categories-page.component.tsx +109 -0
  65. package/src/components/admin/age-groups-page.component.tsx +146 -0
  66. package/src/components/admin/etl-sources-page.component.tsx +344 -0
  67. package/src/components/admin/report-categories-page.component.tsx +256 -0
  68. package/src/components/admin/report-library-page.component.tsx +540 -0
  69. package/src/components/ai-support/ai-assist-button.component.tsx +30 -0
  70. package/src/components/ai-support/ai-assist-modal.component.tsx +81 -0
  71. package/src/components/ai-support/ai.service.ts +21 -0
  72. package/src/components/ai-support/ai.types.ts +12 -0
  73. package/src/components/app-shell/report-builder-shell.component.tsx +120 -0
  74. package/src/components/app-shell/report-builder-shell.scss +15 -0
  75. package/src/components/data-themes/data-theme-form.component.tsx +59 -0
  76. package/src/components/data-themes/data-theme-modal.component.tsx +349 -0
  77. package/src/components/data-themes/data-themes-page.component.tsx +132 -0
  78. package/src/components/data-themes/data-themes-table.component.tsx +91 -0
  79. package/src/components/data-themes/icon-registry.ts +35 -0
  80. package/src/components/data-themes/sections/data-theme-basics.section.tsx +63 -0
  81. package/src/components/data-themes/sections/data-theme-condition-columns.section.tsx +397 -0
  82. package/src/components/data-themes/sections/data-theme-fields-editor.section.tsx +125 -0
  83. package/src/components/data-themes/sections/data-theme-metadata.section.tsx +245 -0
  84. package/src/components/data-themes/sections/data-theme-preview.section.tsx +115 -0
  85. package/src/components/data-themes/sections/data-theme-source.section.tsx +184 -0
  86. package/src/components/indicators/README.md +24 -0
  87. package/src/components/indicators/base-indicator-basic-fields.component.tsx +18 -0
  88. package/src/components/indicators/base-indicator-basics.section.tsx +54 -0
  89. package/src/components/indicators/base-indicator-countby.section.tsx +25 -0
  90. package/src/components/indicators/base-indicator-criteria.section.tsx +83 -0
  91. package/src/components/indicators/base-indicator-details-form.component.tsx +80 -0
  92. package/src/components/indicators/base-indicator-theme-unit-fields.component.tsx +39 -0
  93. package/src/components/indicators/create-base-indicator-modal.component.tsx +501 -0
  94. package/src/components/indicators/create-composite-base-indicator-modal.component.tsx +297 -0
  95. package/src/components/indicators/create-final-indicator-modal.component.tsx +260 -0
  96. package/src/components/indicators/diagnosis-filters-form.component.tsx +101 -0
  97. package/src/components/indicators/disaggregation-panel.component.tsx +93 -0
  98. package/src/components/indicators/handler/concept-search-multiselect.component.tsx +153 -0
  99. package/src/components/indicators/handler/question-answer-concept-search.component.tsx +336 -0
  100. package/src/components/indicators/indicator-status-tag.component.tsx +9 -0
  101. package/src/components/indicators/indicators-page.component.tsx +481 -0
  102. package/src/components/indicators/indicators-page.scss +121 -0
  103. package/src/components/indicators/indicators-table.component.tsx +166 -0
  104. package/src/components/indicators/preview-table.component.tsx +31 -0
  105. package/src/components/indicators/sections/composite-indicator-basics.section.tsx +36 -0
  106. package/src/components/indicators/sections/composite-indicator-picker.section.tsx +161 -0
  107. package/src/components/indicators/sections/composite-indicator-sql-preview.section.tsx +31 -0
  108. package/src/components/indicators/sections/final-indicator-basics.section.tsx +46 -0
  109. package/src/components/indicators/sections/final-indicator-disaggregation.section.tsx +47 -0
  110. package/src/components/indicators/sections/final-indicator-picker.section.tsx +92 -0
  111. package/src/components/indicators/sections/final-indicator-preview.section.tsx +20 -0
  112. package/src/components/indicators/sections/final-indicator-results-preview.section.tsx +65 -0
  113. package/src/components/indicators/sections/indicator-basics.section.tsx +40 -0
  114. package/src/components/indicators/sections/indicator-conditions.section.tsx +194 -0
  115. package/src/components/indicators/sections/indicator-sql-preview.section.tsx +26 -0
  116. package/src/components/indicators/sections/indicator-theme.section.tsx +48 -0
  117. package/src/components/indicators/sql-preview.component.tsx +19 -0
  118. package/src/components/indicators/types/base-indicator-form.types.ts +17 -0
  119. package/src/components/indicators/types/base-indicator-theme.constants.ts +8 -0
  120. package/src/components/indicators/types/composite-indicator.types.ts +21 -0
  121. package/src/components/indicators/types/condition-ui.types.ts +11 -0
  122. package/src/components/indicators/types/data-theme-config.types.ts +88 -0
  123. package/src/components/indicators/types/indicator-types.ts +56 -0
  124. package/src/components/indicators/types/sql-builders.ts +43 -0
  125. package/src/components/indicators/utils/composite-indicator-sql.utils.ts +206 -0
  126. package/src/components/indicators/utils/concept-preload.utils.ts +21 -0
  127. package/src/components/indicators/utils/final-indicator-sql.utils.ts +124 -0
  128. package/src/components/indicators/utils/indicator-conditions-hydration.utils.ts +254 -0
  129. package/src/components/indicators/utils/indicator-sql.utils.ts +185 -0
  130. package/src/components/landing/landing-action-item.component.tsx +50 -0
  131. package/src/components/landing/landing-action-list.component.tsx +12 -0
  132. package/src/components/landing/landing-activity-list.component.tsx +47 -0
  133. package/src/components/landing/landing-footer-grid.component.tsx +45 -0
  134. package/src/components/landing/landing-hero.component.tsx +18 -0
  135. package/src/components/landing/landing-section-card.component.tsx +33 -0
  136. package/src/components/landing/report-builder-landing-page.component.tsx +103 -0
  137. package/src/components/landing/report-builder-landing-page.scss +131 -0
  138. package/src/components/report/dashboard/reports-table.component.tsx +145 -0
  139. package/src/components/report/definition/panels/properties-panel.component.tsx +38 -0
  140. package/src/components/report/definition/panels/report-structure-panel.component.tsx +61 -0
  141. package/src/components/report/definition/panels/selection-panel.component.tsx +58 -0
  142. package/src/components/report/definition/report-definition-editor.component.tsx +99 -0
  143. package/src/components/report/definition/report-definition.types.ts +66 -0
  144. package/src/components/report/design/panels/IndicatorPropertiesPanel.scss +33 -0
  145. package/src/components/report/design/panels/IndicatorPropertiesPanel.tsx +389 -0
  146. package/src/components/report/design/panels/JsonPreviewPanel.scss +32 -0
  147. package/src/components/report/design/panels/JsonPreviewPanel.tsx +104 -0
  148. package/src/components/report/design/panels/mapping-preview-panel.component.tsx +82 -0
  149. package/src/components/report/design/panels/mapping-preview-panel.scss +55 -0
  150. package/src/components/report/design/panels/template-structure-panel.component.tsx +296 -0
  151. package/src/components/report/design/panels/template-structure-panel.scss +81 -0
  152. package/src/components/report/design/report-design-editor.component.tsx +894 -0
  153. package/src/components/report/design/report-design.types.ts +43 -0
  154. package/src/components/report/design/report-design.utils.ts +86 -0
  155. package/src/components/report/panels/report-detail.component.tsx +71 -0
  156. package/src/components/report/panels/report-panel-shell.component.tsx +60 -0
  157. package/src/components/report/report-dashboard.page.component.tsx +75 -0
  158. package/src/components/report/report-editor.page.component.tsx +466 -0
  159. package/src/components/report/report.routes.tsx +30 -0
  160. package/src/components/report-sections/create-report-section-modal.component.tsx +278 -0
  161. package/src/components/report-sections/hooks/useAgeCategories.ts +25 -0
  162. package/src/components/report-sections/hooks/useSectionEditorState.ts +306 -0
  163. package/src/components/report-sections/panels/Dhis2MappingPanel.tsx +157 -0
  164. package/src/components/report-sections/panels/DisaggregationPanel.tsx +97 -0
  165. package/src/components/report-sections/panels/IndicatorPickerPanel.tsx +143 -0
  166. package/src/components/report-sections/panels/SectionBasicsPanel.tsx +27 -0
  167. package/src/components/report-sections/report-section-preview-modal.component.tsx +418 -0
  168. package/src/components/report-sections/report-sections-page.component.tsx +313 -0
  169. package/src/components/report-sections/section-types.ts +55 -0
  170. package/src/components/report-sections/section-utils.ts +46 -0
  171. package/src/components/report-sections/sections-page.scss +79 -0
  172. package/src/components/run-reports/run-reports-page.component.tsx +23 -0
  173. package/src/components/shared/header/builder-header-actions.component.tsx +38 -0
  174. package/src/components/shared/header/header.component.tsx +85 -0
  175. package/src/components/shared/header/header.scss +150 -0
  176. package/src/components/shared/header/illustration.component.tsx +34 -0
  177. package/src/components/shared/indicator-properties-panel/IndicatorPropertiesPanel.scss +33 -0
  178. package/src/components/shared/indicator-properties-panel/IndicatorPropertiesPanel.tsx +389 -0
  179. package/src/components/shared/json-preview-panel/JsonPreviewPanel.scss +32 -0
  180. package/src/components/shared/json-preview-panel/JsonPreviewPanel.tsx +104 -0
  181. package/src/components/shared/mapping-preview-panel/mapping-preview-panel.component.tsx +82 -0
  182. package/src/components/shared/mapping-preview-panel/mapping-preview-panel.scss +55 -0
  183. package/src/components/shared/preview/query-results-preview.component.tsx +204 -0
  184. package/src/components/shared/template-structure-panel/template-structure-panel.component.tsx +296 -0
  185. package/src/components/shared/template-structure-panel/template-structure-panel.scss +81 -0
  186. package/src/config-schema.ts +23 -0
  187. package/src/globals.d.ts +14 -0
  188. package/src/hooks/theme/useDataThemes.ts +28 -0
  189. package/src/hooks/theme/useMambaTableMeta.ts +34 -0
  190. package/src/hooks/theme/useMambaTables.ts +63 -0
  191. package/src/index.ts +23 -0
  192. package/src/resources/agegroup/agegroups.api.ts +58 -0
  193. package/src/resources/concepts/concept-mapper.ts +21 -0
  194. package/src/resources/concepts/concept-types.ts +31 -0
  195. package/src/resources/concepts/concepts.resource.ts +44 -0
  196. package/src/resources/concepts/useConceptSearch.ts +41 -0
  197. package/src/resources/etl-source/etl-source.api.ts +65 -0
  198. package/src/resources/indicator/indicators.api.ts +125 -0
  199. package/src/resources/openmrs-api.ts +24 -0
  200. package/src/resources/preview/sql-preview.api.ts +54 -0
  201. package/src/resources/report/reports.api.ts +117 -0
  202. package/src/resources/report-category/report-category.api.ts +41 -0
  203. package/src/resources/report-library/report-library.api.ts +63 -0
  204. package/src/resources/report-section/report-sections.api.ts +73 -0
  205. package/src/resources/report-section/section-preview.api.ts +21 -0
  206. package/src/resources/theme/data-theme.api.ts +88 -0
  207. package/src/resources/theme/mamba-schema.api.ts +31 -0
  208. package/src/resources/theme/mamba-table-meta.api.ts +45 -0
  209. package/src/root.component.tsx +20 -0
  210. package/src/routes/report-builder.routes.tsx +66 -0
  211. package/src/routes/report-builder.scss +56 -0
  212. package/src/routes.json +21 -0
  213. package/src/sample-template.ts +121 -0
  214. package/src/template-utils.ts +110 -0
  215. package/src/types/carbon-react-inert.d.ts +13 -0
  216. package/src/types/condition-operators.ts +49 -0
  217. package/src/types/theme/data-theme.types.ts +88 -0
  218. package/src/utils/html-entities.utils.ts +23 -0
  219. package/tools/setup-tests.ts +1 -0
  220. package/translations/en.json +4 -0
  221. package/tsconfig.json +43 -0
  222. package/webpack.config.js +14 -0
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { TextInput } from '@carbon/react';
3
+
4
+ type Props = {
5
+ code: string;
6
+ name: string;
7
+ onChangeCode: (next: string) => void;
8
+ onChangeName: (next: string) => void;
9
+ };
10
+
11
+ export default function BaseIndicatorBasicFields({ code, name, onChangeCode, onChangeName }: Props) {
12
+ return (
13
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: '0.75rem' }}>
14
+ <TextInput id="base-code" labelText="Code" value={code} onChange={(e) => onChangeCode((e.target as HTMLInputElement).value)} />
15
+ <TextInput id="base-name" labelText="Name" value={name} onChange={(e) => onChangeName((e.target as HTMLInputElement).value)} />
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { Select, SelectItem, TextArea, TextInput, Stack } from '@carbon/react';
3
+
4
+ import type { CreateBaseIndicatorPayload } from './types/base-indicator-form.types';
5
+ import { THEME_OPTIONS, THEME_LABELS } from './types/base-indicator-theme.constants';
6
+
7
+ type Props = {
8
+ state: CreateBaseIndicatorPayload;
9
+ onChange: (patch: Partial<CreateBaseIndicatorPayload>) => void;
10
+ };
11
+
12
+ const BaseIndicatorBasicsSection: React.FC<Props> = ({ state, onChange }) => {
13
+ return (
14
+ <Stack gap={5}>
15
+ <Select
16
+ id="theme"
17
+ labelText="Theme"
18
+ value={state.theme}
19
+ onChange={(e) => onChange({ theme: (e.target as HTMLSelectElement).value })}
20
+ >
21
+ {THEME_OPTIONS.map((key) => (
22
+ <SelectItem key={key} value={key} text={THEME_LABELS[key]} />
23
+ ))}
24
+ </Select>
25
+
26
+ <TextInput
27
+ id="code"
28
+ labelText="Code"
29
+ helperText="Short unique code used in reports (e.g. MAL_PREG)"
30
+ value={state.code}
31
+ onChange={(e) => onChange({ code: (e.target as HTMLInputElement).value })}
32
+ placeholder="e.g. MAL_PREG"
33
+ />
34
+
35
+ <TextInput
36
+ id="name"
37
+ labelText="Indicator"
38
+ value={state.indicatorName}
39
+ onChange={(e) => onChange({ indicatorName: (e.target as HTMLInputElement).value })}
40
+ placeholder="e.g. Pregnant Women with Malaria"
41
+ />
42
+
43
+ <TextArea
44
+ id="desc"
45
+ labelText="Description"
46
+ value={state.description}
47
+ onChange={(e) => onChange({ description: (e.target as HTMLTextAreaElement).value })}
48
+ placeholder="Short description of what this indicator represents"
49
+ />
50
+ </Stack>
51
+ );
52
+ };
53
+
54
+ export default BaseIndicatorBasicsSection;
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { RadioButtonGroup, RadioButton } from '@carbon/react';
3
+
4
+ import type { CreateBaseIndicatorPayload } from './types/base-indicator-form.types';
5
+
6
+ type Props = {
7
+ state: CreateBaseIndicatorPayload;
8
+ onChange: (patch: Partial<CreateBaseIndicatorPayload>) => void;
9
+ };
10
+
11
+ const BaseIndicatorCountBySection: React.FC<Props> = ({ state, onChange }) => {
12
+ return (
13
+ <RadioButtonGroup
14
+ legendText="Count By"
15
+ name="countBy"
16
+ valueSelected={state.countBy}
17
+ onChange={(val) => onChange({ countBy: val as 'Patients' | 'Encounters' })}
18
+ >
19
+ <RadioButton id="cb-patients" labelText="Patients" value="Patients" />
20
+ <RadioButton id="cb-encounters" labelText="Encounters" value="Encounters" />
21
+ </RadioButtonGroup>
22
+ );
23
+ };
24
+
25
+ export default BaseIndicatorCountBySection;
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { Stack, Search, InlineLoading, FilterableMultiSelect, Select, SelectItem } from '@carbon/react';
3
+
4
+ import { useConceptSearch } from '../../resources/concepts/useConceptSearch';
5
+ import type { ConceptSummary } from '../../resources/concepts/concept-types';
6
+ import type { CreateBaseIndicatorPayload } from './types/base-indicator-form.types';
7
+
8
+ type Props = {
9
+ open: boolean; // to reset when modal opens
10
+ state: CreateBaseIndicatorPayload;
11
+ onChange: (patch: Partial<CreateBaseIndicatorPayload>) => void;
12
+ };
13
+
14
+ const BaseIndicatorCriteriaSection: React.FC<Props> = ({ open, state, onChange }) => {
15
+ const [conceptQuery, setConceptQuery] = React.useState('');
16
+ const { loading, results, error } = useConceptSearch(conceptQuery);
17
+
18
+ // Force-reset Carbon internal selected state on open
19
+ const [multiKey, setMultiKey] = React.useState(0);
20
+
21
+ React.useEffect(() => {
22
+ if (!open) return;
23
+ setConceptQuery('');
24
+ setMultiKey((k) => k + 1);
25
+ onChange({ conditionConceptUuids: [], conditionConceptLabels: [] });
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ }, [open]);
28
+
29
+ const itemToString = React.useCallback((item: ConceptSummary | null) => (item ? item.display : ''), []);
30
+
31
+ const onSelectedItems = (selectedItems: ConceptSummary[]) => {
32
+ onChange({
33
+ conditionConceptUuids: selectedItems.map((x) => x.uuid),
34
+ conditionConceptLabels: selectedItems.map((x) => x.display),
35
+ });
36
+ };
37
+
38
+ return (
39
+ <div>
40
+ <div style={{ fontWeight: 600, marginBottom: '0.5rem' }}>Criteria</div>
41
+
42
+ <Stack gap={4}>
43
+ <Search
44
+ id="concept-search"
45
+ labelText="Search concepts"
46
+ placeholder="Type to search concepts..."
47
+ value={conceptQuery}
48
+ onChange={(e) => setConceptQuery((e.target as HTMLInputElement).value)}
49
+ size="lg"
50
+ />
51
+
52
+ {loading ? <InlineLoading description="Searching…" /> : null}
53
+ {error ? (
54
+ <div style={{ fontSize: '0.875rem', color: 'var(--cds-text-error, #da1e28)' }}>{error}</div>
55
+ ) : null}
56
+
57
+ <FilterableMultiSelect
58
+ key={multiKey}
59
+ id="conditionConcepts"
60
+ titleText="Condition concept(s)"
61
+ items={results}
62
+ itemToString={itemToString}
63
+ placeholder={results.length ? 'Select concept(s)…' : 'No results'}
64
+ helperText="Select 1 concept for '=' filtering, select 2+ for 'IN (...)' filtering"
65
+ onChange={(e: any) => onSelectedItems((e.selectedItems ?? []) as ConceptSummary[])}
66
+ />
67
+
68
+ <Select
69
+ id="preg"
70
+ labelText="Pregnancy Status"
71
+ value={state.pregnancyStatus}
72
+ onChange={(e) => onChange({ pregnancyStatus: (e.target as HTMLSelectElement).value })}
73
+ >
74
+ {['Pregnant', 'Not pregnant'].map((x) => (
75
+ <SelectItem key={x} value={x} text={x} />
76
+ ))}
77
+ </Select>
78
+ </Stack>
79
+ </div>
80
+ );
81
+ };
82
+
83
+ export default BaseIndicatorCriteriaSection;
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import {Select, SelectItem, TextInput} from '@carbon/react';
3
+
4
+ export type DataTheme = 'DIAGNOSIS' | 'OBSERVATIONS' | 'ENCOUNTERS';
5
+
6
+ type Props = {
7
+ code: string;
8
+ name: string;
9
+ theme: DataTheme;
10
+ unit: 'Patients' | 'Encounters';
11
+
12
+ onChangeCode: (v: string) => void;
13
+ onChangeName: (v: string) => void;
14
+ onChangeTheme: (v: DataTheme) => void;
15
+ onChangeUnit: (v: 'Patients' | 'Encounters') => void;
16
+ };
17
+
18
+ const grid2 = {
19
+ display: 'grid',
20
+ gridTemplateColumns: '1fr 1fr',
21
+ gap: '0.75rem',
22
+ } as const;
23
+
24
+ const BaseIndicatorDetailsForm: React.FC<Props> = ({
25
+ code,
26
+ name,
27
+ theme,
28
+ unit,
29
+ onChangeCode,
30
+ onChangeName,
31
+ onChangeTheme,
32
+ onChangeUnit,
33
+ }) => {
34
+ return (
35
+ <>
36
+ <div style={grid2}>
37
+ <TextInput
38
+ id="base-code"
39
+ labelText="Code"
40
+ value={code}
41
+ onChange={(e) => onChangeCode((e.target as HTMLInputElement).value)}
42
+ placeholder="e.g. MAL_CASES"
43
+ />
44
+
45
+ <TextInput
46
+ id="base-name"
47
+ labelText="Name"
48
+ value={name}
49
+ onChange={(e) => onChangeName((e.target as HTMLInputElement).value)}
50
+ placeholder="e.g. Malaria Cases"
51
+ />
52
+ </div>
53
+
54
+ <div style={{...grid2, marginTop: '0.75rem'}}>
55
+ <Select
56
+ id="base-theme"
57
+ labelText="Data theme"
58
+ value={theme}
59
+ onChange={(e) => onChangeTheme((e.target as HTMLSelectElement).value as DataTheme)}
60
+ >
61
+ <SelectItem value="DIAGNOSIS" text="Diagnosis Data"/>
62
+ <SelectItem value="OBSERVATIONS" text="Observations (coming soon)"/>
63
+ <SelectItem value="ENCOUNTERS" text="Encounters (coming soon)"/>
64
+ </Select>
65
+
66
+ <Select
67
+ id="base-unit"
68
+ labelText="Unit"
69
+ value={unit}
70
+ onChange={(e) => onChangeUnit((e.target as HTMLSelectElement).value as 'Patients' | 'Encounters')}
71
+ >
72
+ <SelectItem value="Patients" text="Patients"/>
73
+ <SelectItem value="Encounters" text="Encounters"/>
74
+ </Select>
75
+ </div>
76
+ </>
77
+ );
78
+ };
79
+
80
+ export default BaseIndicatorDetailsForm;
@@ -0,0 +1,39 @@
1
+ /*
2
+ import React from 'react';
3
+ import { Select, SelectItem, TextInput } from '@carbon/react';
4
+
5
+ import type { CountingUnit, DataTheme } from './types/indicator-types';
6
+
7
+ type Props = {
8
+ theme: DataTheme;
9
+ unit: CountingUnit;
10
+
11
+ onChangeTheme: (next: DataTheme) => void;
12
+ onChangeUnit: (next: CountingUnit) => void;
13
+ };
14
+
15
+ export default function BaseIndicatorThemeUnitFields({ theme, unit, onChangeTheme, onChangeUnit }: Props) {
16
+ return (
17
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
18
+ <Select
19
+ id="base-theme"
20
+ labelText="Data theme"
21
+ value={theme}
22
+ onChange={(e) => onChangeTheme((e.target as HTMLSelectElement).value as DataTheme)}
23
+ >
24
+ <SelectItem value="DIAGNOSIS" text="Diagnosis Data" />
25
+ <SelectItem value="OBSERVATIONS" text="Observations (coming soon)" />
26
+ <SelectItem value="ENCOUNTERS" text="Encounters (coming soon)" />
27
+ </Select>
28
+
29
+ {/!* keeping this as TextInput allows future custom units, but we still type it as Patients/Encounters for now *!/}
30
+ <TextInput
31
+ id="base-unit"
32
+ labelText="Unit"
33
+ value={unit}
34
+ onChange={(e) => onChangeUnit(((e.target as HTMLInputElement).value as CountingUnit) || 'Patients')}
35
+ />
36
+ </div>
37
+ );
38
+ }
39
+ */