Skip to content

Commit

Permalink
Tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
denniskigen committed Jun 30, 2023
1 parent 00eb582 commit 2e1ea3a
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 108 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { MouseEvent, useCallback, useEffect, useState } from 'react';
import React, { MouseEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Tag } from '@carbon/react';
import { ChevronDown, ChevronUp, OverflowMenuVertical } from '@carbon/react/icons';
import { ExtensionSlot, age, formatDate, parseDate, useConfig } from '@openmrs/esm-framework';
import ContactDetails from '../contact-details/contact-details.component';
import CustomOverflowMenuComponent from '../ui-components/overflow-menu.component';
import styles from './patient-banner.scss';
import { Breakpoint } from '@openmrs/esm-framework/src/internal';

interface PatientBannerProps {
patient: fhir.Patient;
Expand All @@ -23,17 +22,17 @@ const PatientBanner: React.FC<PatientBannerProps> = ({
onTransition,
hideActionsOverflow,
}) => {
const { excludePatientIdentifierCodeTypes } = useConfig();
const { t } = useTranslation();
const overflowMenuRef = React.useRef(null);
const patientBannerRef = React.useRef(null);
const [isPatientBannerSmallSize, setIsPatientBannerSmallSize] = useState(false);
const overflowMenuRef = useRef(null);
const patientBannerRef = useRef(null);
const [isTabletViewport, setIsTabletViewport] = useState(false);
const { excludePatientIdentifierCodeTypes } = useConfig();

useEffect(() => {
const currentRef = patientBannerRef.current;
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
setIsPatientBannerSmallSize(entry.contentRect.width < Breakpoint.TABLET_MAX);
setIsTabletViewport(entry.contentRect.width < 1023);
}
});
resizeObserver.observe(patientBannerRef.current);
Expand All @@ -42,20 +41,20 @@ const PatientBanner: React.FC<PatientBannerProps> = ({
resizeObserver.unobserve(currentRef);
}
};
}, [patientBannerRef, setIsPatientBannerSmallSize]);
}, [patientBannerRef, setIsTabletViewport]);

// Ensure we have emptyStateText and record translation keys
// t('emptyStateText', 'There are no {{displayText}} to display for this patient'); t('record', 'Record');

