@kenyaemr/esm-admin-app 5.4.2-pre.2430 → 5.4.2-pre.2432
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +9 -9
- package/dist/20.js +1 -0
- package/dist/20.js.map +1 -0
- package/dist/kenyaemr-esm-admin-app.js +1 -1
- package/dist/kenyaemr-esm-admin-app.js.buildmanifest.json +28 -28
- package/dist/kenyaemr-esm-admin-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/components/provider-banner/provider-banner.component.tsx +99 -0
- package/src/components/provider-banner/provider-banner.module.scss +50 -0
- package/src/components/provider-banner/provider-banner.resource.ts +29 -0
- package/src/index.ts +4 -0
- package/src/routes.json +6 -0
- package/dist/635.js +0 -1
- package/dist/635.js.map +0 -1
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemrCharts":"^1.6.7"},"extensions":[{"component":"adminLeftPanelLink","name":"admin-left-panel-link","slot":"admin-left-panel-slot"},{"component":"userManagementLeftPannelLink","name":"user-management-left-panel-link","slot":"admin-left-panel-slot"},{"component":"etlAdministrationLeftPannelLink","name":"etl-administration-left-panel-link","slot":"admin-left-panel-slot"},{"component":"locationsLeftPanelLink","name":"locations-left-panel-link","slot":"admin-left-panel-slot"},{"component":"facilitySetupLeftPanelLink","name":"facility-setup-left-panel-link","slot":"admin-left-panel-slot"}],"workspaces":[{"name":"manage-user-workspace","component":"manageUserWorkspace","title":"Manage User Workspace","type":"other-form","canMaximize":true,"width":"extra-wide"},{"name":"user-role-scope-workspace","component":"userRoleScopeWorkspace","title":"User Rple Scope Workspace","type":"other-form","canMaximize":true,"width":"extra-wide"},{"name":"add-location-workspace","title":"Add Location","component":"addLocation","type":"workspace"},{"name":"search-location-workspace","title":"Search Location","component":"searchLocationWorkspace","type":"workspace"},{"name":"hwr-sync-workspace","title":"HWR Sync Workspace","component":"hwrSyncWorkspace","type":"other-form"},{"name":"hwr-sync-modal","title":"HWR Sync Modal","component":"hwrSyncModal","type":"modal"}],"modals":[{"component":"operationConfirmationModal","name":"operation-confirmation-modal"},{"component":"hwrConfirmationModal","name":"hwr-confirmation-modal"},{"component":"hwrEmptyModal","name":"hwr-empty-modal"},{"component":"hwrSyncModal","name":"hwr-syncing-modal"}],"pages":[{"component":"root","route":"admin"}],"version":"5.4.2-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemrCharts":"^1.6.7"},"extensions":[{"component":"adminLeftPanelLink","name":"admin-left-panel-link","slot":"admin-left-panel-slot"},{"component":"userManagementLeftPannelLink","name":"user-management-left-panel-link","slot":"admin-left-panel-slot"},{"component":"etlAdministrationLeftPannelLink","name":"etl-administration-left-panel-link","slot":"admin-left-panel-slot"},{"component":"locationsLeftPanelLink","name":"locations-left-panel-link","slot":"admin-left-panel-slot"},{"component":"facilitySetupLeftPanelLink","name":"facility-setup-left-panel-link","slot":"admin-left-panel-slot"},{"component":"providerBanner","name":"provider-banner","slot":"top-nav-info-slot","order":1}],"workspaces":[{"name":"manage-user-workspace","component":"manageUserWorkspace","title":"Manage User Workspace","type":"other-form","canMaximize":true,"width":"extra-wide"},{"name":"user-role-scope-workspace","component":"userRoleScopeWorkspace","title":"User Rple Scope Workspace","type":"other-form","canMaximize":true,"width":"extra-wide"},{"name":"add-location-workspace","title":"Add Location","component":"addLocation","type":"workspace"},{"name":"search-location-workspace","title":"Search Location","component":"searchLocationWorkspace","type":"workspace"},{"name":"hwr-sync-workspace","title":"HWR Sync Workspace","component":"hwrSyncWorkspace","type":"other-form"},{"name":"hwr-sync-modal","title":"HWR Sync Modal","component":"hwrSyncModal","type":"modal"}],"modals":[{"component":"operationConfirmationModal","name":"operation-confirmation-modal"},{"component":"hwrConfirmationModal","name":"hwr-confirmation-modal"},{"component":"hwrEmptyModal","name":"hwr-empty-modal"},{"component":"hwrSyncModal","name":"hwr-syncing-modal"}],"pages":[{"component":"root","route":"admin"}],"version":"5.4.2-pre.2432"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { useSession } from '@openmrs/esm-framework';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { type Attribute, useProviderAttributes } from './provider-banner.resource';
|
|
4
|
+
import styles from './provider-banner.module.scss';
|
|
5
|
+
import { InlineLoading, Tag } from '@carbon/react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import upperCase from 'lodash-es/upperCase';
|
|
8
|
+
|
|
9
|
+
const ProviderBannerTag: React.FC = () => {
|
|
10
|
+
const { currentProvider } = useSession();
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const currentProviderUuid = currentProvider?.uuid;
|
|
13
|
+
const { isLoading, error, providerAttributes } = useProviderAttributes(currentProviderUuid);
|
|
14
|
+
|
|
15
|
+
const getAttributeValue = (attributes: Array<Attribute>, displayName: string): string => {
|
|
16
|
+
const attribute = attributes?.find((attr) => attr.attributeType.display === displayName);
|
|
17
|
+
return attribute?.value || '';
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getLicenseStatus = (expiryDate: string) => {
|
|
21
|
+
if (!expiryDate || expiryDate === '0000-00-00') {
|
|
22
|
+
return { status: 'unknown', message: t('unlicensed', 'Unlicensed'), tagType: 'magenta' as const };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const today = new Date();
|
|
26
|
+
const expiry = new Date(expiryDate);
|
|
27
|
+
const timeDiff = expiry.getTime() - today.getTime();
|
|
28
|
+
const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
|
29
|
+
|
|
30
|
+
if (daysDiff < 0) {
|
|
31
|
+
return { status: 'expired', message: t('licenseExpired', 'License Expired'), tagType: 'red' as const };
|
|
32
|
+
} else if (daysDiff <= 30) {
|
|
33
|
+
return { status: 'warning', message: t('expiresSoon', 'Expires Soon'), tagType: 'blue' as const };
|
|
34
|
+
} else if (daysDiff <= 90) {
|
|
35
|
+
return { status: 'caution', message: t('expiresIn3Months', 'Expires in 3 months'), tagType: 'teal' as const };
|
|
36
|
+
} else {
|
|
37
|
+
return { status: 'valid', message: t('validLicense', 'Valid License'), tagType: 'green' as const };
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const formatDate = (dateString: string): string => {
|
|
42
|
+
if (!dateString) {
|
|
43
|
+
return '0000-00-00';
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const date = new Date(dateString);
|
|
47
|
+
return date.toISOString().split('T')[0];
|
|
48
|
+
} catch {
|
|
49
|
+
return '0000-00-00';
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (isLoading) {
|
|
54
|
+
return (
|
|
55
|
+
<div className={styles.loading}>
|
|
56
|
+
<InlineLoading description={t('loadingState', 'loading' + '...')} />
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const name = upperCase(providerAttributes?.person?.display) || 'NONE';
|
|
62
|
+
const hwi = getAttributeValue(providerAttributes?.attributes, 'Provider unique identifier') || 'NONE';
|
|
63
|
+
const licenseExpiry = getAttributeValue(providerAttributes?.attributes, 'License Expiry Date');
|
|
64
|
+
const formattedExpiry = formatDate(licenseExpiry) || '0000-00-00';
|
|
65
|
+
const licenseStatus = getLicenseStatus(licenseExpiry);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className={styles.providerBanner}>
|
|
69
|
+
<div className={styles.bannerContent}>
|
|
70
|
+
<div className={styles.divider} />
|
|
71
|
+
<div className={styles.infoItem}>
|
|
72
|
+
<span className={styles.label}>{t('healthWorkerIdentifier', 'Health Worker Identifier' + ':')}</span>
|
|
73
|
+
<span className={styles.value}>{hwi}</span>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className={styles.divider} />
|
|
77
|
+
|
|
78
|
+
<div className={styles.infoItem}>
|
|
79
|
+
<span className={styles.label}>{t('licenseExpiry', 'License Expiry' + ':')}</span>
|
|
80
|
+
<span className={styles.value}>{formattedExpiry}</span>
|
|
81
|
+
<span className={styles.statusIndicator}>
|
|
82
|
+
<Tag size="md" type={licenseStatus.tagType}>
|
|
83
|
+
{licenseStatus.message}
|
|
84
|
+
</Tag>
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div className={styles.divider} />
|
|
89
|
+
|
|
90
|
+
<div className={styles.infoItem}>
|
|
91
|
+
<span className={styles.label}>{t('name', 'Name' + ':')}</span>
|
|
92
|
+
<span className={styles.value}>{name}</span>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default ProviderBannerTag;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
@use '@carbon/colors';
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use '@carbon/type';
|
|
4
|
+
|
|
5
|
+
.providerBanner {
|
|
6
|
+
position: relative;
|
|
7
|
+
padding: layout.$spacing-03 layout.$spacing-05;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.bannerContent {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
gap: layout.$spacing-04;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.infoItem {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: 6px;
|
|
21
|
+
flex-wrap: wrap;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.divider {
|
|
25
|
+
width: 1px;
|
|
26
|
+
height: layout.$spacing-06;
|
|
27
|
+
background-color: rgba(244, 244, 244, 0.4);
|
|
28
|
+
margin-inline-start: layout.$spacing-04;
|
|
29
|
+
}
|
|
30
|
+
.label {
|
|
31
|
+
color: colors.$white;
|
|
32
|
+
font-weight: 500;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
|
|
35
|
+
&::after {
|
|
36
|
+
content: '';
|
|
37
|
+
margin-left: layout.$spacing-01;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.value {
|
|
42
|
+
color: colors.$white;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.loading {
|
|
48
|
+
text-align: center;
|
|
49
|
+
padding: layout.$spacing-03 0;
|
|
50
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import useSWR from 'swr';
|
|
3
|
+
|
|
4
|
+
export interface ProviderAttributesResponse {
|
|
5
|
+
person: Person;
|
|
6
|
+
attributes: Array<Attribute>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Person {
|
|
10
|
+
display: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Attribute {
|
|
14
|
+
attributeType: AttributeType;
|
|
15
|
+
value: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AttributeType {
|
|
19
|
+
display: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const useProviderAttributes = (uuid: string) => {
|
|
23
|
+
const customRepresentation = 'custom:(person:(display),attributes:(attributeType:(display),value))';
|
|
24
|
+
const url = `${restBaseUrl}/provider/${uuid}?v=${customRepresentation}`;
|
|
25
|
+
|
|
26
|
+
const { isLoading, error, data } = useSWR<FetchResponse<ProviderAttributesResponse>>(url, openmrsFetch);
|
|
27
|
+
const providerAttributes = data?.data;
|
|
28
|
+
return { isLoading, error, providerAttributes };
|
|
29
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import UserRoleScopeWorkspace from './components/users/manage-users/manage-user-
|
|
|
11
11
|
import HWRSyncModal from './components/modal/hwr-sync.modal';
|
|
12
12
|
import AddLocationWorkspace from './components/locations/forms/add-location/add-location.workspace';
|
|
13
13
|
import SearchLocationWorkspace from './components/locations/forms/search-location/search-location.workspace';
|
|
14
|
+
import ProviderBannerTag from './components/provider-banner/provider-banner.component';
|
|
14
15
|
|
|
15
16
|
const options = {
|
|
16
17
|
featureName: 'esm-admin-app',
|
|
@@ -53,3 +54,6 @@ export const hwrSyncModal = getSyncLifecycle(HWRSyncModal, options);
|
|
|
53
54
|
|
|
54
55
|
export const addLocation = getSyncLifecycle(AddLocationWorkspace, options);
|
|
55
56
|
export const searchLocationWorkspace = getSyncLifecycle(SearchLocationWorkspace, options);
|
|
57
|
+
|
|
58
|
+
// t('providerBanner', 'Provider banner')
|
|
59
|
+
export const providerBanner = getSyncLifecycle(ProviderBannerTag, options);
|
package/src/routes.json
CHANGED
|
@@ -28,6 +28,12 @@
|
|
|
28
28
|
"component": "facilitySetupLeftPanelLink",
|
|
29
29
|
"name": "facility-setup-left-panel-link",
|
|
30
30
|
"slot": "admin-left-panel-slot"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"component": "providerBanner",
|
|
34
|
+
"name": "provider-banner",
|
|
35
|
+
"slot": "top-nav-info-slot",
|
|
36
|
+
"order":1
|
|
31
37
|
}
|
|
32
38
|
],
|
|
33
39
|
"workspaces": [
|