Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MINT-3123] CR and TDL Sidepanel #1418

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cypress/e2e/crtdl.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ describe('FFS CRs and TDLs', () => {
cy.contains('h4', 'FFS3559');
cy.contains('h4', 'TDL240535');

cy.contains('button', 'View this in ECHIMP').click();
cy.contains('button', 'View more').click();
cy.get('[data-testid="cr-and-tdl-sidepanel"]').contains(
'Billing Requirements for Physician Services Rendered in Method II Critical Access Hospitals'
);
cy.get('[data-testid="cr-and-tdl-sidepanel"]').within(() => {
cy.contains('button', 'View this in ECHIMP').click();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`The CRAndTDLSidePanel component > renders TDL without crashing 1`] = `
<DocumentFragment>
<div
class="grid-container padding-y-5 padding-x-4 side-panel--cr-and-tdl"
data-testid="gridContainer"
>
<div
class="grid-row"
data-testid="grid"
>
<div
class="grid-col-12"
data-testid="grid"
>
<div
class="sidepanel__header"
>
<h4
class="text-base"
>
abc123
</h4>
<h1>
Test Title
</h1>
</div>
<div
class="sidepanel__content"
>
<div>
<p
class="text-bold"
>
Issued date
</p>
<p>
2023
</p>
</div>
<button
class="usa-button usa-button--unstyled sidepanel--full-width margin-right-0"
data-testid="button"
type="button"
>
<span
class="display-flex flex-align-center"
style="column-gap: 0.25rem;"
>
View this in ECHIMP
<svg
class="usa-icon"
focusable="false"
height="1em"
role="img"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
/>
</svg>
</span>
</button>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
13 changes: 13 additions & 0 deletions src/components/CRAndTDLSidePanel/_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const properlyCapitalizeInitiator = (fullName: string) => {
const [namePart, parenthesisPart] = fullName.split(' (');

const capitalizedName = namePart
.toLowerCase()
.replace(/\b\w/g, char => char.toUpperCase());

return parenthesisPart
? `${capitalizedName} (${parenthesisPart}`
: capitalizedName;
};

export default properlyCapitalizeInitiator;
53 changes: 53 additions & 0 deletions src/components/CRAndTDLSidePanel/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@use 'uswds-core' as *;
@use 'viewports' as *;

.side-panel--cr-and-tdl {
.sidepanel {
&__header {
padding-bottom: 2.5rem;
border-bottom: 1px solid color("base-light");

h1, h4 {
margin: 0;
margin-bottom: 1rem;
}

h1 {
font-size: 40px;
font-weight: 700;
line-height: 50px;
-webkit-line-clamp: 3;
line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
}

.echimp-card__cr-status {
display: flex;
gap: 0.5rem;
margin-bottom: 0;
}
}

&__content {
padding: 2rem 0rem;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;

.sidepanel--full-width {
grid-column: 1 / 3;
}

& div {
margin-bottom: 0;

p {
margin: 0;
line-height: 25px;
}
}
}
}
}
21 changes: 21 additions & 0 deletions src/components/CRAndTDLSidePanel/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { render, screen } from '@testing-library/react';

import CRAndTDLSidePanel from './index';

describe('The CRAndTDLSidePanel component', () => {
it('renders TDL without crashing', () => {
const { asFragment } = render(
<CRAndTDLSidePanel
isCR={false}
id="abc123"
title="Test Title"
issuedDate="2023"
/>
);
expect(screen.getByText('abc123')).toBeInTheDocument();
expect(screen.getByText('Test Title')).toBeInTheDocument();
expect(screen.getByText('View this in ECHIMP')).toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});
});
165 changes: 165 additions & 0 deletions src/components/CRAndTDLSidePanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Grid, GridContainer, Icon } from '@trussworks/react-uswds';
import i18n from 'config/i18n';

import ExternalLink from 'components/ExternalLink';
import TruncatedText from 'components/TruncatedText';

import properlyCapitalizeInitiator from './_utils';

import './index.scss';

export type CRAndTDLSidePanelProps = {
isCR: boolean;
id: string;
title?: string | null;
crStatus?: string | null;
emergencyCrFlag?: boolean | null;
implementationDate?: string | null;
issuedDate?: string | null;
sensitiveFlag?: boolean | null;
initiator?: string | null;
relatedCrTdlNumbers?: string | null;
crSummary?: {
rawContent: string;
} | null;
};

const CRAndTDLSidePanel = ({
isCR,
id,
title,
crStatus,
emergencyCrFlag,
implementationDate,
issuedDate,
sensitiveFlag,
initiator,
relatedCrTdlNumbers,
crSummary
}: CRAndTDLSidePanelProps) => {
const { t: crtdlsT } = useTranslation('crtdlsMisc');

return (
<GridContainer className="padding-y-5 padding-x-4 side-panel--cr-and-tdl">
<Grid row>
<Grid col={12}>
<div className="sidepanel__header">
<h4 className="text-base">{id}</h4>
<h1>{title?.replace(/&amp;/g, '&')}</h1>

{(emergencyCrFlag || sensitiveFlag) && (
<div className="echimp-card__cr-tags">
{emergencyCrFlag && (
<div
className="echimp-card__cr-tag echimp-card__cr-tag--emergency"
data-testid="emergency__cr-tag"
>
<Icon.LocalFireDepartment />
{crtdlsT('echimpCard.crTag.emergency')}
</div>
)}
{sensitiveFlag && (
<div
className="echimp-card__cr-tag echimp-card__cr-tag--sensitive"
data-testid="sensitive__cr-tag"
>
<Icon.Flag />
{crtdlsT('echimpCard.crTag.sensitive')}
</div>
)}
</div>
)}

{crStatus && (
<div className="echimp-card__cr-status">
<p className="text-bold">{crtdlsT('echimpCard.crStatus')}:</p>
<p>{crStatus}</p>
</div>
)}
</div>
<div className="sidepanel__content">
{isCR ? (
<>
<div>
<p className="text-bold">
{crtdlsT('echimpCard.implementationDate')}
</p>
<p>{implementationDate}</p>
</div>
{initiator && (
<div>
<p className="text-bold">
{crtdlsT('echimpCard.initiator')}
</p>
{/* Currently initiator returns name in ALL CAPS */}
<p>{properlyCapitalizeInitiator(initiator)}</p>
</div>
)}
{crSummary && (
<div className="sidepanel--full-width">
<p className="text-bold">
{crtdlsT('echimpCard.crSummary')}
</p>
<TruncatedText
id={id}
text={crSummary?.rawContent}
charLimit={269}
/>
</div>
)}

<div>
<p className="text-bold">
{crtdlsT('echimpCard.crTag.emergency')}
{crtdlsT('echimpCard.crTag.crQuestion')}
</p>
<p>
{emergencyCrFlag
? i18n.t('general:yes')
: i18n.t('general:no')}
</p>
</div>
<div>
<p className="text-bold">
{crtdlsT('echimpCard.crTag.sensitive')}
{crtdlsT('echimpCard.crTag.crQuestion')}
</p>
<p>
{sensitiveFlag
? i18n.t('general:yes')
: i18n.t('general:no')}
</p>
</div>
<div>
<p className="text-bold">
{crtdlsT('echimpCard.relatedCrTdl')}
</p>
<p>{relatedCrTdlNumbers}</p>
</div>
</>
) : (
// If TDL, then render the following
<div>
<p className="text-bold">{crtdlsT('echimpCard.issuedDate')}</p>
{/* Currently issuedDate returns '2024-07-24 00:00:00' */}
<p>{issuedDate?.split(' ')[0]}</p>
</div>
)}

<ExternalLink
href={`${import.meta.env.VITE_ECHIMP_URL}?sysSelect=${id.slice(0, 3)}&crNum=${id}`}
className="sidepanel--full-width margin-right-0"
toEchimp
>
{crtdlsT('echimpCard.viewThisInECHIMP')}
</ExternalLink>
</div>
</Grid>
</Grid>
</GridContainer>
);
};

export default CRAndTDLSidePanel;
18 changes: 18 additions & 0 deletions src/components/CRAndTDLSidePanel/utils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import properlyCapitalizeInitiator from './_utils';

describe('Properly Capitalize Initiator Function Test', () => {
it('returns properly capitalized name', () => {
expect(properlyCapitalizeInitiator('STEVE ROGERS')).toBe('Steve Rogers');
expect(properlyCapitalizeInitiator('sTEVE rOGERS')).toBe('Steve Rogers');
expect(properlyCapitalizeInitiator('steve rogers')).toBe('Steve Rogers');
});

it('returns properly capitalized name while words in parenthesis remains as is', () => {
expect(properlyCapitalizeInitiator('STEVE ROGERS (AVENGER)')).toBe(
'Steve Rogers (AVENGER)'
);
expect(properlyCapitalizeInitiator('BRUCE BANNER (MD, Ph.D)')).toBe(
'Bruce Banner (MD, Ph.D)'
);
});
});
4 changes: 3 additions & 1 deletion src/components/EChimpCards/EChimpCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ describe('EChimpCard', () => {
crStatus: 'Open',
emergencyCrFlag: true,
sensitiveFlag: false,
implementationDate: '2022-07-30T05:00:00Z'
implementationDate: '2022-07-30T05:00:00Z',
setShowCRorTDLWithId: () => {},
setIsSidepanelOpen: () => {}
};

it('renders without errors', async () => {
Expand Down
Loading