const patientActionsSlotState = React.useMemo(
const patientActionsSlotState = useMemo(
() => ({ patientUuid, onClick, onTransition }),
[patientUuid, onClick, onTransition],
);

const patientName = `${patient?.name?.[0]?.given?.join(' ')} ${patient?.name?.[0].family}`;
const patientPhotoSlotState = React.useMemo(() => ({ patientUuid, patientName }), [patientUuid, patientName]);
const patientPhotoSlotState = useMemo(() => ({ patientUuid, patientName }), [patientUuid, patientName]);

const [showContactDetails, setShowContactDetails] = React.useState(false);
const [showContactDetails, setShowContactDetails] = useState(false);
const toggleContactDetails = useCallback(() => {
setShowContactDetails((value) => !value);
}, []);
Expand Down Expand Up @@ -182,7 +181,7 @@ const PatientBanner: React.FC<PatientBannerProps> = ({
</div>
{showContactDetails && (
<ContactDetails
isPatientBannerSmallSize={isPatientBannerSmallSize}
isTabletViewport={isTabletViewport}
address={patient?.address ?? []}
telecom={patient?.telecom ?? []}
patientId={patient?.id}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,69 +1,61 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { InlineLoading } from '@carbon/react';
import { ConfigurableLink, navigate, parseDate, useConfig, useLayoutType } from '@openmrs/esm-framework';
import { ConfigurableLink, parseDate, useConfig } from '@openmrs/esm-framework';
import { ConfigObject } from '../config-schema';
import { useRelationships } from './relationships.resource';
import { usePatientContactAttributes } from '../hooks/usePatientAttributes';
import { usePatientListsForPatient } from '../hooks/usePatientListsForPatient';
import { ConfigObject } from '../config-schema';
import styles from './contact-details.scss';

interface ContactDetailsProps {
address: Array<fhir.Address>;
telecom: Array<fhir.ContactPoint>;
patientId: string;
deceased: boolean;
isPatientBannerSmallSize: boolean;
isTabletViewport: boolean;
}

const PatientLists: React.FC<{ patientUuid: string }> = ({ patientUuid }) => {
const { cohorts, isLoading } = usePatientListsForPatient(patientUuid);
const { t } = useTranslation();
const { cohorts, isLoading } = usePatientListsForPatient(patientUuid);

if (isLoading) {
return <InlineLoading />;
}

if (cohorts?.length > 0) {
const sorted = cohorts.sort((a, b) => parseDate(a.startDate).getTime() - parseDate(b.startDate).getTime());
const slicedLists = sorted.slice(0, 3);
return (
<>
<p className={styles.heading}>
{t('patientLists', 'Patient Lists ({totalLists})', {
totalLists: cohorts.length,
})}
</p>
return (
<>
<p className={styles.heading}>
{t('patientLists', 'Patient Lists')} ({cohorts?.length ?? 0})
</p>
{isLoading ? (
<InlineLoading description={`${t('loading', 'Loading')} ...`} role="progressbar" />
) : (
<ul>
{slicedLists.map((cohort) => (
<li>
<ConfigurableLink to={`${window.spaBase}/home/patient-lists/${cohort.uuid}`} key={cohort.uuid}>
{cohort.name}
</ConfigurableLink>
</li>
))}
<li>
{(() => {
if (cohorts?.length > 0) {
const sortedLists = cohorts.sort(
(a, b) => parseDate(a.startDate).getTime() - parseDate(b.startDate).getTime(),
);
const slicedLists = sortedLists.slice(0, 3);
return slicedLists?.map((cohort) => (
<li key={cohort.uuid}>
<ConfigurableLink to={`${window.spaBase}/home/patient-lists/${cohort.uuid}`} key={cohort.uuid}>
{cohort.name}
</ConfigurableLink>
</li>
));
}
return <li>--</li>;
})()}
<li style={{ marginTop: '1rem' }}>
<ConfigurableLink to={`${window.spaBase}/home/patient-lists`}>
{cohorts.length > 3
? t('seeMore', 'See {moreLists} more', {
moreLists: cohorts?.length - 3,
? t('seeMoreLists', 'See {listCount} more lists', {
listCount: cohorts?.length - 3,
})
: ''}
</ConfigurableLink>
</li>
</ul>
</>
);
}

return (
<>
<p className={styles.heading}>
{t('patientLists', 'Patient Lists ({totalLists})', {
totalLists: cohorts.length,
})}
</p>
<p>--</p>
)}
</>
);
};
Expand Down Expand Up @@ -135,18 +127,21 @@ const Contact: React.FC<{ telecom: Array<fhir.ContactPoint>; patientUuid: string
return (
<>
<p className={styles.heading}>{t('contactDetails', 'Contact Details')}</p>
<ul>
<li>{value}</li>
{isLoading ? (
<InlineLoading description={`${t('loading', 'Loading')} ...`} />
) : (
contactAttributes?.map(({ attributeType, value, uuid }) => (
<li key={uuid}>
{attributeType.display} : {value}
</li>
))
)}
</ul>
{isLoading ? (
<InlineLoading description={`${t('loading', 'Loading')} ...`} role="progressbar" />
) : (
<ul>
{contactAttributes?.length > 0 ? (
contactAttributes.map(({ attributeType, value, uuid }) => (
<li key={uuid}>
{attributeType.display} : {value}
</li>
))
) : (
<li>--</li>
)}
</ul>
)}
</>
);
};
Expand All @@ -167,44 +162,39 @@ const Relationships: React.FC<{ patientId: string }> = ({ patientId }) => {
return (
<>
<p className={styles.heading}>{t('relationships', 'Relationships')}</p>
<>
{(() => {
if (isLoading) return <InlineLoading description="Loading..." role="progressbar" />;
if (relationships?.length) {
return (
<ul>
{relationships.map((r) => (
<li key={r.uuid} className={styles.relationship}>
<div>{extractName(r.display)}</div>
<div>{r.relationshipType}</div>
<div>
{`${r.relativeAge ? r.relativeAge : '--'} ${
r.relativeAge ? (r.relativeAge === 1 ? 'yr' : 'yrs') : ''
}`}
</div>
</li>
))}
</ul>
);
}
return <p>--</p>;
})()}
</>
{isLoading ? (
<InlineLoading description={`${t('loading', 'Loading')} ...`} role="progressbar" />
) : (
<ul>
{relationships?.length > 0 ? (
<>
{relationships.map((r) => (
<li key={r.uuid} className={styles.relationship}>
<div>{extractName(r.display)}</div>
<div>{r.relationshipType}</div>
<div>
{`${r.relativeAge ? r.relativeAge : '--'} ${
r.relativeAge ? (r.relativeAge === 1 ? 'yr' : 'yrs') : ''
}`}
</div>
</li>
))}
</>
) : (
<li>--</li>
)}
</ul>
)}
</>
);
};

const ContactDetails: React.FC<ContactDetailsProps> = ({
address,
telecom,
patientId,
deceased,
isPatientBannerSmallSize,
}) => {
const ContactDetails: React.FC<ContactDetailsProps> = ({ address, telecom, patientId, deceased, isTabletViewport }) => {
const currentAddress = address?.find((a) => a.use === 'home');
const currentClass = `${styles[deceased && 'deceased']} ${
styles[isPatientBannerSmallSize ? 'smallBannerSize' : 'contactDetailsContainer']
styles[isTabletViewport ? 'tabletSizeBanner' : 'contactDetailsContainer']
}`;

return (
<div className={currentClass}>
<div className={styles.row}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
@include type.type-style("body-compact-01");
text-decoration: none;
}

}

.contactDetailsContainer {
Expand Down Expand Up @@ -52,21 +51,21 @@
.relationship {
display: flex;
flex-flow: row nowrap;
}

.relationship div {
flex: 1 1;
div {
flex: 1 1;
}
}

.smallBannerSize {
.tabletSizeBanner {
@include container;
display: block;

.row {
&:first-child {
border-bottom: 1px solid $ui-03;
}
}
}

.row > .col {
&:nth-of-type(2n + 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ describe('ContactDetails', () => {
isLoading: false,
cohorts: mockCohorts,
});
const props = { ...testProps, isPatientBannerSmallSize: true };
const props = { ...testProps, isTabletViewport: true };

const { container } = renderWithSwr(<ContactDetails {...props} />);

await waitForLoadingToFinish();

expect(container.firstChild).toHaveClass('smallBannerSize');
expect(container.firstChild).toHaveClass('tabletSizeBanner');
expect(screen.getByText('Address')).toBeInTheDocument();
expect(screen.getByText('Contact Details')).toBeInTheDocument();
expect(screen.getByText('Relationships')).toBeInTheDocument();
Expand Down Expand Up @@ -190,13 +190,13 @@ describe('ContactDetails', () => {
});

mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockRelationships } });
const props = { ...testProps, isPatientBannerSmallSize: false };
const props = { ...testProps, isTabletViewport: false };

const { container } = renderWithSwr(<ContactDetails {...props} />);

await waitForLoadingToFinish();

expect(container.firstChild).not.toHaveClass('smallBannerSize');
expect(container.firstChild).not.toHaveClass('tabletSizeBanner');
expect(screen.getByText('Address')).toBeInTheDocument();
expect(screen.getByText('Contact Details')).toBeInTheDocument();
expect(screen.getByText('Relationships')).toBeInTheDocument();
Expand Down
6 changes: 3 additions & 3 deletions packages/esm-patient-banner-app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
"emptyStateText": "There are no {{displayText}} to display for this patient",
"female": "Female",
"hideDetails": "Hide details",
"loading": "Loading...",
"loading": "Loading",
"male": "Male",
"other": "Other",
"patientLists": "Patient Lists ({totalLists})",
"patientLists": "Patient Lists",
"postalCode": "Postal code",
"record": "Record",
"relationships": "Relationships",
"seeMore": "See {moreLists} more",
"seeMoreLists": "See {listCount} more lists",
"showDetails": "Show details",
"started": "Started",
"state": "State",
Expand Down

0 comments on commit 2e1ea3a

Please sign in to comment.