@kenyaemr/esm-adr-app 5.4.2-pre.2257

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 (77) hide show
  1. package/.turbo/turbo-build.log +32 -0
  2. package/dist/144.js +2 -0
  3. package/dist/144.js.LICENSE.txt +19 -0
  4. package/dist/144.js.map +1 -0
  5. package/dist/216.js +2 -0
  6. package/dist/216.js.LICENSE.txt +9 -0
  7. package/dist/216.js.map +1 -0
  8. package/dist/218.js +2 -0
  9. package/dist/218.js.LICENSE.txt +5 -0
  10. package/dist/218.js.map +1 -0
  11. package/dist/300.js +1 -0
  12. package/dist/389.js +1 -0
  13. package/dist/389.js.map +1 -0
  14. package/dist/405.js +2 -0
  15. package/dist/405.js.LICENSE.txt +5 -0
  16. package/dist/405.js.map +1 -0
  17. package/dist/41.js +2 -0
  18. package/dist/41.js.LICENSE.txt +9 -0
  19. package/dist/41.js.map +1 -0
  20. package/dist/410.js +1 -0
  21. package/dist/410.js.map +1 -0
  22. package/dist/470.js +1 -0
  23. package/dist/470.js.map +1 -0
  24. package/dist/495.js +1 -0
  25. package/dist/495.js.map +1 -0
  26. package/dist/537.js +1 -0
  27. package/dist/537.js.map +1 -0
  28. package/dist/562.js +2 -0
  29. package/dist/562.js.LICENSE.txt +5 -0
  30. package/dist/562.js.map +1 -0
  31. package/dist/780.js +1 -0
  32. package/dist/780.js.map +1 -0
  33. package/dist/837.js +2 -0
  34. package/dist/837.js.LICENSE.txt +29 -0
  35. package/dist/837.js.map +1 -0
  36. package/dist/876.js +1 -0
  37. package/dist/876.js.map +1 -0
  38. package/dist/89.js +1 -0
  39. package/dist/89.js.map +1 -0
  40. package/dist/913.js +2 -0
  41. package/dist/913.js.LICENSE.txt +32 -0
  42. package/dist/913.js.map +1 -0
  43. package/dist/914.js +1 -0
  44. package/dist/914.js.map +1 -0
  45. package/dist/917.js +2 -0
  46. package/dist/917.js.LICENSE.txt +48 -0
  47. package/dist/917.js.map +1 -0
  48. package/dist/kenyaemr-esm-adr-app.js +1 -0
  49. package/dist/kenyaemr-esm-adr-app.js.buildmanifest.json +602 -0
  50. package/dist/kenyaemr-esm-adr-app.js.map +1 -0
  51. package/dist/main.js +2 -0
  52. package/dist/main.js.LICENSE.txt +15 -0
  53. package/dist/main.js.map +1 -0
  54. package/dist/routes.json +1 -0
  55. package/jest.config.js +8 -0
  56. package/package.json +52 -0
  57. package/src/components/dashboard/dashboard-view.component.tsx +17 -0
  58. package/src/components/dashboard/dashboard-view.scss +5 -0
  59. package/src/components/dashboard/home-dashboard.component.tsx +30 -0
  60. package/src/components/dashboard/home-dashboard.scss +28 -0
  61. package/src/components/encounters/adr-encounter.component.tsx +165 -0
  62. package/src/components/encounters/encounter.resource.tsx +13 -0
  63. package/src/components/encounters/encounter.scss +26 -0
  64. package/src/components/header/header.component.tsx +8 -0
  65. package/src/components/patient-adr.workspace.tsx +79 -0
  66. package/src/components/side-menu/side-menu.component.tsx +6 -0
  67. package/src/components/summary/summary.component.tsx +84 -0
  68. package/src/components/summary/summary.scss +35 -0
  69. package/src/config-schema.ts +1 -0
  70. package/src/declarations.d.ts +2 -0
  71. package/src/index.ts +30 -0
  72. package/src/root.component.tsx +27 -0
  73. package/src/routes.json +47 -0
  74. package/src/types/index.ts +21 -0
  75. package/translations/en.json +12 -0
  76. package/tsconfig.json +5 -0
  77. package/webpack.config.js +1 -0
