@palladium-ethiopia/esm-clinical-workflow-app 5.4.2-pre.20

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 (89) hide show
  1. package/.turbo/turbo-build.log +14 -0
  2. package/README.md +1 -0
  3. package/dist/152.js +1 -0
  4. package/dist/152.js.map +1 -0
  5. package/dist/159.js +1 -0
  6. package/dist/159.js.map +1 -0
  7. package/dist/208.js +1 -0
  8. package/dist/208.js.map +1 -0
  9. package/dist/209.js +1 -0
  10. package/dist/209.js.map +1 -0
  11. package/dist/363.js +1 -0
  12. package/dist/363.js.map +1 -0
  13. package/dist/410.js +1 -0
  14. package/dist/410.js.map +1 -0
  15. package/dist/442.js +1 -0
  16. package/dist/442.js.map +1 -0
  17. package/dist/466.js +1 -0
  18. package/dist/466.js.map +1 -0
  19. package/dist/484.js +11 -0
  20. package/dist/484.js.map +1 -0
  21. package/dist/540.js +1 -0
  22. package/dist/540.js.map +1 -0
  23. package/dist/545.js +43 -0
  24. package/dist/545.js.map +1 -0
  25. package/dist/61.js +1 -0
  26. package/dist/61.js.map +1 -0
  27. package/dist/677.js +1 -0
  28. package/dist/677.js.map +1 -0
  29. package/dist/689.js +1 -0
  30. package/dist/689.js.map +1 -0
  31. package/dist/697.js +1 -0
  32. package/dist/697.js.map +1 -0
  33. package/dist/712.js +1 -0
  34. package/dist/712.js.map +1 -0
  35. package/dist/771.js +1 -0
  36. package/dist/771.js.map +1 -0
  37. package/dist/789.js +1 -0
  38. package/dist/789.js.map +1 -0
  39. package/dist/ethiopia-esm-clinical-workflow-app.js +6 -0
  40. package/dist/ethiopia-esm-clinical-workflow-app.js.buildmanifest.json +579 -0
  41. package/dist/ethiopia-esm-clinical-workflow-app.js.map +1 -0
  42. package/dist/main.js +16 -0
  43. package/dist/main.js.map +1 -0
  44. package/dist/routes.json +1 -0
  45. package/jest.config.js +3 -0
  46. package/package.json +59 -0
  47. package/rspack.config.js +1 -0
  48. package/src/config-schema.ts +69 -0
  49. package/src/constants.ts +2 -0
  50. package/src/createDashboardLink.tsx +10 -0
  51. package/src/dashboard.meta.ts +6 -0
  52. package/src/declarations.d.ts +3 -0
  53. package/src/helper.ts +115 -0
  54. package/src/index.ts +51 -0
  55. package/src/mru/billing-information/billing-information.resource.ts +139 -0
  56. package/src/mru/billing-information/billing-information.scss +55 -0
  57. package/src/mru/billing-information/billing-information.workspace.tsx +371 -0
  58. package/src/mru/dashboard.component.tsx +18 -0
  59. package/src/mru/mru.component.tsx +106 -0
  60. package/src/mru/mru.scss +28 -0
  61. package/src/patient-registration/patient-registration.resource.tsx +129 -0
  62. package/src/patient-registration/patient.registration.workspace.scss +47 -0
  63. package/src/patient-registration/patient.registration.workspace.tsx +443 -0
  64. package/src/patient-registration/useGenerateIdentifier.ts +26 -0
  65. package/src/patient-scoreboard/appointment-cards/checked-in-appointments.card.tsx +18 -0
  66. package/src/patient-scoreboard/appointment-cards/not-arrived-appointments.card.tsx +18 -0
  67. package/src/patient-scoreboard/appointment-cards/total-appointments.card.tsx +18 -0
  68. package/src/patient-scoreboard/hooks/useAppointmentList.ts +61 -0
  69. package/src/patient-scoreboard/hooks/useVisitList.ts +104 -0
  70. package/src/patient-scoreboard/metrics-card/metrics-card.component.scss +84 -0
  71. package/src/patient-scoreboard/metrics-card/metrics-card.component.tsx +40 -0
  72. package/src/patient-scoreboard/patient-scoreboard.component.scss +47 -0
  73. package/src/patient-scoreboard/patient-scoreboard.component.tsx +70 -0
  74. package/src/patient-scoreboard/visit-cards/active-visits.card.tsx +18 -0
  75. package/src/patient-scoreboard/visit-cards/scheduled-visits.card.tsx +18 -0
  76. package/src/patient-scoreboard/visit-cards/total-visits.card.tsx +18 -0
  77. package/src/patient-scoreboard/visits-table/visits-table.component.scss +31 -0
  78. package/src/patient-scoreboard/visits-table/visits-table.component.tsx +181 -0
  79. package/src/root.component.tsx +20 -0
  80. package/src/root.scss +10 -0
  81. package/src/routes.json +108 -0
  82. package/src/triage/patient-banner.component.tsx +59 -0
  83. package/src/triage/patient-banner.scss +14 -0
  84. package/src/triage/triage-dashboard.component.tsx +116 -0
  85. package/src/triage/triage-dashboard.scss +107 -0
  86. package/src/triage/triage.resource.tsx +44 -0
  87. package/src/triage/useStartVisitAndLaunchTriageForm.ts +156 -0
  88. package/src/types/index.ts +0 -0
  89. package/tsconfig.json +4 -0
