-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
align search form and results page with designs (#2609)
* seed some styles * pull out alert * refactor search form * refactor and make results view component dumb * make component more readable * new files * componentize sidenav * new folder * [pre-commit.ci] auto fixes from pre-commit hooks * move some files around * imports * [pre-commit.ci] auto fixes from pre-commit hooks * copy * [pre-commit.ci] auto fixes from pre-commit hooks * add a more reasonable sidenav default * [pre-commit.ci] auto fixes from pre-commit hooks * remove log * docs * rename * lint more * [pre-commit.ci] auto fixes from pre-commit hooks * more file moving * new files * third times the charm * try this? * add missing prop * [pre-commit.ci] auto fixes from pre-commit hooks * one more * change padding * [pre-commit.ci] auto fixes from pre-commit hooks * fix one test * [pre-commit.ci] auto fixes from pre-commit hooks * debug in ci * [pre-commit.ci] auto fixes from pre-commit hooks * change to 10 * remove debug log * [pre-commit.ci] auto fixes from pre-commit hooks * change selector * [pre-commit.ci] auto fixes from pre-commit hooks * change role --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
d4c0455
commit 029f3cb
Showing
26 changed files
with
642 additions
and
534 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,7 +62,7 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
// Make sure we have a results page with a single patient | ||
// Non-interactive 'div' elements in the table should be located by text | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
await expect(page.getByText("Patient Name")).toBeVisible(); | ||
await expect(page.getByText("WATERMELON SPROUT MCGEE")).toBeVisible(); | ||
|
@@ -76,20 +76,18 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
"Interested in learning more about using the TEFCA Query Connector for your jurisdiction? Send us an email at [email protected]", | ||
); | ||
|
||
// Let's get a little schwifty: there are multiple possible resolutions for 'Observations', | ||
// so we can chain things to get the table header to make sure the accordion is open | ||
// Check to see if the accordion button is open | ||
await expect( | ||
page | ||
.getByTestId("accordionItem_observations") | ||
.getByRole("heading", { name: "Observations" }), | ||
page.getByRole("button", { name: "Observations", expanded: true }), | ||
).toBeVisible(); | ||
|
||
// We can also just directly ask the page to find us filtered table rows | ||
await expect(page.locator("tbody").locator("tr")).toHaveCount(5); | ||
|
||
// Now let's use the return to search to go back to a blank form | ||
await page.getByRole("link", { name: "New patient search" }).click(); | ||
await page.getByRole("button", { name: "New patient search" }).click(); | ||
await expect( | ||
page.getByRole("heading", { name: "Search for a Patient" }), | ||
page.getByRole("heading", { name: "Search for a Patient", exact: true }), | ||
).toBeVisible(); | ||
}); | ||
|
||
|
@@ -116,7 +114,7 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
await expect(page.getByText("There are no patient records")).toBeVisible(); | ||
await page.getByRole("link", { name: "Search for a new patient" }).click(); | ||
await expect( | ||
page.getByRole("heading", { name: "Search for a Patient" }), | ||
page.getByRole("heading", { name: "Search for a Patient", exact: true }), | ||
).toBeVisible(); | ||
}); | ||
|
||
|
@@ -138,7 +136,7 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
// Among verification, make sure phone number is right | ||
await page.getByRole("button", { name: "Search for patient" }).click(); | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
await expect(page.getByText("Patient Name")).toBeVisible(); | ||
await expect(page.getByText("Veronica Anne Blackstone")).toBeVisible(); | ||
|
@@ -158,7 +156,7 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
await page.getByRole("button", { name: "Fill fields" }).click(); | ||
await page.getByRole("button", { name: "Search for patient" }).click(); | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
}); | ||
|
||
|
@@ -171,7 +169,7 @@ test.describe("querying with the TryTEFCA viewer", () => { | |
await page.getByLabel("Phone Number").fill(""); | ||
await page.getByRole("button", { name: "Search for patient" }).click(); | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
}); | ||
}); | ||
|
@@ -214,7 +212,7 @@ test.describe("Test the user journey of a 'tester'", () => { | |
|
||
// Make sure we have a results page with a single patient | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
await expect(page.getByText("Patient Name")).toBeVisible(); | ||
await expect(page.getByText("WATERMELON SPROUT MCGEE")).toBeVisible(); | ||
|
@@ -240,7 +238,7 @@ test.describe("Test the user journey of a 'tester'", () => { | |
|
||
// Make sure we have a results page with a single patient | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
await expect(page.getByText("Patient Name")).toBeVisible(); | ||
await expect(page.getByText("WATERMELON SPROUT MCGEE")).toBeVisible(); | ||
|
@@ -277,10 +275,10 @@ test.describe("Test the user journey of a 'tester'", () => { | |
|
||
// Make sure we have a results page with a single patient & appropriate back buttons | ||
await expect( | ||
page.getByRole("heading", { name: "Query Results" }), | ||
page.getByRole("heading", { name: "Patient Record" }), | ||
).toBeVisible(); | ||
await expect( | ||
page.getByRole("link", { name: "New patient search" }), | ||
page.getByRole("button", { name: "New patient search" }), | ||
).toBeVisible(); | ||
|
||
await page.getByRole("link", { name: "Return to search results" }).click(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 119 additions & 49 deletions
168
containers/tefca-viewer/src/app/query/components/ResultsView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,157 @@ | ||
import { UseCaseQueryResponse } from "../../query-service"; | ||
import SideNav from "./SideNav"; | ||
import ResultsViewSideNav, { | ||
NavSection, | ||
} from "./resultsView/ResultsViewSideNav"; | ||
import React, { useEffect } from "react"; | ||
import { Alert, Icon } from "@trussworks/react-uswds"; | ||
import ResultsViewTable from "./ResultsViewTable"; | ||
import ResultsViewTable from "./resultsView/ResultsViewTable"; | ||
import Backlink from "./backLink/Backlink"; | ||
import styles from "../page.module.css"; | ||
import ConditionsTable from "./ConditionsTable"; | ||
import Demographics from "./Demographics"; | ||
import DiagnosticReportTable from "./DiagnosticReportTable"; | ||
import EncounterTable from "./EncounterTable"; | ||
import MedicationRequestTable from "./MedicationRequestTable"; | ||
import ObservationTable from "./ObservationTable"; | ||
|
||
type ResultsViewProps = { | ||
useCaseQueryResponse: UseCaseQueryResponse; | ||
goBack: () => void; | ||
goBackToMultiplePatients?: () => void; | ||
queryName: string; | ||
}; | ||
|
||
export type ResultsViewAccordionItem = { | ||
title: string; | ||
subtitle?: string; | ||
content?: React.ReactNode; | ||
}; | ||
|
||
/** | ||
* The QueryView component to render the query results. | ||
* @param props - The props for the QueryView component. | ||
* @param props.useCaseQueryResponse - The response from the query service. | ||
* @param props.goBack - The function to go back to the previous page. | ||
* @param props.goBackToMultiplePatients - The function to go back to the multiple patients selection page. | ||
* @param props.goBackToMultiplePatients - The function to go back to the | ||
* multiple patients selection page. | ||
* @param props.queryName - The name of the saved query to display to the user | ||
* @returns The QueryView component. | ||
*/ | ||
const ResultsView: React.FC<ResultsViewProps> = ({ | ||
useCaseQueryResponse, | ||
goBack, | ||
goBackToMultiplePatients, | ||
queryName, | ||
}) => { | ||
useEffect(() => { | ||
window.scrollTo(0, 0); | ||
}, []); | ||
|
||
const accordionItems = | ||
mapQueryResponseToAccordionDataStructure(useCaseQueryResponse); | ||
|
||
const sideNavContent = accordionItems | ||
.map((item) => { | ||
if (item.content) { | ||
return { title: item.title, subtitle: item?.subtitle }; | ||
} | ||
}) | ||
.filter((i) => Boolean(i)) as NavSection[]; | ||
|
||
return ( | ||
<> | ||
<Alert type="info" headingLevel="h4" slim className="custom-alert"> | ||
Interested in learning more about using the TEFCA Query Connector for | ||
your jurisdiction? Send us an email at{" "} | ||
<a | ||
href="mailto:[email protected]" | ||
style={{ | ||
color: "inherit", | ||
fontWeight: "bold", | ||
textDecoration: "underline", | ||
}} | ||
> | ||
[email protected] | ||
</a> | ||
</Alert> | ||
|
||
<div className="results-banner"> | ||
<div className="results-banner-content usa-nav-container"> | ||
{goBackToMultiplePatients && ( | ||
<> | ||
<a | ||
href="#" | ||
onClick={() => goBackToMultiplePatients()} | ||
className="back-link" | ||
> | ||
<Icon.ArrowBack /> | ||
Return to search results | ||
</a> | ||
<div className="results-banner-divider">|</div> | ||
</> | ||
)} | ||
<div className={`${styles.resultsBannerContent}`}> | ||
<Backlink | ||
onClick={goBackToMultiplePatients ?? goBack} | ||
label="Return to search results" | ||
/> | ||
|
||
<a href="#" onClick={() => goBack()} className="back-link"> | ||
<button | ||
className="usa-button usa-button--outline margin-left-auto" | ||
onClick={() => goBack()} | ||
> | ||
New patient search | ||
</a> | ||
</button> | ||
</div> | ||
</div> | ||
<div className="main-container grid-container grid-row"> | ||
<div className="nav-wrapper tablet:grid-col-3"> | ||
<nav className="sticky-nav"> | ||
<SideNav /> | ||
</nav> | ||
<div className="margin-bottom-3"> | ||
<h2 className="margin-0" id="ecr-summary"> | ||
Patient Record | ||
</h2> | ||
<h3> | ||
Query:{" "} | ||
<span className="text-normal display-inline-block"> {queryName}</span> | ||
</h3> | ||
</div> | ||
|
||
<div className=" grid-container grid-row grid-gap-md padding-0 "> | ||
<div className="tablet:grid-col-3"> | ||
<ResultsViewSideNav items={sideNavContent} /> | ||
</div> | ||
<div className="tablet:grid-col-9"> | ||
<div className="ecr-content"> | ||
<h2 className="margin-bottom-3" id="ecr-summary"> | ||
Query Results | ||
</h2> | ||
<div className="margin-top-6"> | ||
<ResultsViewTable queryResponse={useCaseQueryResponse} /> | ||
</div> | ||
</div> | ||
<div className="tablet:grid-col-9 ecr-content"> | ||
<ResultsViewTable accordionItems={accordionItems} /> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; | ||
export default ResultsView; | ||
|
||
function mapQueryResponseToAccordionDataStructure( | ||
useCaseQueryResponse: UseCaseQueryResponse, | ||
) { | ||
const patient = | ||
useCaseQueryResponse.Patient && useCaseQueryResponse.Patient.length === 1 | ||
? useCaseQueryResponse.Patient[0] | ||
: null; | ||
const observations = useCaseQueryResponse.Observation | ||
? useCaseQueryResponse.Observation | ||
: null; | ||
const encounters = useCaseQueryResponse.Encounter | ||
? useCaseQueryResponse.Encounter | ||
: null; | ||
const conditions = useCaseQueryResponse.Condition | ||
? useCaseQueryResponse.Condition | ||
: null; | ||
const diagnosticReports = useCaseQueryResponse.DiagnosticReport | ||
? useCaseQueryResponse.DiagnosticReport | ||
: null; | ||
const medicationRequests = useCaseQueryResponse.MedicationRequest | ||
? useCaseQueryResponse.MedicationRequest | ||
: null; | ||
|
||
const accordionItems: ResultsViewAccordionItem[] = [ | ||
{ | ||
title: "Patient Info", | ||
subtitle: "Demographics", | ||
content: patient ? <Demographics patient={patient} /> : null, | ||
}, | ||
{ | ||
title: "Observations", | ||
content: observations ? ( | ||
<ObservationTable observations={observations} /> | ||
) : null, | ||
}, | ||
{ | ||
title: "Encounters", | ||
content: encounters ? <EncounterTable encounters={encounters} /> : null, | ||
}, | ||
{ | ||
title: "Conditions", | ||
content: conditions ? <ConditionsTable conditions={conditions} /> : null, | ||
}, | ||
{ | ||
title: "Diagnostic Reports", | ||
content: diagnosticReports ? ( | ||
<DiagnosticReportTable diagnosticReports={diagnosticReports} /> | ||
) : null, | ||
}, | ||
{ | ||
title: "Medication Requests", | ||
content: medicationRequests ? ( | ||
<MedicationRequestTable medicationRequests={medicationRequests} /> | ||
) : null, | ||
}, | ||
]; | ||
return accordionItems; | ||
} |
Oops, something went wrong.