Skip to content

Commit

Permalink
PDF Page (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
ailZhou authored Nov 15, 2024
1 parent 6ae1ffd commit 5d76592
Show file tree
Hide file tree
Showing 18 changed files with 399 additions and 25 deletions.
1 change: 0 additions & 1 deletion .env.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ IAM_PERMISSIONS_BOUNDARY="bound"
LOCAL_LOGIN=true
LOGGING_BUCKET=log-bucket
S3_LOCAL_ENDPOINT=http://localhost:4569
SAR_REPORT_TABLE_NAME=local-sar-reports
SKIP_PREFLIGHT_CHECK=true
QM_REPORT_TABLE_NAME=local-qm-reports

Expand Down
8 changes: 5 additions & 3 deletions services/ui-src/src/components/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useContext } from "react";
import { Routes, Route } from "react-router-dom";
import { Routes, Route, useLocation } from "react-router-dom";
import {
AppRoutes,
Error,
Expand All @@ -19,7 +19,9 @@ export const App = () => {
const context = useContext(UserContext);
const { logout } = context;
const { user, showLocalLogins } = useStore();
// const { pathname } = useLocation();
const { pathname } = useLocation();

const isExportPage = pathname.includes("/export");

// TODO: fire tealium page view on route change
/*
Expand All @@ -38,7 +40,7 @@ export const App = () => {
{user && (
<Flex sx={sx.appLayout}>
<Timeout />
<Header handleLogout={logout} />
{!isExportPage && <Header handleLogout={logout} />}
<Container sx={sx.appContainer}>
<ErrorBoundary FallbackComponent={Error}>
<AppRoutes />
Expand Down
9 changes: 7 additions & 2 deletions services/ui-src/src/components/app/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ProfilePage,
DashboardPage,
NotFoundPage,
ExportedReportPage,
} from "components";
import { CreateReportOptions } from "components/pages/CreateReportOptions/CreateReportOptions";
import { ReportPageWrapper } from "components/report/ReportPageWrapper";
Expand All @@ -22,8 +23,12 @@ export const AppRoutes = () => {
<Route path="/report/QM" element={<CreateReportOptions />} />
<Route
path="/report/:reportType/:state/:reportId"
element={<ReportPageWrapper></ReportPageWrapper>}
></Route>
element={<ReportPageWrapper />}
/>
<Route
path="/report/:reportType/:state/:reportId/export"
element={<ExportedReportPage />}
/>
</Routes>
</main>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { render, screen } from "@testing-library/react";
import { ExportedReportBanner } from "./ExportedReportBanner";
import userEvent from "@testing-library/user-event";
import qmVerbiage from "verbiage/export/qm-export";

describe("ExportedReportBanner", () => {
beforeEach(() => {
render(<ExportedReportBanner></ExportedReportBanner>);
jest.spyOn(window, "print").mockImplementation(() => {});
});
it("ExportedReportBanner is visible", () => {
expect(screen.getByText(qmVerbiage.reportBanner.intro)).toBeInTheDocument();
});
it("Test click of print button", async () => {
const pdfButton = screen.getByText("Download PDF");
await userEvent.click(pdfButton);
expect(window.print).toBeCalled();
});
});
54 changes: 54 additions & 0 deletions services/ui-src/src/components/export/ExportedReportBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Box, Text, Button, Image } from "@chakra-ui/react";
import pdfIcon from "assets/icons/pdf/icon_pdf_white.svg";
import qmVerbiage from "verbiage/export/qm-export";

export const ExportedReportBanner = () => {
const { reportBanner } = qmVerbiage;

const onClickHandler = () => {
window?.print();
};

return (
<Box sx={sx.container}>
<Text>{reportBanner.intro}</Text>
<Button sx={sx.pdfButton} onClick={onClickHandler}>
<Image src={pdfIcon} w={5} alt="PDF Icon" />
{reportBanner.pdfButton}
</Button>
</Box>
);
};

const sx = {
container: {
position: "sticky",
zIndex: "sticky",
top: "0",
marginBottom: "2rem",
padding: "2rem 2rem",
background: "white",
boxShadow: "0px 3px 9px rgba(0, 0, 0, 0.2)",
textAlign: "center",
".mobile &": {
padding: "2rem 1rem",
},
"@media print": {
display: "none",
},
p: {
marginBottom: "1rem",
fontSize: "xl",
fontWeight: "bold",
".mobile &": {
fontSize: "lg",
},
},
},
pdfButton: {
img: {
width: "1rem",
marginRight: "0.5rem",
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { render, screen } from "@testing-library/react";
import { ExportedReportWrapper } from "./ExportedReportWrapper";
import { ElementType, FormPageTemplate, PageElement, PageType } from "types";

const elements: PageElement[] = [
{
type: ElementType.Header,
text: "General Information",
},
{
type: ElementType.Textbox,
label: "Contact title",
helperText:
"Enter person's title or a position title for CMS to contact with questions about this request.",
},
{
type: ElementType.Date,
label: "Reporting period start date",
helperText:
"What is the reporting period Start Date applicable to the measure results?",
},
];

const section: FormPageTemplate = {
id: "mock-id",
title: "mock-title",
type: PageType.Standard,
elements: elements,
sidebar: true,
};

describe("ExportedReportWrapper", () => {
it("ExportedReportWrapper is visible", () => {
render(<ExportedReportWrapper section={section}></ExportedReportWrapper>);
expect(screen.getByText("Contact title")).toBeInTheDocument();
});
});
77 changes: 77 additions & 0 deletions services/ui-src/src/components/export/ExportedReportWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {
Box,
Stack,
Table,
Thead,
Th,
Tr,
Td,
Tbody,
Text,
} from "@chakra-ui/react";
import {
ElementType,
FormPageTemplate,
MeasurePageTemplate,
ParentPageTemplate,
} from "types";

export const ExportedReportWrapper = ({ section }: Props) => {
const elements = section.elements
?.filter(
(element) =>
element.type !== ElementType.ButtonLink &&
element.type !== ElementType.Accordion &&
element.type !== ElementType.Header &&
element.type !== ElementType.MeasureTable
)
.map((element: any) => {
return {
label: element?.label ?? "",
helperText: element.helperText ?? "",
value: element.value ?? "",
answer: element.answer ?? "No Response",
type: element.type ?? "",
};
});

return (
<Stack>
{elements?.length! > 0 ? (
<Table variant="export">
<Thead>
<Tr>
<Th>Indicator</Th>
<Th>Response</Th>
</Tr>
</Thead>
<Tbody>
{elements?.map(
(element, idx) =>
element?.label && (
<Tr key={`${element.label}.${idx}`}>
<Td>
<Text>{element?.label}</Text>
{element?.helperText && (
<Text>{element?.helperText}</Text>
)}
{element?.type === ElementType.Date && (
<Text>MM/DD/YYYY</Text>
)}
</Td>
<Td>{element?.answer}</Td>
</Tr>
)
)}
</Tbody>
</Table>
) : (
<Box>N/A</Box>
)}
</Stack>
);
};

export interface Props {
section: ParentPageTemplate | FormPageTemplate | MeasurePageTemplate;
}
4 changes: 4 additions & 0 deletions services/ui-src/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export { Timeout } from "./layout/Timeout";
export { Card } from "./cards/Card";
export { EmailCard } from "./cards/EmailCard";
export { TemplateCard } from "./cards/TemplateCard";
// export
export { ExportedReportBanner } from "./export/ExportedReportBanner";
export { ExportedReportWrapper } from "./export/ExportedReportWrapper";
// fields
export { TextField } from "./fields/TextField";
// forms
Expand All @@ -31,6 +34,7 @@ export { LoginIDM } from "./logins/LoginIDM";
export { HelpPage } from "./pages/HelpPage/HelpPage";
export { ProfilePage } from "./pages/Profile/ProfilePage";
export { NotFoundPage } from "./pages/NotFound/NotFoundPage";
export { ExportedReportPage } from "./pages/Export/ExportedReportPage";
// menus
export { Menu } from "./menus/Menu";
export { MenuOption } from "./menus/MenuOption";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button, Td, Tr } from "@chakra-ui/react";
import { Table } from "components";
import { useNavigate } from "react-router-dom";
import { Report, UserRoles } from "types";
import { formatMonthDayYear, useStore } from "utils";
import { formatMonthDayYear, reportBasePath, useStore } from "utils";

interface DashboardTableProps {
reports: Report[];
Expand Down Expand Up @@ -43,7 +43,3 @@ export const DashboardTable = ({ reports }: DashboardTableProps) => {
</Table>
);
};

const reportBasePath = (report: Report) => {
return `/report/${report.type}/${report.state}/${report.id}`;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { screen, render } from "@testing-library/react";
import { useStore } from "utils";
import { ExportedReportPage } from "./ExportedReportPage";

jest.mock("utils", () => ({
useStore: jest.fn(),
}));

const report = {
type: "QM",
id: "mock-report-id",
state: "CO",
title: "mock-title",
pages: [
{ childPageIds: ["1", "2"] },
{ title: "Section 1", id: "id-1" },
{ title: "Section 2", id: "id-2" },
],
};

describe("ExportedReportPage", () => {
beforeEach(() => {
jest.clearAllMocks();
(useStore as unknown as jest.Mock).mockReturnValue({
report: report,
});
});
it("ExportReportPage is visible", () => {
render(<ExportedReportPage></ExportedReportPage>);
expect(screen.getByText("CO mock-title")).toBeInTheDocument();
});
});
Loading

0 comments on commit 5d76592

Please sign in to comment.