@@ -0,0 +1,84 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+
5
+ .tileContainer {
6
+ border: 1px solid colors.$gray-20;
7
+ height: 7.875rem;
8
+ padding: layout.$spacing-05;
9
+ }
10
+
11
+ .tileHeader {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: baseline;
15
+ margin-bottom: layout.$spacing-03;
16
+ }
17
+
18
+ .headerLabel {
19
+ @include type.type-style('heading-compact-01');
20
+ color: colors.$gray-70;
21
+ }
22
+
23
+ .totalsLabel {
24
+ @include type.type-style('label-01');
25
+ color: colors.$gray-70;
26
+ }
27
+
28
+ .totalsValue {
29
+ @include type.type-style('heading-04');
30
+ color: colors.$gray-100;
31
+ }
32
+
33
+ .headerLabelContainer {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: space-between;
37
+ width: 100%;
38
+ }
39
+
40
+ .link {
41
+ text-decoration: none;
42
+ display: flex;
43
+ align-items: center;
44
+ color: colors.$blue-60;
45
+ }
46
+
47
+ .metricsGrid {
48
+ display: grid;
49
+ grid-template-columns: 1fr 1fr;
50
+
51
+ &:has(.countGrid) {
52
+ grid-template-columns: 1fr 1fr;
53
+ }
54
+
55
+ &:not(:has(.countGrid)) {
56
+ grid-template-columns: 1fr;
57
+ }
58
+ }
59
+
60
+ .metricsContent {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: flex-start;
64
+ justify-content: center;
65
+ }
66
+
67
+ .countGrid {
68
+ display: grid;
69
+ grid-template-columns: 1fr 1fr;
70
+ justify-self: flex-end;
71
+ column-gap: layout.$spacing-03;
72
+ row-gap: layout.$spacing-03;
73
+ margin: layout.$spacing-03;
74
+
75
+ & > span {
76
+ font-size: 0.7rem !important;
77
+ margin: 0;
78
+ color: colors.$gray-70;
79
+ }
80
+
81
+ & > p {
82
+ margin: 0;
83
+ }
84
+ }
@@ -0,0 +1,40 @@
1
+ import React, { useMemo } from 'react';
2
+ import dayjs from 'dayjs';
3
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
4
+ import { useTranslation } from 'react-i18next';
5
+ import isEmpty from 'lodash-es/isEmpty';
6
+
7
+ import styles from './metrics-card.component.scss';
8
+
9
+ dayjs.extend(isSameOrBefore);
10
+
11
+ interface MetricsCardProps {
12
+ label: string;
13
+ value: number | string;
14
+ headerLabel: string;
15
+ selectedDate?: string;
16
+ }
17
+
18
+ const MetricsCard: React.FC<MetricsCardProps> = ({ label, value, headerLabel, selectedDate }) => {
19
+ const { t } = useTranslation();
20
+ const date = selectedDate || dayjs().format('YYYY-MM-DD');
21
+ const isSelectedDateInPast = useMemo(() => dayjs(date).isBefore(dayjs(), 'date'), [date]);
22
+
23
+ return (
24
+ <article className={styles.tileContainer}>
25
+ <div className={styles.tileHeader}>
26
+ <div className={styles.headerLabelContainer}>
27
+ <span className={styles.headerLabel}>{headerLabel}</span>
28
+ </div>
29
+ </div>
30
+ <div className={styles.metricsGrid}>
31
+ <div className={styles.metricsContent}>
32
+ <span className={styles.totalsLabel}>{label}</span>
33
+ <p className={styles.totalsValue}>{value}</p>
34
+ </div>
35
+ </div>
36
+ </article>
37
+ );
38
+ };
39
+
40
+ export default MetricsCard;
@@ -0,0 +1,47 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/colors';
3
+ @use '@carbon/type';
4
+
5
+ .patientScoreboardContainer {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: layout.$spacing-05;
9
+ padding: layout.$spacing-05;
10
+
11
+ h1 {
12
+ @include type.type-style('heading-05');
13
+ margin-bottom: layout.$spacing-03;
14
+ }
15
+
16
+ .cardsGrid {
17
+ display: grid;
18
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
19
+ gap: layout.$spacing-05;
20
+ }
21
+
22
+ .visitsSection {
23
+ margin-top: layout.$spacing-06;
24
+ }
25
+
26
+ .switcher {
27
+ margin-bottom: layout.$spacing-05;
28
+ }
29
+
30
+ .patientScoreboardContent {
31
+ display: flex;
32
+ justify-content: space-between;
33
+ align-items: center;
34
+ }
35
+
36
+ .scoreCard {
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: layout.$spacing-05;
40
+ width: 32%;
41
+ border: 1px solid colors.$gray-20;
42
+ padding: layout.$spacing-05;
43
+ min-height: 8rem;
44
+ font-weight: 600;
45
+ color: colors.$gray-70;
46
+ }
47
+ }
@@ -0,0 +1,70 @@
1
+ import React, { useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { ContentSwitcher, Switch } from '@carbon/react';
4
+ import { isDesktop, useLayoutType } from '@openmrs/esm-framework';
5
+
6
+ import styles from './patient-scoreboard.component.scss';
7
+ import ActiveVisitsCard from './visit-cards/active-visits.card';
8
+ import ScheduledVisitsCard from './visit-cards/scheduled-visits.card';
9
+ import TotalVisitsCard from './visit-cards/total-visits.card';
10
+ import VisitsTable from './visits-table/visits-table.component';
11
+ import { useActiveVisits, useScheduledVisits, useTotalVisits } from './hooks/useVisitList';
12
+
13
+ type VisitType = 'active' | 'scheduled' | 'all';
14
+
15
+ const PatientScoreboard: React.FC = () => {
16
+ const { t } = useTranslation();
17
+ const layout = useLayoutType();
18
+ const responsiveSize = isDesktop(layout) ? 'sm' : 'md';
19
+ const [selectedVisitType, setSelectedVisitType] = useState<VisitType>('active');
20
+
21
+ const { visits: activeVisits, isLoading: isLoadingActive } = useActiveVisits();
22
+ const { visits: scheduledVisits, isLoading: isLoadingScheduled } = useScheduledVisits();
23
+ const { visits: totalVisits, isLoading: isLoadingTotal } = useTotalVisits();
24
+
25
+ const getCurrentVisits = () => {
26
+ switch (selectedVisitType) {
27
+ case 'active':
28
+ return { visits: activeVisits, isLoading: isLoadingActive, heading: t('activeVisits', 'Active Visits') };
29
+ case 'scheduled':
30
+ return {
31
+ visits: scheduledVisits,
32
+ isLoading: isLoadingScheduled,
33
+ heading: t('scheduledVisits', 'Scheduled Visits'),
34
+ };
35
+ case 'all':
36
+ return { visits: totalVisits, isLoading: isLoadingTotal, heading: t('allVisits', 'All Visits') };
37
+ default:
38
+ return { visits: [], isLoading: false, heading: '' };
39
+ }
40
+ };
41
+
42
+ const { visits, isLoading, heading } = getCurrentVisits();
43
+
44
+ return (
45
+ <div className={styles.patientScoreboardContainer}>
46
+ <h1>Patient Scoreboard</h1>
47
+ <div className={styles.cardsGrid}>
48
+ <ActiveVisitsCard />
49
+ <ScheduledVisitsCard />
50
+ <TotalVisitsCard />
51
+ </div>
52
+
53
+ <div className={styles.visitsSection}>
54
+ <ContentSwitcher
55
+ className={styles.switcher}
56
+ size={responsiveSize}
57
+ onChange={({ name }) => setSelectedVisitType(name as VisitType)}
58
+ selectedIndex={['active', 'scheduled', 'all'].indexOf(selectedVisitType)}>
59
+ <Switch name="active" text={t('active', 'Active')} />
60
+ <Switch name="scheduled" text={t('scheduled', 'Scheduled')} />
61
+ <Switch name="all" text={t('all', 'All')} />
62
+ </ContentSwitcher>
63
+
64
+ <VisitsTable visits={visits} isLoading={isLoading} tableHeading={heading} />
65
+ </div>
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export default PatientScoreboard;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+
4
+ import MetricsCard from '../metrics-card/metrics-card.component';
5
+ import { useActiveVisits } from '../hooks/useVisitList';
6
+
7
+ export default function ActiveVisitsCard() {
8
+ const { t } = useTranslation();
9
+ const { count, isLoading } = useActiveVisits();
10
+
11
+ return (
12
+ <MetricsCard
13
+ headerLabel={t('activeVisits', 'Active Visits')}
14
+ label={t('visits', 'Visits')}
15
+ value={isLoading ? '...' : count}
16
+ />
17
+ );
18
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+
4
+ import MetricsCard from '../metrics-card/metrics-card.component';
5
+ import { useScheduledVisits } from '../hooks/useVisitList';
6
+
7
+ export default function ScheduledVisitsCard() {
8
+ const { t } = useTranslation();
9
+ const { count, isLoading } = useScheduledVisits();
10
+
11
+ return (
12
+ <MetricsCard
13
+ headerLabel={t('pastVisits', 'Past Visits')}
14
+ label={t('visits', 'Visits')}
15
+ value={isLoading ? '...' : count}
16
+ />
17
+ );
18
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+
4
+ import MetricsCard from '../metrics-card/metrics-card.component';
5
+ import { useTotalVisits } from '../hooks/useVisitList';
6
+
7
+ export default function TotalVisitsCard() {
8
+ const { t } = useTranslation();
9
+ const { count, isLoading } = useTotalVisits();
10
+
11
+ return (
12
+ <MetricsCard
13
+ headerLabel={t('totalVisits', 'Total Visits')}
14
+ label={t('visits', 'Visits')}
15
+ value={isLoading ? '...' : count}
16
+ />
17
+ );
18
+ }
@@ -0,0 +1,31 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/colors';
3
+
4
+ .visitsTableContainer {
5
+ margin-top: layout.$spacing-06;
6
+ }
7
+
8
+ .tableHeader {
9
+ margin-bottom: layout.$spacing-05;
10
+
11
+ h4 {
12
+ font-size: 1.25rem;
13
+ font-weight: 600;
14
+ color: colors.$gray-100;
15
+ }
16
+ }
17
+
18
+ .link {
19
+ text-decoration: none;
20
+ color: colors.$blue-60;
21
+
22
+ &:hover {
23
+ text-decoration: underline;
24
+ }
25
+ }
26
+
27
+ .emptyState {
28
+ padding: layout.$spacing-06;
29
+ text-align: center;
30
+ color: colors.$gray-70;
31
+ }
@@ -0,0 +1,181 @@
1
+ import React, { useState, useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import dayjs from 'dayjs';
4
+ import {
5
+ DataTable,
6
+ DataTableSkeleton,
7
+ Search,
8
+ Table,
9
+ TableBody,
10
+ TableCell,
11
+ TableContainer,
12
+ TableHead,
13
+ TableHeader,
14
+ TableRow,
15
+ Pagination,
16
+ } from '@carbon/react';
17
+ import {
18
+ ConfigurableLink,
19
+ formatDatetime,
20
+ isDesktop,
21
+ useLayoutType,
22
+ usePagination,
23
+ useConfig,
24
+ type Visit,
25
+ } from '@openmrs/esm-framework';
26
+ import styles from './visits-table.component.scss';
27
+
28
+ interface VisitsTableProps {
29
+ visits: Array<Visit>;
30
+ isLoading: boolean;
31
+ tableHeading: string;
32
+ }
33
+
34
+ const VisitsTable: React.FC<VisitsTableProps> = ({ visits, isLoading, tableHeading }) => {
35
+ const { t } = useTranslation();
36
+ const [pageSize, setPageSize] = useState(25);
37
+ const [searchString, setSearchString] = useState('');
38
+ const layout = useLayoutType();
39
+ const responsiveSize = isDesktop(layout) ? 'sm' : 'lg';
40
+ const config = useConfig();
41
+ const customPatientChartUrl =
42
+ config?.customPatientChartUrl || '${openmrsSpaBase}/patient/${patientUuid}/chart/Visits';
43
+
44
+ const searchResults = useMemo(() => {
45
+ if (!visits || visits.length === 0) {
46
+ return [];
47
+ }
48
+ if (!searchString || searchString.trim() === '') {
49
+ return visits;
50
+ }
51
+
52
+ const search = searchString.toLowerCase();
53
+ return visits.filter((visit) => {
54
+ const patientName = visit.patient?.person?.display?.toLowerCase() || '';
55
+ const identifier = visit.patient?.identifiers?.[0]?.identifier?.toLowerCase() || '';
56
+ const location = visit.location?.display?.toLowerCase() || '';
57
+ const visitType = visit.visitType?.display?.toLowerCase() || '';
58
+
59
+ return (
60
+ patientName.includes(search) ||
61
+ identifier.includes(search) ||
62
+ location.includes(search) ||
63
+ visitType.includes(search)
64
+ );
65
+ });
66
+ }, [visits, searchString]);
67
+
68
+ const { results, goTo, currentPage } = usePagination(searchResults, pageSize);
69
+
70
+ const headerData = [
71
+ { header: t('patientName', 'Patient Name'), key: 'patientName' },
72
+ { header: t('identifier', 'Identifier'), key: 'identifier' },
73
+ { header: t('visitType', 'Visit Type'), key: 'visitType' },
74
+ { header: t('location', 'Location'), key: 'location' },
75
+ { header: t('startTime', 'Start Time'), key: 'startTime' },
76
+ { header: t('endTime', 'End Time'), key: 'endTime' },
77
+ { header: t('status', 'Status'), key: 'status' },
78
+ ];
79
+
80
+ const rowData = results?.map((visit) => {
81
+ const patientUuid = visit.patient?.uuid;
82
+ const patientName = visit.patient?.person?.display || '--';
83
+ const identifier = visit.patient?.identifiers?.[0]?.identifier || '--';
84
+ const visitType = visit.visitType?.display || '--';
85
+ const location = visit.location?.display || '--';
86
+ const startTime = visit.startDatetime ? formatDatetime(new Date(visit.startDatetime)) : '--';
87
+ const endTime = visit.stopDatetime ? formatDatetime(new Date(visit.stopDatetime)) : '--';
88
+ const status = visit.stopDatetime ? t('ended', 'Ended') : t('active', 'Active');
89
+
90
+ return {
91
+ id: visit.uuid,
92
+ patientName: patientUuid ? (
93
+ <ConfigurableLink className={styles.link} to={customPatientChartUrl} templateParams={{ patientUuid }}>
94
+ {patientName}
95
+ </ConfigurableLink>
96
+ ) : (
97
+ patientName
98
+ ),
99
+ identifier,
100
+ visitType,
101
+ location,
102
+ startTime,
103
+ endTime,
104
+ status,
105
+ };
106
+ });
107
+
108
+ const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
109
+ goTo(1);
110
+ setSearchString(e.target.value);
111
+ };
112
+
113
+ if (isLoading) {
114
+ return <DataTableSkeleton role="progressbar" rowCount={5} columnCount={headerData.length} />;
115
+ }
116
+
117
+ if (!visits || visits.length === 0) {
118
+ return (
119
+ <div className={styles.emptyState}>
120
+ <p>{t('noVisitsFound', 'No visits found')}</p>
121
+ </div>
122
+ );
123
+ }
124
+
125
+ return (
126
+ <div className={styles.visitsTableContainer}>
127
+ <div className={styles.tableHeader}>
128
+ <h4>{tableHeading}</h4>
129
+ </div>
130
+ <Search
131
+ labelText={t('searchVisits', 'Search visits')}
132
+ placeholder={t('searchTable', 'Search table')}
133
+ onChange={handleSearch}
134
+ size={responsiveSize}
135
+ value={searchString}
136
+ />
137
+ <DataTable rows={rowData} headers={headerData} isSortable size={responsiveSize} useZebraStyles>
138
+ {({ rows, headers, getHeaderProps, getTableProps }) => (
139
+ <TableContainer>
140
+ <Table {...getTableProps()}>
141
+ <TableHead>
142
+ <TableRow>
143
+ {headers.map((header) => (
144
+ <TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
145
+ ))}
146
+ </TableRow>
147
+ </TableHead>
148
+ <TableBody>
149
+ {rows.map((row) => (
150
+ <TableRow key={row.id}>
151
+ {row.cells.map((cell) => (
152
+ <TableCell key={cell.id}>{cell.value?.content ?? cell.value}</TableCell>
153
+ ))}
154
+ </TableRow>
155
+ ))}
156
+ </TableBody>
157
+ </Table>
158
+ </TableContainer>
159
+ )}
160
+ </DataTable>
161
+ {searchResults.length > pageSize && (
162
+ <Pagination
163
+ backwardText={t('previousPage', 'Previous page')}
164
+ forwardText={t('nextPage', 'Next page')}
165
+ itemsPerPageText={t('itemsPerPage', 'Items per page:')}
166
+ page={currentPage}
167
+ pageNumberText={t('pageNumber', 'Page number')}
168
+ pageSize={pageSize}
169
+ pageSizes={[10, 25, 50, 100]}
170
+ totalItems={searchResults.length}
171
+ onChange={({ page, pageSize }) => {
172
+ setPageSize(pageSize);
173
+ goTo(page);
174
+ }}
175
+ />
176
+ )}
177
+ </div>
178
+ );
179
+ };
180
+
181
+ export default VisitsTable;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { BrowserRouter, Route, Routes } from 'react-router-dom';
3
+ import { useLeftNav } from '@openmrs/esm-framework';
4
+
5
+ import { spaBasePath } from './constants';
6
+ import styles from './root.scss';
7
+
8
+ const Root: React.FC = () => {
9
+ useLeftNav({ name: 'clinical-workflow-left-panel-slot', basePath: spaBasePath });
10
+
11
+ return (
12
+ <BrowserRouter basename={spaBasePath}>
13
+ <main className={styles.container}>
14
+ <Routes></Routes>
15
+ </main>
16
+ </BrowserRouter>
17
+ );
18
+ };
19
+
20
+ export default Root;
package/src/root.scss ADDED
@@ -0,0 +1,10 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+
4
+ .container {
5
+ background-color: colors.$white-0;
6
+ }
7
+
8
+ :global(.omrs-breakpoint-gt-tablet) .container {
9
+ margin-left: var(--omrs-sidenav-width);
10
+ }
@@ -0,0 +1,108 @@
1
+ {
2
+ "$schema": "https://json.openmrs.org/routes.schema.json",
3
+ "backendDependencies": {
4
+ "fhir2": ">=1.2",
5
+ "webservices.rest": "^2.24.0"
6
+ },
7
+ "pages": [],
8
+ "extensions": [
9
+ {
10
+ "name": "clinical-workflow-triage-dashboard-link",
11
+ "component": "triageDashboardLink",
12
+ "slot": "homepage-dashboard-slot",
13
+ "order": 0,
14
+ "meta": {
15
+ "name": "clinical-workflow-triage",
16
+ "slot": "clinical-workflow-triage-dashboard-slot",
17
+ "title": "clinical-workflow-triage"
18
+ }
19
+ },
20
+ {
21
+ "name": "clinical-workflow-triage-dashboard",
22
+ "component": "triageDashboard",
23
+ "slot": "clinical-workflow-triage-dashboard-slot"
24
+ },
25
+ {
26
+ "name": "ewf-mru-dashboard-link",
27
+ "component": "mruLeftPanelLink",
28
+ "slot": "homepage-dashboard-slot",
29
+ "order": 1,
30
+ "meta": {
31
+ "name": "mru",
32
+ "title": "MRU",
33
+ "path": "mru",
34
+ "slot": "mru-dashboard-slot"
35
+ }
36
+ },
37
+ {
38
+ "name": "ewf-mru-dashboard",
39
+ "component": "mruDashboard",
40
+ "slot": "mru-dashboard-slot",
41
+ "online": true,
42
+ "offline": false
43
+ },
44
+ {
45
+ "name": "patient-scoreboard-link",
46
+ "component": "patientScoreboardLink",
47
+ "slot": "homepage-dashboard-slot",
48
+ "order": 1,
49
+ "meta": {
50
+ "name": "patient-scoreboard",
51
+ "title": "Patient Scoreboard",
52
+ "path": "patient-scoreboard",
53
+ "slot": "patient-scoreboard-slot"
54
+ }
55
+ },
56
+ {
57
+ "name": "patient-scoreboard",
58
+ "component": "patientScoreboard",
59
+ "slot": "patient-scoreboard-slot",
60
+ "online": true,
61
+ "offline": false
62
+ }
63
+ ],
64
+ "workspaces": [
65
+ {
66
+ "name": "triage-workspace",
67
+ "component": "triageWorkspace",
68
+ "title": "Triage Form",
69
+ "canMaximize": true,
70
+ "type": "clinical-form"
71
+ },
72
+ {
73
+ "name": "patient-registration-workspace",
74
+ "component": "patientRegistrationWorkspace",
75
+ "title": "Patient Registration",
76
+ "canMaximize": true,
77
+ "type": "registration-form"
78
+ },
79
+ {
80
+ "name": "billing-information-workspace",
81
+ "component": "billingInformationWorkspace",
82
+ "title": "Billing Information Workspace",
83
+ "type": "clinical-form"
84
+ }
85
+ ],
86
+ "workspaces2": [
87
+ {
88
+ "name": "clinical-workflow-patient-form-entry-workspace",
89
+ "component": "@openmrs/esm-patient-forms-app#exportedPatientFormEntryWorkspace",
90
+ "window": "clinical-workflow-window"
91
+ }
92
+ ],
93
+ "workspaceWindows2": [
94
+ {
95
+ "name": "clinical-workflow-window",
96
+ "group": "clinical-workflow-group",
97
+ "width": "wider",
98
+ "canMaximize": true
99
+ }
100
+ ],
101
+ "workspaceGroups2": [
102
+ {
103
+ "name": "clinical-workflow-group",
104
+ "overlay": true,
105
+ "persistence": "closable"
106
+ }
107
+ ]
108
+ }