@@ -0,0 +1,79 @@
1
+ import React, { useMemo, useCallback } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { InlineLoading, InlineNotification } from '@carbon/react';
4
+ import { DefaultWorkspaceProps, ExtensionSlot, usePatient } from '@openmrs/esm-framework';
5
+ import { useVisitOrOfflineVisit } from '@openmrs/esm-patient-common-lib';
6
+
7
+ type encounter = {
8
+ formUuid: string;
9
+ encounterDatetime: string;
10
+ encounterType: string;
11
+ encounterUuid: string;
12
+ visitUuid: string;
13
+ patientUuid: string;
14
+ visitTypeUuid: string;
15
+ };
16
+
17
+ type PatientAdrWorkspaceProps = DefaultWorkspaceProps & {
18
+ encounter?: encounter;
19
+ };
20
+
21
+ export function PatientAdrWorkspace(props: PatientAdrWorkspaceProps) {
22
+ const { t } = useTranslation();
23
+ const { closeWorkspace, closeWorkspaceWithSavedChanges, promptBeforeClosing, encounter } = props;
24
+ const { formUuid, encounterUuid, visitUuid, patientUuid, visitTypeUuid } = encounter || {};
25
+ const { isLoading: isLoadingVisit, currentVisit, error: visitError } = useVisitOrOfflineVisit(patientUuid);
26
+ const { patient, isLoading: isLoadingPatient, error: patientError } = usePatient(patientUuid);
27
+ const state = useMemo<Record<string, unknown>>(
28
+ () => ({
29
+ view: 'form',
30
+ formUuid: formUuid ?? null,
31
+ visitUuid: visitUuid ?? null,
32
+ visitTypeUuid: visitTypeUuid ?? null,
33
+ patientUuid: patientUuid ?? null,
34
+ patient,
35
+ encounterUuid: encounterUuid ?? null,
36
+ closeWorkspaceWithSavedChanges,
37
+ closeWorkspace,
38
+ promptBeforeClosing,
39
+ }),
40
+ [
41
+ patientUuid,
42
+ encounterUuid,
43
+ patient,
44
+ closeWorkspace,
45
+ promptBeforeClosing,
46
+ formUuid,
47
+ visitUuid,
48
+ visitTypeUuid,
49
+ closeWorkspaceWithSavedChanges,
50
+ ],
51
+ );
52
+
53
+ const isLoading = isLoadingVisit || isLoadingPatient;
54
+ const error = visitError || patientError;
55
+
56
+ if (isLoading) {
57
+ return <InlineLoading description={t('loading', 'Loading')} iconDescription={t('loading', 'Loading data...')} />;
58
+ }
59
+
60
+ if (error) {
61
+ return (
62
+ <InlineNotification
63
+ aria-label={t('error', 'Error')}
64
+ kind="error"
65
+ onClose={() => {}}
66
+ onCloseButtonClick={() => {}}
67
+ statusIconDescription="notification"
68
+ subtitle={t('errorLoadingPatientWorkspace', 'Error loading patient workspace {{errorMessage}}', {
69
+ errorMessage: error?.message,
70
+ })}
71
+ title={t('error', 'Error')}
72
+ />
73
+ );
74
+ }
75
+
76
+ return <div>{patient && <ExtensionSlot name="form-widget-slot" state={state} />}</div>;
77
+ }
78
+
79
+ export default PatientAdrWorkspace;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { LeftNavMenu } from '@openmrs/esm-framework';
3
+
4
+ const SideMenu = () => <LeftNavMenu />;
5
+
6
+ export default SideMenu;
@@ -0,0 +1,84 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import dayjs from 'dayjs';
3
+
4
+ import styles from './summary.scss';
5
+ import AdrEncounter from '../encounters/adr-encounter.component';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { useAdrAssessmentEncounter } from '../encounters/encounter.resource';
8
+ import { DataTableSkeleton, DatePicker, DatePickerInput } from '@carbon/react';
9
+
10
+ type SummaryProps = {};
11
+
12
+ const Summary: React.FC<SummaryProps> = () => {
13
+ const { t } = useTranslation();
14
+ const defaultDateRange: [Date, Date] = [dayjs().startOf('day').toDate(), dayjs().endOf('day').toDate()];
15
+ const [dateRange, setDateRange] = useState<[Date, Date]>(defaultDateRange);
16
+ const formattedStartDate = dayjs(dateRange[0]).startOf('day').format('YYYY-MM-DDTHH:mm:ss');
17
+ const formattedEndDate = dayjs(dateRange[1]).endOf('day').format('YYYY-MM-DDTHH:mm:ss');
18
+ const { encounters, isLoading } = useAdrAssessmentEncounter(formattedStartDate, formattedEndDate);
19
+ const [counts, setCounts] = useState({
20
+ assessment: 0,
21
+ });
22
+
23
+ const handleDateRangeChange = ([start, end]: Array<Date>) => {
24
+ if (start && end) {
25
+ setDateRange([start, end]);
26
+ }
27
+ };
28
+
29
+ useEffect(() => {
30
+ const adrAssessmentCount = encounters.filter(
31
+ (encounter) => encounter.encounterTypeUuid === 'd18d6d8a-4be2-4115-ac7e-86cc0ec2b263',
32
+ ).length;
33
+
34
+ setCounts({
35
+ assessment: adrAssessmentCount,
36
+ });
37
+ }, [encounters]);
38
+
39
+ if (isLoading) {
40
+ return (
41
+ <div className={styles.loaderContainer}>
42
+ <DataTableSkeleton showHeader={false} showToolbar={false} zebra />
43
+ </div>
44
+ );
45
+ }
46
+
47
+ return (
48
+ <>
49
+ <div className={styles.filterContainer}>
50
+ <DatePicker
51
+ maxDate={new Date()}
52
+ datePickerType="range"
53
+ className={styles.dateRangePicker}
54
+ value={[...dateRange]}
55
+ onChange={handleDateRangeChange}>
56
+ <DatePickerInput
57
+ id="date-picker-input-id-start"
58
+ placeholder="mm/dd/yyyy"
59
+ labelText={t('startDate', 'Start date')}
60
+ size="md"
61
+ />
62
+ <DatePickerInput
63
+ id="date-picker-input-id-finish"
64
+ placeholder="mm/dd/yyyy"
65
+ labelText={t('endDate', 'End date')}
66
+ size="md"
67
+ />
68
+ </DatePicker>
69
+ </div>
70
+ <div className={styles.summaryContainer}>
71
+ <div className={styles.summaryCard}>
72
+ <h4>{t('adrAssessment', 'ADR Assessment')}</h4>
73
+ <div>
74
+ <h6>{t('totalAdrAssessment', 'Total ADR assessment')}</h6>
75
+ <p>{counts.assessment}</p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ <AdrEncounter encounters={encounters} />
80
+ </>
81
+ );
82
+ };
83
+
84
+ export default Summary;
@@ -0,0 +1,35 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/colors';
3
+
4
+ .summaryContainer {
5
+ display: flex;
6
+ flex-direction: row;
7
+ justify-content: space-between;
8
+ gap: layout.$spacing-05;
9
+ padding: layout.$spacing-05;
10
+ }
11
+
12
+ .summaryCard {
13
+ display: flex;
14
+ flex-direction: column;
15
+ justify-content: space-between;
16
+ gap: layout.$spacing-05;
17
+ padding: layout.$spacing-05;
18
+ border: 1px solid colors.$gray-20;
19
+ width: 100%;
20
+ height: 7.875rem;
21
+ background-color: colors.$white;
22
+ }
23
+
24
+ .dateRangePicker {
25
+ flex-grow: unset;
26
+ }
27
+ .filterContainer {
28
+ display: flex;
29
+ flex-wrap: wrap;
30
+ gap: layout.$spacing-05;
31
+ text-align: end;
32
+ align-items: center;
33
+ justify-content: flex-end;
34
+ padding: layout.$spacing-05;
35
+ }
@@ -0,0 +1 @@
1
+ export const configSchema = {};
@@ -0,0 +1,2 @@
1
+ declare module '*.css';
2
+ declare module '*.scss';
package/src/index.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { defineConfigSchema, getAsyncLifecycle, getSyncLifecycle } from '@openmrs/esm-framework';
2
+ import { configSchema } from './config-schema';
3
+ import AdrAssessmentApp from './root.component';
4
+ import { createDashboardLink } from '@openmrs/esm-patient-common-lib';
5
+ import SideMenu from './components/side-menu/side-menu.component';
6
+ import Summary from './components/summary/summary.component';
7
+
8
+ const moduleName = '@kenyaemr/esm-adr-app';
9
+
10
+ const options = {
11
+ featureName: 'adr-assessment',
12
+ moduleName,
13
+ };
14
+
15
+ export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
16
+
17
+ export const adrAssessmentApp = getSyncLifecycle(AdrAssessmentApp, options);
18
+ export const adrAssessmentSideNav = getSyncLifecycle(SideMenu, options);
19
+ export const adrAssessmentSummary = getSyncLifecycle(Summary, options);
20
+ export const patientAdrWorkspace = getAsyncLifecycle(() => import('./components/patient-adr.workspace'), options);
21
+
22
+ // Dashboard link for the search page
23
+ export const overviewDashboardLink = getSyncLifecycle(
24
+ createDashboardLink({ moduleName, path: 'overview', title: 'Overview', icon: '' }),
25
+ options,
26
+ );
27
+
28
+ export function startupApp() {
29
+ defineConfigSchema(moduleName, configSchema);
30
+ }
@@ -0,0 +1,27 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Routes, BrowserRouter, Route } from 'react-router-dom';
3
+ import { setLeftNav, unsetLeftNav, WorkspaceContainer } from '@openmrs/esm-framework';
4
+ import Dashboard from './components/dashboard/home-dashboard.component';
5
+
6
+ const AdrAssessmentApp = () => {
7
+ const spaBasePath = `${window.spaBase}/adr-assessment`;
8
+
9
+ useEffect(() => {
10
+ setLeftNav({ name: 'adr-assessment-page-dashboard-slot', basePath: spaBasePath });
11
+ return () => unsetLeftNav('adr-assessment-page-dashboard-slot');
12
+ }, [spaBasePath]);
13
+
14
+ return (
15
+ <main>
16
+ <BrowserRouter basename={window.spaBase}>
17
+ <Routes>
18
+ <Route path="/adr-assessment" element={<Dashboard />} />
19
+ <Route path="/adr-assessment/:dashboard/*" element={<Dashboard />} />
20
+ </Routes>
21
+ <WorkspaceContainer key="adr-assessment" contextKey="adr-assessment"></WorkspaceContainer>
22
+ </BrowserRouter>
23
+ </main>
24
+ );
25
+ };
26
+
27
+ export default AdrAssessmentApp;
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://json.openmrs.org/routes.schema.json",
3
+ "backendDependencies": {
4
+ "kenyaemr": "^19.0.0"
5
+ },
6
+ "pages": [
7
+ {
8
+ "component": "adrAssessmentApp",
9
+ "route": "adr-assessment"
10
+ }
11
+ ],
12
+ "workspaces": [
13
+ {
14
+ "name": "patient-adr-workspace",
15
+ "title": "ADR Assessment Review",
16
+ "component": "patientAdrWorkspace",
17
+ "type": "workspace",
18
+ "canMaximize": true,
19
+ "canHide": true,
20
+ "width": "extra-wide"
21
+ }
22
+
23
+
24
+ ],
25
+ "extensions": [
26
+ {
27
+ "name": "adr-assessment-side-nav",
28
+ "slot": "adr-assessment-side-nav-slot",
29
+ "component": "adrAssessmentSideNav"
30
+ },
31
+ {
32
+ "name": "adr-assessment-search-dashboard-db-link",
33
+ "slot": "adr-assessment-page-dashboard-slot",
34
+ "component": "overviewDashboardLink",
35
+ "meta": {
36
+ "name": "adr-assessment-overview",
37
+ "title": "Overview",
38
+ "slot": "adr-assessment-overview-dashboard-slot"
39
+ }
40
+ },
41
+ {
42
+ "name": "adr-assessment-summary",
43
+ "component": "adrAssessmentSummary",
44
+ "slot": "adr-assessment-overview-dashboard-slot"
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,21 @@
1
+ export type DashboardConfig = {
2
+ name: string;
3
+ slot: string;
4
+ title: string;
5
+ };
6
+
7
+ export interface MappedAdrEncounter {
8
+ encounterUuid: string;
9
+ encounterTypeUuid: string;
10
+ patientUuid: string;
11
+ patientName: string;
12
+ encounterType: string;
13
+ encounterDatetime: string;
14
+ visitTypeName: string;
15
+ formName: string;
16
+ location: string;
17
+ provider: string;
18
+ formUuid?: string;
19
+ visitUuid?: string;
20
+ visitTypeUuid?: string;
21
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "adrAssessment": "ADR Assessment",
3
+ "adrAssessmentEncounters": "ADR Assessment Encounters",
4
+ "encounters": "Encounters",
5
+ "endDate": "End date",
6
+ "noAdrEncountersFound": "Adr assessment encounters",
7
+ "noEncountersFoundTitle": "No encounters found",
8
+ "review": "Review",
9
+ "startDate": "Start date",
10
+ "summaryOfAdrAssessmentEncounters": "Summary of ADR assessment encounters",
11
+ "totalAdrAssessment": "Total ADR assessment"
12
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src/**/*"],
4
+ "exclude": ["src/**/*.test.tsx", "src/**/*.outdated.tsx"]
5
+ }
@@ -0,0 +1 @@
1
+ module.exports = require('openmrs/default-webpack-config');