diff --git a/packages/esm-admin-app/src/components/facility-setup/facility-info.component.tsx b/packages/esm-admin-app/src/components/facility-setup/facility-info.component.tsx new file mode 100644 index 000000000..e13e621a6 --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/facility-info.component.tsx @@ -0,0 +1,114 @@ +import React, { useEffect, useState } from 'react'; +import { Tile, Grid, Column, Layer, InlineLoading, Button } from '@carbon/react'; +import { useFacilityInfo } from '../hook/useFacilityInfo'; +import styles from './facility-info.scss'; +import { useTranslation } from 'react-i18next'; +import { showNotification, showSnackbar } from '@openmrs/esm-framework'; +import { FacilityData } from '../../types'; + +const FacilityInfo: React.FC = () => { + const { t } = useTranslation(); + const [shouldSynchronize, setshouldSynchronize] = useState(false); + const { defaultFacility, isLoading: defaultFacilityLoading, error, refetch } = useFacilityInfo(shouldSynchronize); + + const [facilityData, setFacilityData] = useState(defaultFacility); + useEffect(() => { + setFacilityData(defaultFacility); + if (defaultFacility?.operationalStatus !== 'Operational') { + showNotification({ kind: 'error', title: 'Error', description: 'The facility SHA status is is not operational' }); + } + }, [defaultFacility]); + + const synchronizeFacilityData = async () => { + try { + setshouldSynchronize(true); + await refetch(); + showSnackbar({ + title: t('syncingHieSuccess', 'Synchronization Complete'), + kind: 'success', + isLowContrast: true, + }); + } catch (error) { + const errorMessage = error?.responseBody?.error?.message ?? 'An error occurred while synchronizing with HIE'; + showSnackbar({ + title: t('syncingHieError', 'Syncing with HIE Failed'), + subtitle: errorMessage, + kind: 'error', + isLowContrast: true, + }); + } + }; + + return ( +
+
+ + {defaultFacilityLoading ? ( + + ) : ( + + )} + +
+ + + {/* General Info Column */} + + +

General Information

+
+
+

+ Facility Name: {facilityData?.display || 'N/A'} +

+

+ Facility KMHFR Code: {facilityData?.mflCode} +

+

+ Keph Level: {facilityData?.shaKephLevel} +

+
+
+
+
+
+ + {/* SHA Info Column */} + + + +

SHA Information

+
+
+

+ Facility Registry Code: {facilityData?.shaFacilityId} +

+

+ SHA License Number: {facilityData?.shaFacilityLicenseNumber} +

+

+ SHA Status: {facilityData?.operationalStatus} +

+

+ SHA Contracted: {facilityData?.shaContracted} +

+

+ SHA Expiry Date: {facilityData?.shaFacilityExpiryDate} +

+
+
+
+
+
+
+ ); +}; + +export default FacilityInfo; diff --git a/packages/esm-admin-app/src/components/facility-setup/facility-info.scss b/packages/esm-admin-app/src/components/facility-setup/facility-info.scss new file mode 100644 index 000000000..27fc2f244 --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/facility-info.scss @@ -0,0 +1,87 @@ +@use '@carbon/layout'; +@use '@carbon/type'; +@use '@carbon/colors'; + +.omrs-main-content { + background-color: colors.$white; +} + +.bottomBorder { + margin-bottom: layout.$spacing-05; +} + +.btnLayer { + display: flex; + padding-top: layout.$spacing-05; + padding-right: layout.$spacing-05; + padding-bottom: layout.$spacing-05; + margin-top: layout.$spacing-05; + flex-direction: row; + justify-content: flex-end; + background-color: white; + width: 100%; +} + +.tableLayer { + padding-left: layout.$spacing-05; + padding-right: layout.$spacing-05; + background: white; + padding-top: layout.$spacing-01; +} + +.loading { + display: flex; + padding-top: layout.$spacing-05; + padding-right: layout.$spacing-05; + padding-bottom: layout.$spacing-05; + margin-top: layout.$spacing-05; + flex-direction: row; + justify-content: flex-end; + background-color: white; + width: 100%; +} + +.facilityInfoContainer { + margin: layout.$spacing-05; +} + +.card { + padding: 1rem; + background-color: colors.$gray-10; + border: 1px solid #e0e0e0; + border-radius: 2px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.cardTitle { + margin-bottom: 1rem; + font-size: 1.25rem; + font-weight: 600; +} + +.cardDivider { + border: none; + border-top: 1px solid #e0e0e0; + margin: 0.5rem 0; +} +.cardContent { + font-size: 1rem; + line-height: 1.8; +} + +.cardContent p { + display: flex; + justify-content: space-between; + margin-bottom: 0.5rem; +} +.cardContent br { + display: flex; + justify-content: space-between; + margin-bottom: 0.5rem; +} + +.cardContent strong { + min-width: 150px; + display: inline-block; + color: #393939; +} diff --git a/packages/esm-admin-app/src/components/facility-setup/facility-setup.component.tsx b/packages/esm-admin-app/src/components/facility-setup/facility-setup.component.tsx new file mode 100644 index 000000000..467262137 --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/facility-setup.component.tsx @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Layer, Button, MenuItem, InlineLoading } from '@carbon/react'; +import styles from './facility-setup.scss'; +import FacilityInfo from './facility-info.component'; +import Header from './header/header.component'; +import { showSnackbar } from '@openmrs/esm-framework'; + +const FacilitySetup: React.FC = () => { + const { t } = useTranslation(); + return ( +
+
+ + + + +
+ ); +}; + +export default FacilitySetup; diff --git a/packages/esm-admin-app/src/components/facility-setup/facility-setup.scss b/packages/esm-admin-app/src/components/facility-setup/facility-setup.scss new file mode 100644 index 000000000..4407b7dd4 --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/facility-setup.scss @@ -0,0 +1,38 @@ +@use '@carbon/layout'; +@use '@carbon/type'; +@use '@carbon/colors'; + +.omrs-main-content { + background-color: white; +} + +.btnLayer { + display: flex; + padding-top: layout.$spacing-05; + padding-right: layout.$spacing-05; + padding-bottom: layout.$spacing-05; + margin-top: layout.$spacing-05; + flex-direction: row; + justify-content: flex-end; + background-color: white; + width: 100%; +} + +.tableLayer { + padding-left: layout.$spacing-05; + padding-right: layout.$spacing-05; + background: white; + padding-top: layout.$spacing-01; +} + +.loading { + display: flex; + padding-top: layout.$spacing-05; + padding-right: layout.$spacing-05; + padding-bottom: layout.$spacing-05; + margin-top: layout.$spacing-05; + flex-direction: row; + justify-content: flex-end; + background-color: white; + width: 100%; +} diff --git a/packages/esm-admin-app/src/components/facility-setup/header/header.component.tsx b/packages/esm-admin-app/src/components/facility-setup/header/header.component.tsx new file mode 100644 index 000000000..ae276726c --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/header/header.component.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Development } from '@carbon/react/icons'; +import { useSession, PageHeader } from '@openmrs/esm-framework'; +import styles from './header.scss'; + +interface HeaderProps { + title: string; +} + +const Header: React.FC = ({ title }) => { + const { t } = useTranslation(); + const session = useSession(); + const location = session?.sessionLocation?.display; + + return ( +
+ } className={styles.header} /> +
+ ); +}; + +export default Header; diff --git a/packages/esm-admin-app/src/components/facility-setup/header/header.scss b/packages/esm-admin-app/src/components/facility-setup/header/header.scss new file mode 100644 index 000000000..907b58f6b --- /dev/null +++ b/packages/esm-admin-app/src/components/facility-setup/header/header.scss @@ -0,0 +1,19 @@ +@use '@carbon/layout'; +@use '@carbon/type'; +@use '@carbon/colors'; + +.header { + @include type.type-style('body-compact-02'); + height: layout.$spacing-12; + display: flex; + justify-content: space-between; + padding: layout.$spacing-05; + background: white; + border: 1px solid colors.$gray-20; +} +.svgContainer svg { + width: layout.$spacing-10; + height: layout.$spacing-10; + margin-right: layout.$spacing-06; + fill: var(--brand-03); +} diff --git a/packages/esm-admin-app/src/components/hook/useFacilityInfo.tsx b/packages/esm-admin-app/src/components/hook/useFacilityInfo.tsx new file mode 100644 index 000000000..a3c60a681 --- /dev/null +++ b/packages/esm-admin-app/src/components/hook/useFacilityInfo.tsx @@ -0,0 +1,21 @@ +import { FetchResponse, openmrsFetch, restBaseUrl, useSession } from '@openmrs/esm-framework'; +import useSWR from 'swr'; +import { FacilityData } from '../../types'; + +export function useFacilityInfo(shouldSynchronize: boolean = false) { + const { authenticated } = useSession(); + const url = `${restBaseUrl}/kenyaemr/default-facility?synchronize=${shouldSynchronize}`; + + const { data, isLoading, error, mutate } = useSWR>( + authenticated ? url : null, + openmrsFetch, + {}, + ); + + return { + isLoading, + defaultFacility: data?.data, + error, + refetch: mutate, // Expose mutate as refetch + }; +} diff --git a/packages/esm-admin-app/src/components/logs-table/operation-log-table.component.tsx b/packages/esm-admin-app/src/components/logs-table/operation-log-table.component.tsx index f572b80e0..33e1fb5fe 100644 --- a/packages/esm-admin-app/src/components/logs-table/operation-log-table.component.tsx +++ b/packages/esm-admin-app/src/components/logs-table/operation-log-table.component.tsx @@ -49,7 +49,7 @@ const LogTable: React.FC = ({ logData, isLoading }) => { return (
- +
{isLoading && logData.length === 0 ? ( { const spaBasePath = window.spaBase; @@ -26,6 +27,7 @@ const Root: React.FC = () => { } /> } /> } /> + } /> diff --git a/packages/esm-admin-app/src/routes.json b/packages/esm-admin-app/src/routes.json index ac04a8b03..64b48e9a0 100755 --- a/packages/esm-admin-app/src/routes.json +++ b/packages/esm-admin-app/src/routes.json @@ -18,6 +18,11 @@ "component": "etlAdministrationLeftPannelLink", "name": "etl-administration-left-panel-link", "slot": "admin-left-panel-slot" + }, + { + "component": "facilitySetupLeftPanelLink", + "name": "facility-setup-left-panel-link", + "slot": "admin-left-panel-slot" } ], "workspaces": [ diff --git a/packages/esm-admin-app/src/types/index.ts b/packages/esm-admin-app/src/types/index.ts index ac81cd6dd..0bb3426ca 100644 --- a/packages/esm-admin-app/src/types/index.ts +++ b/packages/esm-admin-app/src/types/index.ts @@ -10,3 +10,26 @@ export interface DashboardConfig { slot: string; title: string; } +export interface FrontendModule { + name: string; + version?: string; +} +export interface DefaultFacility { + locationId: number; + uuid: string; + display: string; + operationalStatus: string; + shaContracted: string; + shaFacilityExpiryDate: string; +} + +export interface FacilityData { + shaKephLevel?: string; + mflCode?: string; + display?: string; + operationalStatus?: string; + shaContracted?: string; + shaFacilityId?: string; + shaFacilityLicenseNumber?: string; + shaFacilityExpiryDate?: string; +} diff --git a/packages/esm-admin-app/translations/en.json b/packages/esm-admin-app/translations/en.json index 67db1700e..5352f9795 100644 --- a/packages/esm-admin-app/translations/en.json +++ b/packages/esm-admin-app/translations/en.json @@ -10,8 +10,8 @@ "endTime": "End time", "etlAdministration": "ETL Admin", "etlOperation": "ETL operations", - "etlOperationLog": "ETL Operations Log", "etlsOperationsLoading": "Please wait {{currentOperation}} is in progress...", + "facilityInfo": "Facility Info", "familyName": "Family Name", "given": "Given", "home": "Home", @@ -35,6 +35,10 @@ "searchLabel": "Search", "searchUser": "Search user table", "startTime": "Start time", + "synchronizeWithHie": "Synchronize with HIE", + "synchronizingFacilityData": "Please wait, Synchronizing Info.", + "syncingHieError": "Syncing with HIE Failed", + "syncingHieSuccess": "Synchronization Complete", "systemId": "System ID", "userManagement": "User Management", "username": "Username", diff --git a/packages/esm-billing-app/translations/en.json b/packages/esm-billing-app/translations/en.json index e73d3d205..9ac8559b2 100644 --- a/packages/esm-billing-app/translations/en.json +++ b/packages/esm-billing-app/translations/en.json @@ -78,7 +78,6 @@ "delete": "Delete", "deleteBill": "Delete Bill", "description": "Description", - "diagnosis": "Diagnosis", "discard": "Discard", "discardClaim": "Discard Claim", "discount": "Discount", @@ -109,6 +108,7 @@ "enterRegExp": "Enter regular expression", "error": "Error", "errored": "Errored", + "errorEndingVisit": "Error ending visit", "errorFetchingPackages": "Error fetching packeges", "errorLoadingBillServices": "Error loading bill services", "errorLoadingPaymentModes": "Payment modes error", @@ -122,6 +122,7 @@ "filterBy": "Filter by", "filterByTimesheet": "Filter by timesheet", "filterTable": "Filter table", + "finalDiagnosis": "Final Diagnosis", "formTitle": "Fill in the form details", "generatedMessage": "The invoice has been electronically generated and is a valid document. It was created by {{userName}} on {{date}} at {{time}}", "home": "Home", @@ -200,7 +201,6 @@ "payments": "Payments", "paymentType": "Payment Type", "pendingHIEVerification": "Pending HIE verification", - "pendingVerificationReason": "", "Phone Number": "Phone Number", "pickLabRequest": "Pick Lab Request", "policyNumber": "Policy number", @@ -281,8 +281,9 @@ "unsettledBill": "Unsettled bill", "updateRegistration": "Update registration", "valuated": "Valuated", - "verify": "Verify", "verifyingBillStatus": "Verifying bill status...", + "visitEnded": "Visit ended", + "visitEndSuccessfully": "", "visitTime": "Visit time", "visittype": "Visit Type", "waiveBill": "Waive Bill", diff --git a/packages/esm-version-app/src/about/about.component.tsx b/packages/esm-version-app/src/about/about.component.tsx index 6f68ef9bc..8ad96f1fc 100644 --- a/packages/esm-version-app/src/about/about.component.tsx +++ b/packages/esm-version-app/src/about/about.component.tsx @@ -1,11 +1,8 @@ import React, { useEffect } from 'react'; import styles from './about.scss'; import { useModules } from '../hooks/useModules'; -import { useDefaultFacility, useSystemSetting } from '../hooks/useSystemSetting'; import { formatDate, formatDatetime, showNotification } from '@openmrs/esm-framework'; import FrontendModule from '../frontend-modules/frontend-modules.component'; -import { SkeletonText } from '@carbon/react'; -import dayjs from 'dayjs'; const packageInfo = require('../release-version.js'); interface AboutProps {} @@ -13,28 +10,8 @@ interface AboutProps {} const About: React.FC = () => { const { modules, isLoading } = useModules(); const kenyaEMR = modules.find(({ uuid }) => uuid === 'kenyaemr'); - const { mflCodeResource } = useSystemSetting('facility.mflcode'); - const mflCode = mflCodeResource ? `(${mflCodeResource?.value ?? ''})` : ''; const { title, container, aboutBody, aboutPage } = styles; const { VERSION } = packageInfo; - const { defaultFacility, error, isLoading: defaultFacilityLoading } = useDefaultFacility(); - - useEffect(() => { - if (!defaultFacility) { - return; - } - // Uncomment when dates are availed - /*if (!dayjs(defaultFacility?.shaFacilityExpiryDate).isValid()) { - showNotification({ kind: 'error', title: 'Error', description: 'Invalid SHA accreditation expiry date' }); - return; - } - if (dayjs(defaultFacility?.shaFacilityExpiryDate).isBefore(dayjs())) { - showNotification({ kind: 'error', title: 'Error', description: 'SHA accreditation Licence has expired' }); - }*/ - if (defaultFacility?.operationalStatus !== 'Operational') { - showNotification({ kind: 'error', title: 'Error', description: 'The facility SHA status is is not operational' }); - } - }, [defaultFacility]); return (
@@ -59,16 +36,6 @@ const About: React.FC = () => {

{`v${VERSION.version}`}

Build date time

{formatDatetime(new Date(VERSION.buildDate), { mode: 'standard' })}

-

Facility code

-

{mflCode ?? '--'}

-

Facility Name

- {defaultFacilityLoading ? :

{defaultFacility?.display ?? '--'}

} -

Operational status

- {defaultFacilityLoading ? :

{defaultFacility?.operationalStatus ?? '--'}

} -

Sha Contracted

- {defaultFacilityLoading ? :

--

} -

Expiry Date

- {defaultFacilityLoading ? :

{defaultFacility?.shaFacilityExpiryDate ?? '--'}

}
diff --git a/packages/esm-version-app/src/hooks/useSystemSetting.tsx b/packages/esm-version-app/src/hooks/useSystemSetting.tsx deleted file mode 100644 index 465d97a4e..000000000 --- a/packages/esm-version-app/src/hooks/useSystemSetting.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { FetchResponse, OpenmrsResource, openmrsFetch, restBaseUrl, useSession } from '@openmrs/esm-framework'; -import useSWRImmutable from 'swr/immutable'; -import useSWR from 'swr'; -import { DefaultFacility } from '../types'; - -export function useSystemSetting(key: string) { - const { data, isLoading } = useSWRImmutable<{ data: { results: Array } }>( - `/ws/rest/v1/systemsetting?q=${key}&v=full`, - openmrsFetch, - { - revalidateOnFocus: false, - revalidateOnReconnect: false, - }, - ); - - const mflCodeResource = data?.data?.results?.find((resource) => resource.property === 'facility.mflcode'); - - return { mflCodeResource, isLoading }; -} - -export function useDefaultFacility() { - const { authenticated } = useSession(); - const url = `${restBaseUrl}/kenyaemr/default-facility`; - const { data, isLoading, error } = useSWR>( - authenticated ? url : null, - openmrsFetch, - {}, - ); - return { - isLoading, - defaultFacility: data?.data, - error, - }; -}