From 14532c3c4cc3187544ff48cc8c72367a70f4a20f Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 16 Jan 2025 22:51:09 +0300 Subject: [PATCH 1/4] (refactor) follow up changes on the provider UI redesign --- .../src/component/providers.component.tsx | 43 +---- .../esm-providers-app/src/config-schema.ts | 6 + .../content-switcher.component.tsx | 98 ----------- .../src/header/providers-header.component.tsx | 47 +----- .../src/header/providers-header.scss | 111 +------------ .../providers-illustration.component.tsx | 4 +- .../header/providers-metrics.component.tsx | 16 -- .../src/overview/overview.component.tsx | 35 ++++ .../overview.scss} | 0 .../src/table/generic-data-table.scss | 3 + .../table/provider-data-table.component.tsx | 100 +++++++++--- .../src/table/provider-details.component.tsx | 154 +++++++----------- .../src/table/provider-details.scss | 52 ++++-- packages/esm-providers-app/src/types/index.ts | 1 + .../src/workspace/provider-form.workspace.tsx | 83 ++++++---- 15 files changed, 290 insertions(+), 463 deletions(-) delete mode 100644 packages/esm-providers-app/src/content-switcher/content-switcher.component.tsx delete mode 100644 packages/esm-providers-app/src/header/providers-metrics.component.tsx create mode 100644 packages/esm-providers-app/src/overview/overview.component.tsx rename packages/esm-providers-app/src/{content-switcher/content-switcher.scss => overview/overview.scss} (100%) diff --git a/packages/esm-providers-app/src/component/providers.component.tsx b/packages/esm-providers-app/src/component/providers.component.tsx index 8c51ae045..7fb98e7f8 100755 --- a/packages/esm-providers-app/src/component/providers.component.tsx +++ b/packages/esm-providers-app/src/component/providers.component.tsx @@ -1,53 +1,16 @@ import React from 'react'; import { ProvidersHeader } from '../header/providers-header.component'; -import { ContentSwitchTabs } from '../content-switcher/content-switcher.component'; import { useProviders } from '../table/provider-data-table.resource'; import dayjs from 'dayjs'; import { ConfigObject } from '../config-schema'; import { useConfig } from '@openmrs/esm-framework'; +import { Overview } from '../overview/overview.component'; const ProvidersComponent: React.FC = () => { - const { provider, error, isLoading } = useProviders(); - const { licenseNumberUuid, licenseExpiryDateUuid, providerNationalIdUuid } = useConfig(); - - const activeProviders = provider.filter((provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; - - return nationalId && licenseAttr && licenseExpiryDate && licenseExpiryDate.isAfter(dayjs()); - }); - - const expiredProviders = provider.filter((provider) => { - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; - - return licenseExpiryDate && licenseExpiryDate.isBefore(dayjs()); - }); - - const missingNationalId = provider.filter((provider) => { - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - return !nationalId; - }); - const missingLicenseOrExpiry = provider.filter((provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - - return nationalId && (!licenseAttr || !expiryAttr); - }); - const summarize = { - all: provider.length, - active: activeProviders.length, - expired: expiredProviders.length, - missingNationalId: missingNationalId.length, - missingLicenseOrExpiry: missingLicenseOrExpiry.length, - }; return (
- - + +
); }; diff --git a/packages/esm-providers-app/src/config-schema.ts b/packages/esm-providers-app/src/config-schema.ts index 047e0058c..86f52b00c 100755 --- a/packages/esm-providers-app/src/config-schema.ts +++ b/packages/esm-providers-app/src/config-schema.ts @@ -32,6 +32,11 @@ export const configSchema = { _description: 'UUID for provider licensing body', _default: 'bcaaa67b-cc72-4662-90c2-e1e992ceda66', }, + providerHieFhirReference: { + _type: Type.String, + _description: 'UUID for provider hie fhir reference', + _default: '67b94e8e-4d61-4810-b0f1-d86497f6e553', + }, defaultPrimaryFacility: { _type: Type.String, _description: 'Default facility for a provider', @@ -64,6 +69,7 @@ export interface ConfigObject { nationalIDUuid: string; passportNumberUuid: string; licenseExpiryDateUuid: string; + providerHieFhirReference: string; licenseBodyUuid: string; providerNationalIdUuid: string; licenseNumberUuid: string; diff --git a/packages/esm-providers-app/src/content-switcher/content-switcher.component.tsx b/packages/esm-providers-app/src/content-switcher/content-switcher.component.tsx deleted file mode 100644 index 492267979..000000000 --- a/packages/esm-providers-app/src/content-switcher/content-switcher.component.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React, { useState } from 'react'; -import { ContentSwitcher, Switch, Button } from '@carbon/react'; -import { useTranslation } from 'react-i18next'; -import styles from './content-switcher.scss'; -import { launchWorkspace, useConfig } from '@openmrs/esm-framework'; -import { Friendship } from '@carbon/react/icons'; -import ProviderListTable from '../table/provider-data-table.component'; -import dayjs from 'dayjs'; -import { ConfigObject } from '../config-schema'; -export const ContentSwitchTabs: React.FC = () => { - const { t } = useTranslation(); - const { licenseNumberUuid, licenseExpiryDateUuid, providerNationalIdUuid } = useConfig(); - - const switchTabs = [ - { - name: t('providersWithActiveLicenses', 'Active license'), - filter: (provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; - - return nationalId && licenseAttr && licenseExpiryDate && licenseExpiryDate.isAfter(dayjs()); - }, - }, - { - name: t('expiringedLicenses', 'Expiring(ed) licenses'), - filter: (provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; - - return licenseAttr && nationalId && licenseExpiryDate && licenseExpiryDate.diff(dayjs(), 'day') <= 3; - }, - }, - { - name: t('missingNationalIDs', 'Missing national id'), - filter: (provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - return !nationalId && !licenseAttr && !expiryAttr; - }, - }, - { - name: t('WithMissingLicenses', 'Missing license'), - filter: (provider) => { - const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); - const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); - const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); - return nationalId && (!licenseAttr || !expiryAttr); - }, - }, - ]; - - const [activeIndex, setActiveIndex] = useState(0); - - const handleRegisterProvider = () => { - launchWorkspace('provider-register-form', { - workspaceTitle: 'Register account form', - }); - }; - - const handleSwitchChange = (event) => { - setActiveIndex(event.index); - }; - - return ( - <> -
-
- - {switchTabs.map((tab, index) => ( - - ))} - -
- -
- -
- -
- - ); -}; diff --git a/packages/esm-providers-app/src/header/providers-header.component.tsx b/packages/esm-providers-app/src/header/providers-header.component.tsx index db32cef5f..962d30cc4 100755 --- a/packages/esm-providers-app/src/header/providers-header.component.tsx +++ b/packages/esm-providers-app/src/header/providers-header.component.tsx @@ -1,53 +1,18 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Calendar, Location } from '@carbon/react/icons'; -import { useSession, formatDate } from '@openmrs/esm-framework'; +import { useSession, formatDate, PageHeader } from '@openmrs/esm-framework'; import styles from './providers-header.scss'; import ProvidersIllustration from './providers-illustration.component'; -import { MetricCard } from './providers-metrics.component'; -interface ProviderHeaderProps { - title: string; - summarize: { - all: number; - active: number; - expired: number; - missingNationalId: number; - missingLicenseOrExpiry: number; - }; -} -export const ProvidersHeader: React.FC = ({ title, summarize }) => { +export const ProvidersHeader: React.FC = () => { const { t } = useTranslation(); - const userSession = useSession(); - const userLocation = userSession?.sessionLocation?.display; return ( -
-
- -
-

{title}

-

{t('providerManagement', 'Providers Management')}

-
+ <> +
+ } />
-
- - - - - - -
-
- - {userLocation} - - - {formatDate(new Date(), { mode: 'standard' })} - -
-
-
-
+ ); }; diff --git a/packages/esm-providers-app/src/header/providers-header.scss b/packages/esm-providers-app/src/header/providers-header.scss index a2af8c724..0e48de144 100755 --- a/packages/esm-providers-app/src/header/providers-header.scss +++ b/packages/esm-providers-app/src/header/providers-header.scss @@ -2,117 +2,18 @@ @use '@carbon/type'; @use '@carbon/colors'; -.header__section__container { +.header { @include type.type-style('body-compact-02'); - color: colors.$gray-70; height: layout.$spacing-12; - background-color: white; - border: 1px solid colors.$gray-20; - border-left: 0; display: flex; justify-content: space-between; - align-items: center; - margin-bottom: layout.$spacing-01; - margin-right: 0; - overflow-x: hidden; - padding: 0 layout.$spacing-05; -} - -.left__justified__items { - display: flex; - flex-direction: row; - align-items: center; - margin-left: layout.$spacing-04; -} - -.page__name { - @include type.type-style('heading-04'); -} - -.page__labels { - margin-left: 1rem; - - p:first-of-type { - margin-bottom: layout.$spacing-02; - } + background: white; + border: 1px solid colors.$gray-20; } - -.svg__container svg { +.svgContainer svg { width: layout.$spacing-10; height: layout.$spacing-10; + margin-right: layout.$spacing-03; + margin-left: layout.$spacing-06; fill: var(--brand-03); } - -.metrics__header { - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: center; - gap: layout.$spacing-06; - flex-wrap: wrap; - padding: layout.$spacing-04 layout.$spacing-05 0 0; - margin-right: layout.$spacing-09; - width: auto; - height: auto; -} - -.warp__metrics { - width: auto; - height: auto; - flex-grow: 1; - display: flex; - flex-direction: column; - justify-content: center; - align-items: flex-start; - gap: layout.$spacing-03; - padding: 0; - min-width: layout.$spacing-12; -} - -.metric__label { - flex-grow: 0; - font-family: IBMPlexSans; - font-size: layout.$spacing-04; - line-height: layout.$spacing-06; - letter-spacing: layout.$spacing-01; - color: colors.$gray-70; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.metric__value { - flex-grow: 0; - font-size: layout.$spacing-06; - line-height: layout.$spacing-06; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.metricLocationDate { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - gap: layout.$spacing-05; - width: auto; -} - -.location, -.date { - display: flex; - align-items: center; - font-size: layout.$spacing-05; - line-height: layout.$spacing-06; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.location { - margin-bottom: layout.$spacing-02; -} diff --git a/packages/esm-providers-app/src/header/providers-illustration.component.tsx b/packages/esm-providers-app/src/header/providers-illustration.component.tsx index 203750e3c..3b58f36cf 100755 --- a/packages/esm-providers-app/src/header/providers-illustration.component.tsx +++ b/packages/esm-providers-app/src/header/providers-illustration.component.tsx @@ -4,8 +4,8 @@ import { MedicalStaff } from '@carbon/pictograms-react'; const ProvidersIllustration: React.FC = () => { return ( -
- +
+
); }; diff --git a/packages/esm-providers-app/src/header/providers-metrics.component.tsx b/packages/esm-providers-app/src/header/providers-metrics.component.tsx deleted file mode 100644 index 790ca7b9d..000000000 --- a/packages/esm-providers-app/src/header/providers-metrics.component.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import styles from './providers-header.scss'; - -interface MetricCardProps { - label: string; - value: string | number; -} - -export const MetricCard: React.FC = ({ label, value }) => { - return ( -
- {label} - {value} -
- ); -}; diff --git a/packages/esm-providers-app/src/overview/overview.component.tsx b/packages/esm-providers-app/src/overview/overview.component.tsx new file mode 100644 index 000000000..4cc7a8936 --- /dev/null +++ b/packages/esm-providers-app/src/overview/overview.component.tsx @@ -0,0 +1,35 @@ +import { Button } from '@carbon/react'; +import { Friendship } from '@carbon/react/icons'; +import { launchWorkspace } from '@openmrs/esm-framework'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import ProviderListTable from '../table/provider-data-table.component'; +import styles from './overview.scss'; +export const Overview: React.FC = () => { + const { t } = useTranslation(); + + const handleRegisterProvider = () => { + launchWorkspace('provider-register-form', { + workspaceTitle: 'Register account form', + }); + }; + + return ( + <> +
+ +
+ +
+ +
+ + ); +}; diff --git a/packages/esm-providers-app/src/content-switcher/content-switcher.scss b/packages/esm-providers-app/src/overview/overview.scss similarity index 100% rename from packages/esm-providers-app/src/content-switcher/content-switcher.scss rename to packages/esm-providers-app/src/overview/overview.scss diff --git a/packages/esm-providers-app/src/table/generic-data-table.scss b/packages/esm-providers-app/src/table/generic-data-table.scss index 7a3c4d5d6..e0a0aac0d 100644 --- a/packages/esm-providers-app/src/table/generic-data-table.scss +++ b/packages/esm-providers-app/src/table/generic-data-table.scss @@ -150,3 +150,6 @@ svg.iconOverrides { height: layout.$spacing-11; fill: var(--brand-03); } +.dropDown { + margin-right: layout.$spacing-03; +} diff --git a/packages/esm-providers-app/src/table/provider-data-table.component.tsx b/packages/esm-providers-app/src/table/provider-data-table.component.tsx index ed48d0382..6cf877edb 100644 --- a/packages/esm-providers-app/src/table/provider-data-table.component.tsx +++ b/packages/esm-providers-app/src/table/provider-data-table.component.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { DataTableSkeleton, @@ -15,7 +15,7 @@ import { TableExpandRow, TableExpandedRow, Search, - Tag, + Dropdown, } from '@carbon/react'; import { isDesktop, useConfig, useLayoutType, usePagination } from '@openmrs/esm-framework'; import { ErrorState, CardHeader, usePaginationInfo } from '@openmrs/esm-patient-common-lib'; @@ -26,19 +26,62 @@ import { ConfigObject } from '../config-schema'; import dayjs from 'dayjs'; import CustomActionMenu from '../overflow/overflow-component'; import EmptyProviderState from './empty-state.component'; -import { Report, SearchLocate } from '@carbon/react/icons'; +import { Report } from '@carbon/react/icons'; -const ProviderListTable: React.FC<{ filter: (provider: any) => boolean }> = ({ filter }) => { +const ProviderListTable: React.FC = () => { const { t } = useTranslation(); const layout = useLayoutType(); const responsiveSize = isDesktop(layout) ? 'sm' : 'lg'; const { provider, error, isLoading } = useProviders(); const { licenseNumberUuid, licenseExpiryDateUuid, providerNationalIdUuid } = useConfig(); - const [pageSize, setPageSize] = React.useState(10); - const [searchQuery, setSearchQuery] = React.useState(''); + const [pageSize, setPageSize] = useState(10); + const [searchQuery, setSearchQuery] = useState(''); + const [selectedFilter, setSelectedFilter] = useState('All Providers'); // Default filter to "All Providers" + + // Helper functions for filtering + const isActiveLicensed = (provider) => { + const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); + const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); + const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; + return licenseAttr && licenseExpiryDate && licenseExpiryDate.isAfter(dayjs()); + }; + + const isExpiredLicensed = (provider) => { + const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); + const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; + return licenseExpiryDate && licenseExpiryDate.isBefore(dayjs()); + }; + + const isExpiringSoon = (provider) => { + const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); + const licenseExpiryDate = expiryAttr ? dayjs(expiryAttr.value) : null; + const today = dayjs(); + return ( + licenseExpiryDate && + licenseExpiryDate.isAfter(today) && + licenseExpiryDate.diff(today, 'day') > 0 && + licenseExpiryDate.diff(today, 'day') <= 3 + ); + }; + + const isUnlicensed = (provider) => { + const nationalId = provider.attributes.find((attr) => attr.attributeType.uuid === providerNationalIdUuid); + return !nationalId; + }; const filteredProviders = Array.isArray(provider) - ? provider.filter((p) => filter(p) && p.person.display.toLowerCase().includes(searchQuery.toLowerCase())) + ? provider.filter((p) => { + const matchesSearch = p.person.display.toLowerCase().includes(searchQuery.toLowerCase()); + + const matchesFilter = + selectedFilter === 'All Providers' || + (selectedFilter === 'Active Licensed' && isActiveLicensed(p)) || + (selectedFilter === 'Expired Licensed' && isExpiredLicensed(p)) || + (selectedFilter === 'Licensed expiring soon' && isExpiringSoon(p)) || + (selectedFilter === 'Unlicensed' && isUnlicensed(p)); + + return matchesSearch && matchesFilter; + }) : []; const { paginated, goTo, results, currentPage } = usePagination(filteredProviders, pageSize); @@ -50,16 +93,7 @@ const ProviderListTable: React.FC<{ filter: (provider: any) => boolean }> = ({ f { header: t('action', 'Action'), key: 'action' }, ]; - const maskNationalId = (id) => { - if (id && id.length > 5) { - const start = id.slice(0, 3); - const end = id.slice(-3); - return `${start}***${end}`; - } - return id; - }; - - const rowData = results.map((provider, index) => { + const rowData = results.map((provider) => { const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); return { id: provider.uuid, @@ -85,9 +119,36 @@ const ProviderListTable: React.FC<{ filter: (provider: any) => boolean }> = ({ f return (
- - <> + + item.text} + items={[ + { text: 'All Providers' }, + { text: 'Active Licensed' }, + { text: 'Expired Licensed' }, + { text: 'Licensed expiring soon' }, + { text: 'Unlicensed' }, + ]} + onChange={({ selectedItem }) => setSelectedFilter(selectedItem?.text || 'All Providers')} + /> + boolean }> = ({ f )} )} + {paginated && ( = ({ providerUuid }) => { const { t } = useTranslation(); + const patientBannerRef = useRef(null); const { provider } = useProviderDetails(providerUuid); const { user, isLoading, error } = useProviderUser(providerUuid); @@ -34,17 +26,23 @@ const ProviderDetails: React.FC = ({ providerUuid }) => { const expiryDate = dateAttr?.value ? dayjs(dateAttr.value) : null; const daysUntilExpiry = expiryDate ? expiryDate.diff(today, 'day') : null; - let licenseStatus; + const getLicenseStatusTag = () => { + if (!licenseAttr?.value) { + return {t('unlicensed', 'Unlicensed')}; + } - if (!expiryDate) { - licenseStatus = {t('missingExpiryDate', 'Missing expiry date')}; - } else if (daysUntilExpiry < 0) { - licenseStatus = {t('licenseExpired', 'License has expired')}; - } else if (daysUntilExpiry <= 3) { - licenseStatus = {t('licenseExpiringSoon', 'License is expiring soon')}; - } else { - licenseStatus = {t('activeLicensed', 'Active License')}; - } + if (daysUntilExpiry < 0) { + return {t('licenseExpired', 'License has expired')}; + } else if (daysUntilExpiry <= 3) { + return ( + <> + {t('licenseExpiringSoon', 'License is expiring soon')} + + ); + } else { + return {t('active', 'Active')}; + } + }; if (isLoading) { return
{t('loading', 'Loading...')}
; @@ -56,80 +54,40 @@ const ProviderDetails: React.FC = ({ providerUuid }) => { return (
-
-
- - <> - +
+
+
+ +
+
+ {/* Patient Name, Gender, and License Status */} +
+
+ {user?.person?.display} · + + {user?.person?.gender === 'M' ? 'Male' : user?.person?.gender === 'F' ? 'Female' : ''} ·{' '} + + {getLicenseStatusTag()} +
+
+ + {/* National ID and License Number */} +
+
+ + {t('nationalId', 'National ID')}: {nationalID?.value ? nationalID.value : '--'} + + · + + + {t('licenseNumber', 'License number')}: {licenseAttr?.value ? licenseAttr.value : '--'} + +
+
+
+
- - - - - -
- -
- - {' '} -
-
{user?.person?.display}
-
- {t('Gender', 'Gender')}: {user?.person?.gender} -
-
-
- {t('nationalID', 'National ID')}: - - {nationalID?.value ? ( - {nationalID.value} - ) : ( - {t('missingIDno', 'Missing National ID')} - )} - -
-
- {t('licenseNumber', 'License Number')}: - - {licenseAttr?.value ? ( - {licenseAttr.value} - ) : ( - {t('unlicensed', 'Unlicensed')} - )} - -
-
- {t('expiryDate', 'Expiry Date')}: - - {formattedExpiryDate ? ( - <> - {formattedExpiryDate} - {licenseStatus} - - ) : ( - {t('missingExpiryDate', 'Missing Expiry Date')} - )} - -
-
- {t('roles', 'Roles')}: - {user?.allRoles.map((role) => role.display).join(', ')} -
-
-
-
-
-
-
-
-
+
); }; diff --git a/packages/esm-providers-app/src/table/provider-details.scss b/packages/esm-providers-app/src/table/provider-details.scss index f469ecd58..6a1bdf53d 100644 --- a/packages/esm-providers-app/src/table/provider-details.scss +++ b/packages/esm-providers-app/src/table/provider-details.scss @@ -1,36 +1,58 @@ @use '@carbon/layout'; @use '@carbon/type'; @use '@carbon/colors'; +@use '@openmrs/esm-styleguide/src/vars' as *; -.providerName { - @include type.type-style('label-01'); - color: $text-02; - margin-bottom: spacing.$spacing-02; +.patientName { + @include type.type-style('label-02'); + color: colors.$gray-100; font-weight: 800; + margin-left: layout.$spacing-04; + margin-right: layout.$spacing-01; +} +.middot { + margin: 0 0.25rem; +} +.nationalId { + margin-top: layout.$spacing-04; + margin-left: layout.$spacing-04; + margin-right: layout.$spacing-01; } +.gender { + display: flex; + align-items: center; + color: colors.$gray-70; + gap: layout.$spacing-01; + margin-left: layout.$spacing-02; +} +.statusTag { + display: flex; + align-items: center; + color: colors.$gray-70; + gap: layout.$spacing-01; + margin-left: layout.$spacing-02; +} .demographics { display: flex; align-items: center; - margin-bottom: spacing.$spacing-02; + margin-bottom: layout.$spacing-02; color: $text-02; text-transform: uppercase; } -.identifiers { +.patientBanner { display: flex; - flex-direction: column; } -.middot { - margin: 0 0.25rem; -} -.formClaimRow { +.patientInfo { display: flex; - flex-wrap: nowrap; - gap: spacing.$spacing-05; + flex-direction: column; + width: 100%; } -.formClaimColumn { - flex: 1 1 0%; +.flexRow { + display: flex; + flex-flow: row wrap; + align-items: center; } diff --git a/packages/esm-providers-app/src/types/index.ts b/packages/esm-providers-app/src/types/index.ts index c7d3f4c33..85fb3350b 100644 --- a/packages/esm-providers-app/src/types/index.ts +++ b/packages/esm-providers-app/src/types/index.ts @@ -59,6 +59,7 @@ interface Person { familyName: string; }; gender: string; + birthdate: string; attributes: PersonAttribute[]; } diff --git a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx index 9437b2150..9a272992d 100644 --- a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx +++ b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx @@ -81,6 +81,7 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u licenseNumberUuid, licenseBodyUuid, identifierTypes, + providerHieFhirReference, } = useConfig(); const [searchHWR, setSearchHWR] = useState({ @@ -88,6 +89,7 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u identifier: '', isHWRLoading: false, }); + const [healthWorker, setHealthWorker] = useState(null); const definedRoles = roles.map((role) => role.uuid) || []; const licenseDate = provider?.attributes?.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid)?.value; @@ -118,39 +120,48 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u const handleSearch = async () => { try { setSearchHWR({ ...searchHWR, isHWRLoading: true }); - const healthWorker: Practitioner = await searchHealthCareWork(searchHWR.identifierType, searchHWR.identifier); - const nationalId = healthWorker?.entry[0]?.resource.identifier?.find((id) => - id.type?.coding?.some((code) => code.code === 'national-id'), - )?.value; - const licenseNumber = healthWorker?.entry[0]?.resource.identifier?.find((id) => - id.type?.coding?.some((code) => code.code === 'license-number'), - )?.value; - const registrationNumber = healthWorker?.entry[0]?.resource.identifier?.find((id) => - id.type?.coding?.some((code) => code.code === 'board-registration-number'), - )?.value; - - const licenseDate = formatDate( - new Date( - healthWorker?.entry[0]?.resource.identifier?.find((id) => - id.type?.coding?.some((code) => code.code === 'license-number'), - )?.period?.end || t('unknown', 'Unknown'), - ), + const fetchedHealthWorker: Practitioner = await searchHealthCareWork( + searchHWR.identifierType, + searchHWR.identifier, ); - const Names = healthWorker?.entry[0].resource?.name[0].text; - const nameParts = Names.split(' '); - const surname = nameParts.pop(); - const firstName = nameParts.join(' '); const dispose = showModal('hwr-confirmation-modal', { - healthWorker, + healthWorker: fetchedHealthWorker, onConfirm: () => { dispose(); - setValue('surname', surname); - setValue('firstname', firstName); - setValue('nationalid', nationalId); - setValue('licenseNumber', licenseNumber); - setValue('registrationNumber', registrationNumber); - setValue('licenseExpiryDate', parseDate(licenseDate)); + setValue('surname', fetchedHealthWorker?.entry[0]?.resource?.name[0]?.text.split(' ').pop()); + setValue( + 'firstname', + fetchedHealthWorker?.entry[0]?.resource?.name[0]?.text.split(' ').slice(0, -1).join(' '), + ); + setValue( + 'nationalid', + fetchedHealthWorker?.entry[0]?.resource?.identifier?.find((id) => + id.type?.coding?.some((code) => code.code === 'national-id'), + )?.value, + ); + setValue( + 'licenseNumber', + fetchedHealthWorker?.entry[0]?.resource?.identifier?.find((id) => + id.type?.coding?.some((code) => code.code === 'license-number'), + )?.value, + ); + setValue( + 'registrationNumber', + fetchedHealthWorker?.entry[0]?.resource?.identifier?.find((id) => + id.type?.coding?.some((code) => code.code === 'board-registration-number'), + )?.value, + ); + setValue( + 'licenseExpiryDate', + parseDate( + fetchedHealthWorker?.entry[0]?.resource?.identifier?.find((id) => + id.type?.coding?.some((code) => code.code === 'license-number'), + )?.period?.end || t('unknown', 'Unknown'), + ), + ); + // Save fetched healthWorker to state + setHealthWorker(fetchedHealthWorker); }, }); } catch (error) { @@ -159,6 +170,7 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u setSearchHWR({ ...searchHWR, isHWRLoading: false }); } }; + const onSubmit = async (data) => { let response; try { @@ -218,6 +230,14 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u attributeType: licenseBodyUuid, value: data.registrationNumber, }, + ...(healthWorker + ? [ + { + attributeType: providerHieFhirReference, + value: JSON.stringify(healthWorker), + }, + ] + : []), // Include the healthWorker attribute only if it exists ], retired: false, }; @@ -366,6 +386,7 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u id="form__national__id" placeholder={t('nationalIdPlaceholder', 'Enter National ID')} labelText={t('nationalID', 'National ID*')} + disabled invalid={!!errors.nationalid} invalidText={errors.nationalid?.message} /> @@ -409,7 +430,8 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u render={({ field }) => ( = ({ closeWorkspace, provider, u )} /> + = ({ closeWorkspace, provider, u = ({ closeWorkspace, provider, u labelText="License expiry date*" id="form__license_date_picker" size="md" + disabled invalid={!!errors.licenseExpiryDate} invalidText={errors.licenseExpiryDate?.message} /> From b9b96696fead5477ce2735ed358a79f9c36033d3 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Thu, 16 Jan 2025 22:52:54 +0300 Subject: [PATCH 2/4] (refactor) commented out providerHIEFHIRReference functionality --- packages/esm-billing-app/translations/en.json | 1 - .../src/workspace/provider-form.workspace.tsx | 16 ++++++------- .../esm-providers-app/translations/en.json | 23 +++---------------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/packages/esm-billing-app/translations/en.json b/packages/esm-billing-app/translations/en.json index dec4a7e96..694a40f9d 100644 --- a/packages/esm-billing-app/translations/en.json +++ b/packages/esm-billing-app/translations/en.json @@ -120,7 +120,6 @@ "errorOnLine": "Error on line", "errorRetrievingHIESubscription": "Error retrieving HIE subscription", "exemptionCategory": "Exemption category", - "exemptionSchema": "Exemption Schema", "facility": "Facility", "failedBillPayment": "Bill payment failed", "failure": "Error loading intervensions", diff --git a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx index 9a272992d..79435df81 100644 --- a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx +++ b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx @@ -230,14 +230,14 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u attributeType: licenseBodyUuid, value: data.registrationNumber, }, - ...(healthWorker - ? [ - { - attributeType: providerHieFhirReference, - value: JSON.stringify(healthWorker), - }, - ] - : []), // Include the healthWorker attribute only if it exists + // ...(healthWorker + // ? [ + // { + // attributeType: providerHieFhirReference, + // value: JSON.stringify(healthWorker), + // }, + // ] + // : []), ], retired: false, }; diff --git a/packages/esm-providers-app/translations/en.json b/packages/esm-providers-app/translations/en.json index bb6a8d9c1..ac1669719 100644 --- a/packages/esm-providers-app/translations/en.json +++ b/packages/esm-providers-app/translations/en.json @@ -1,9 +1,7 @@ { "action": "Action", - "activeLicensed": "Active License", - "actives": "Active", + "active": "Active", "adjustFilterOrSwitch": "Try adjusting your search or switch to a different category above.", - "all": "All Providers", "cancel": "Cancel", "chooseIdentifierType": "Choose identifier type", "continue": "Continue to registration", @@ -11,10 +9,6 @@ "enterIdentifierNumber": "Enter identifier number", "error": "Error loading user details", "errorSyncMsg": "", - "expiredlscs": "Expiring license(s)", - "expiringedLicenses": "Expiring(ed) licenses", - "expiryDate": "Expiry Date", - "Gender": "Gender", "HealthworkerNotFound": "The health worker records could not be found in Health Worker registry, do you want to continue to create an account", "healthWorkerRegistry": "Health worker registry", "healthWorkerRegistryEmpty": "Create an Account", @@ -28,30 +22,19 @@ "licenseNumber": "License Number", "loading": "Loading...", "messageText": "", - "missingExpiryDate": "Missing Expiry Date", - "missingIDno": "Missing National ID", - "missingLicenses": "Missing license(s)", - "missingNational": "Missing national id", - "missingNationalIDs": "Missing national id", "name": "Name", - "nationalID": "National ID", + "nationalId": "National ID", "nextPage": "Next page", "noHealthWorkerFound": "No Health worker found", "noHwrApi": "Health Care Worker Registry API credentials not configured,Kindly contact system admin. Do you want to continue to create an account", "noProvidersAvailable": "No providers available", "previousPage": "Previous page", - "profileOverview": "Profile overview", "providerManagement": "Providers Management", - "providersAll": "List of provider", - "providersWithActiveLicenses": "Active license", "ResourceNotFound": "The Health Work Registry is not reachable, kindly confirm your internet connectivity and try again. Do you want to continue to create an account", - "roles": "Roles", "searchProvider": "Search for provider", "sync": "Sync", "syncing": "Syncing...", "syncmsg": "Account synced successfully!", - "unknown": "Unknown", "unknownError": "An error occured while searching Health Worker Registry, kindly contact system admin. Do you want to continue to create an account ", - "unlicensed": "Unlicensed", - "WithMissingLicenses": "Missing license" + "unlicensed": "Unlicensed" } From 13410a69a2f1b616b1962bf2d8d81ca817efb0c2 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Fri, 17 Jan 2025 15:01:57 +0300 Subject: [PATCH 3/4] (refactor) addressed the PR suggestions --- .../src/component/providers.component.tsx | 8 +- .../esm-providers-app/src/config-schema.ts | 18 +++ .../provider-information.modal.componet.tsx | 10 ++ ...nt.tsx => provider-overview.component.tsx} | 4 +- .../{overview.scss => provider-overview.scss} | 0 .../table/provider-data-table.component.tsx | 35 +++--- .../src/table/provider-details.component.tsx | 31 ++++- .../src/table/provider-details.scss | 9 +- packages/esm-providers-app/src/types/index.ts | 15 +++ .../src/workspace/provider-form.workspace.tsx | 110 ++++++++++++++++-- 10 files changed, 199 insertions(+), 41 deletions(-) rename packages/esm-providers-app/src/overview/{overview.component.tsx => provider-overview.component.tsx} (90%) rename packages/esm-providers-app/src/overview/{overview.scss => provider-overview.scss} (100%) diff --git a/packages/esm-providers-app/src/component/providers.component.tsx b/packages/esm-providers-app/src/component/providers.component.tsx index 7fb98e7f8..349b88a64 100755 --- a/packages/esm-providers-app/src/component/providers.component.tsx +++ b/packages/esm-providers-app/src/component/providers.component.tsx @@ -1,16 +1,12 @@ import React from 'react'; import { ProvidersHeader } from '../header/providers-header.component'; -import { useProviders } from '../table/provider-data-table.resource'; -import dayjs from 'dayjs'; -import { ConfigObject } from '../config-schema'; -import { useConfig } from '@openmrs/esm-framework'; -import { Overview } from '../overview/overview.component'; +import { ProviderOverview } from '../overview/provider-overview.component'; const ProvidersComponent: React.FC = () => { return (
- +
); }; diff --git a/packages/esm-providers-app/src/config-schema.ts b/packages/esm-providers-app/src/config-schema.ts index 86f52b00c..93834492f 100755 --- a/packages/esm-providers-app/src/config-schema.ts +++ b/packages/esm-providers-app/src/config-schema.ts @@ -37,6 +37,21 @@ export const configSchema = { _description: 'UUID for provider hie fhir reference', _default: '67b94e8e-4d61-4810-b0f1-d86497f6e553', }, + phoneNumberUuid: { + _type: Type.String, + _description: 'UUID for provider hie phone number', + _default: '37daed7f-1f4e-4e62-8e83-6048ade18a87', + }, + qualificationUuid: { + _type: Type.String, + _description: 'UUID for provider hie qualification', + _default: '43f99413-6e7f-4812-bc60-066bb1d43f94', + }, + providerAddressUuid: { + _type: Type.String, + _description: 'UUID for provider hie address', + _default: '033ff604-ecf7-464f-b623-5b77c733667f', + }, defaultPrimaryFacility: { _type: Type.String, _description: 'Default facility for a provider', @@ -70,6 +85,9 @@ export interface ConfigObject { passportNumberUuid: string; licenseExpiryDateUuid: string; providerHieFhirReference: string; + phoneNumberUuid: string; + qualificationUuid: string; + providerAddressUuid: string; licenseBodyUuid: string; providerNationalIdUuid: string; licenseNumberUuid: string; diff --git a/packages/esm-providers-app/src/modal/provider-information.modal.componet.tsx b/packages/esm-providers-app/src/modal/provider-information.modal.componet.tsx index 9fa47236b..1f521bb1d 100644 --- a/packages/esm-providers-app/src/modal/provider-information.modal.componet.tsx +++ b/packages/esm-providers-app/src/modal/provider-information.modal.componet.tsx @@ -95,6 +95,16 @@ const HWRConfirmModal: React.FC = ({ close, onConfirm, hea )?.valueCodeableConcept?.coding?.[0]?.display || t('unknown', 'Unknown') } /> + ext.url === 'https://ts.kenya-hie.health/Codesystem/specialty', + )?.valueCodeableConcept?.coding?.[0]?.display || + t('unknown', 'Unknown') + } + /> { +import styles from './provider-overview.scss'; +export const ProviderOverview: React.FC = () => { const { t } = useTranslation(); const handleRegisterProvider = () => { diff --git a/packages/esm-providers-app/src/overview/overview.scss b/packages/esm-providers-app/src/overview/provider-overview.scss similarity index 100% rename from packages/esm-providers-app/src/overview/overview.scss rename to packages/esm-providers-app/src/overview/provider-overview.scss diff --git a/packages/esm-providers-app/src/table/provider-data-table.component.tsx b/packages/esm-providers-app/src/table/provider-data-table.component.tsx index 6cf877edb..35dec1d4d 100644 --- a/packages/esm-providers-app/src/table/provider-data-table.component.tsx +++ b/packages/esm-providers-app/src/table/provider-data-table.component.tsx @@ -28,6 +28,19 @@ import CustomActionMenu from '../overflow/overflow-component'; import EmptyProviderState from './empty-state.component'; import { Report } from '@carbon/react/icons'; +type FilterType = 'All Providers' | 'Active Licensed' | 'Expired Licensed' | 'Licensed expiring soon' | 'Unlicensed'; + +const getCardTitle = (filterName: FilterType): string => { + const filterMap: Record = { + 'All Providers': 'List of all providers', + 'Active Licensed': 'List of active licensed providers', + 'Expired Licensed': 'List of expired licensed providers', + 'Licensed expiring soon': 'List of licensed expiring soon providers', + Unlicensed: 'List of unlicensed providers', + }; + return filterMap[filterName] || 'List of providers'; +}; + const ProviderListTable: React.FC = () => { const { t } = useTranslation(); const layout = useLayoutType(); @@ -36,9 +49,8 @@ const ProviderListTable: React.FC = () => { const { licenseNumberUuid, licenseExpiryDateUuid, providerNationalIdUuid } = useConfig(); const [pageSize, setPageSize] = useState(10); const [searchQuery, setSearchQuery] = useState(''); - const [selectedFilter, setSelectedFilter] = useState('All Providers'); // Default filter to "All Providers" + const [selectedFilter, setSelectedFilter] = useState('All Providers'); - // Helper functions for filtering const isActiveLicensed = (provider) => { const licenseAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseNumberUuid); const expiryAttr = provider.attributes.find((attr) => attr.attributeType.uuid === licenseExpiryDateUuid); @@ -120,20 +132,9 @@ const ProviderListTable: React.FC = () => {
+ title={`${t(getCardTitle(selectedFilter), { count: filteredProviders.length })} (${ + filteredProviders.length + })`}> { { text: 'Licensed expiring soon' }, { text: 'Unlicensed' }, ]} - onChange={({ selectedItem }) => setSelectedFilter(selectedItem?.text || 'All Providers')} + onChange={({ selectedItem }) => setSelectedFilter((selectedItem?.text as FilterType) || 'All Providers')} /> diff --git a/packages/esm-providers-app/src/table/provider-details.component.tsx b/packages/esm-providers-app/src/table/provider-details.component.tsx index e9e82dca7..e7e3e8ae1 100644 --- a/packages/esm-providers-app/src/table/provider-details.component.tsx +++ b/packages/esm-providers-app/src/table/provider-details.component.tsx @@ -6,6 +6,7 @@ import { useProviderDetails, useProviderUser } from '../workspace/hook/provider- import { PatientPhoto } from '@openmrs/esm-framework'; import dayjs from 'dayjs'; import classNames from 'classnames'; +import capitalize from 'lodash/capitalize'; interface ProviderDetailsProps { providerUuid: string; @@ -20,6 +21,10 @@ const ProviderDetails: React.FC = ({ providerUuid }) => { const licenseAttr = provider?.attributes?.find((attr) => attr.attributeType.display === 'Practising License Number'); const nationalID = provider?.attributes?.find((attr) => attr.attributeType.display === 'Provider National Id Number'); const dateAttr = provider?.attributes?.find((attr) => attr.attributeType.display === 'License Expiry Date'); + const phoneNumber = provider?.attributes?.find((attr) => attr.attributeType.display === 'Phone number'); + const qualification = provider?.attributes?.find((attr) => attr.attributeType.display === 'Provider qualification'); + const registrationNumber = provider?.attributes?.find((attr) => attr.attributeType.display === 'License Body'); + const emailAddress = provider?.attributes?.find((attr) => attr.attributeType.display === 'Provider address'); const formattedExpiryDate = dateAttr?.value ? dayjs(dateAttr.value).format('YYYY-MM-DD') : null; const today = dayjs(); @@ -60,7 +65,6 @@ const ProviderDetails: React.FC = ({ providerUuid }) => {
- {/* Patient Name, Gender, and License Status */}
{user?.person?.display} · @@ -68,20 +72,39 @@ const ProviderDetails: React.FC = ({ providerUuid }) => { {user?.person?.gender === 'M' ? 'Male' : user?.person?.gender === 'F' ? 'Female' : ''} ·{' '} {getLicenseStatusTag()} + + {qualification?.value && {capitalize(qualification.value)}} +
- {/* National ID and License Number */}
- + + {t('phoneNumber', 'Phone number')}: {phoneNumber?.value ? phoneNumber.value : '--'} + + · + + + {t('emailAddress', 'Email address')}: {emailAddress?.value ? emailAddress.value : '--'} + +
+
+
+
+ {t('nationalId', 'National ID')}: {nationalID?.value ? nationalID.value : '--'} · - + {t('licenseNumber', 'License number')}: {licenseAttr?.value ? licenseAttr.value : '--'} + · + + {t('registrationNumber', 'Registration number')}:{' '} + {registrationNumber?.value ? registrationNumber.value : '--'} +

diff --git a/packages/esm-providers-app/src/table/provider-details.scss b/packages/esm-providers-app/src/table/provider-details.scss index 6a1bdf53d..3861c58d3 100644 --- a/packages/esm-providers-app/src/table/provider-details.scss +++ b/packages/esm-providers-app/src/table/provider-details.scss @@ -11,10 +11,9 @@ margin-right: layout.$spacing-01; } .middot { - margin: 0 0.25rem; + margin: 0 layout.$spacing-01; } -.nationalId { - margin-top: layout.$spacing-04; +.spanField { margin-left: layout.$spacing-04; margin-right: layout.$spacing-01; } @@ -55,4 +54,8 @@ display: flex; flex-flow: row wrap; align-items: center; + margin-top: layout.$spacing-04; +} +.patientAvatar { + margin-top: layout.$spacing-06; } diff --git a/packages/esm-providers-app/src/types/index.ts b/packages/esm-providers-app/src/types/index.ts index 85fb3350b..d8ba452cc 100644 --- a/packages/esm-providers-app/src/types/index.ts +++ b/packages/esm-providers-app/src/types/index.ts @@ -88,10 +88,25 @@ interface Entry { active: boolean; name: Name[]; telecom: ContactList[]; + extension: Extension[]; gender: string; qualification: Qualification[]; }; } +export interface Extension { + url: string; + valueCodeableConcept: ValueCodeableConcept; +} + +export interface ValueCodeableConcept { + coding: Coding[]; +} + +export interface Coding { + system: string; + code: string; + display: string; +} interface IdentifierType { type: { diff --git a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx index 79435df81..a4053c6dc 100644 --- a/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx +++ b/packages/esm-providers-app/src/workspace/provider-form.workspace.tsx @@ -50,6 +50,9 @@ const providerFormSchema = z gender: z.enum(['M', 'F'], { required_error: 'Gender is required' }), licenseNumber: z.string().nonempty('License number is required'), registrationNumber: z.string().nonempty('License number is required'), + phoneNumber: z.string().optional(), + qualification: z.string().optional(), + providerAddress: z.string().optional(), passportNumber: z.string().optional(), licenseExpiryDate: z.date(), username: z.string().nonempty('Username is required'), @@ -82,6 +85,9 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u licenseBodyUuid, identifierTypes, providerHieFhirReference, + phoneNumberUuid, + qualificationUuid, + providerAddressUuid, } = useConfig(); const [searchHWR, setSearchHWR] = useState({ @@ -107,6 +113,9 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u gender: provider?.person?.gender ?? 'M', licenseNumber: provider?.attributes?.find((attr) => attr.attributeType.uuid === licenseNumberUuid)?.value, registrationNumber: provider?.attributes?.find((attr) => attr.attributeType.uuid === licenseBodyUuid)?.value, + phoneNumber: provider?.attributes?.find((attr) => attr.attributeType.uuid === phoneNumberUuid)?.value, + qualification: provider?.attributes?.find((attr) => attr.attributeType.uuid === qualificationUuid)?.value, + providerAddress: provider?.attributes?.find((attr) => attr.attributeType.uuid === providerAddressUuid)?.value, licenseExpiryDate: licenseDate ? parseDate(licenseDate) : undefined, username: user?.username, password: provider ? '*****' : '', @@ -152,6 +161,26 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u id.type?.coding?.some((code) => code.code === 'board-registration-number'), )?.value, ); + setValue( + 'phoneNumber', + fetchedHealthWorker?.entry[0]?.resource?.telecom?.find((contact) => contact.system === 'phone')?.value || + '', + ); + + setValue( + 'qualification', + fetchedHealthWorker?.entry[0]?.resource?.qualification?.[0]?.code?.coding?.[0]?.display || + fetchedHealthWorker?.entry[0]?.resource?.extension?.find( + (ext) => ext.url === 'https://ts.kenya-hie.health/Codesystem/specialty', + )?.valueCodeableConcept?.coding?.[0]?.display || + '', + ); + setValue( + 'providerAddress', + fetchedHealthWorker?.entry[0]?.resource?.telecom?.find((contact) => contact.system === 'email')?.value || + '', + ); + setValue( 'licenseExpiryDate', parseDate( @@ -160,7 +189,6 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u )?.period?.end || t('unknown', 'Unknown'), ), ); - // Save fetched healthWorker to state setHealthWorker(fetchedHealthWorker); }, }); @@ -230,14 +258,27 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u attributeType: licenseBodyUuid, value: data.registrationNumber, }, - // ...(healthWorker - // ? [ - // { - // attributeType: providerHieFhirReference, - // value: JSON.stringify(healthWorker), - // }, - // ] - // : []), + { + attributeType: phoneNumberUuid, + value: data.phoneNumber, + }, + { + attributeType: qualificationUuid, + value: data.qualification, + }, + { + attributeType: providerAddressUuid, + value: data.providerAddress, + }, + + ...(healthWorker + ? [ + { + attributeType: providerHieFhirReference, + value: JSON.stringify(healthWorker), + }, + ] + : []), ], retired: false, }; @@ -486,6 +527,57 @@ const ProviderForm: React.FC = ({ closeWorkspace, provider, u )} /> + + ( + + )} + /> + + + ( + + )} + /> + + + ( + + )} + /> + {!provider ? ( {t('loginIn', 'Login info')} ) : ( From f99b8214aa0dbb4fe8cebf45b3406ca1bf5a98f5 Mon Sep 17 00:00:00 2001 From: its-kios09 Date: Fri, 17 Jan 2025 15:11:09 +0300 Subject: [PATCH 4/4] (refactor) updated the translation --- packages/esm-providers-app/translations/en.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/esm-providers-app/translations/en.json b/packages/esm-providers-app/translations/en.json index ac1669719..49e01e609 100644 --- a/packages/esm-providers-app/translations/en.json +++ b/packages/esm-providers-app/translations/en.json @@ -6,6 +6,7 @@ "chooseIdentifierType": "Choose identifier type", "continue": "Continue to registration", "createAnAccount": "Create an account", + "emailAddress": "Email address", "enterIdentifierNumber": "Enter identifier number", "error": "Error loading user details", "errorSyncMsg": "", @@ -28,8 +29,10 @@ "noHealthWorkerFound": "No Health worker found", "noHwrApi": "Health Care Worker Registry API credentials not configured,Kindly contact system admin. Do you want to continue to create an account", "noProvidersAvailable": "No providers available", + "phoneNumber": "Phone number", "previousPage": "Previous page", "providerManagement": "Providers Management", + "registrationNumber": "Registration number", "ResourceNotFound": "The Health Work Registry is not reachable, kindly confirm your internet connectivity and try again. Do you want to continue to create an account", "searchProvider": "Search for provider", "sync": "Sync",