Skip to content

Commit

Permalink
feat(RV-420): Add home page first time UX (#444)
Browse files Browse the repository at this point in the history
  • Loading branch information
knguyenrise8 authored Nov 29, 2024
1 parent 7d130c2 commit e2c2ce4
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 21 deletions.
53 changes: 53 additions & 0 deletions frontend/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,56 @@
.nav-link {
text-decoration: none;
}

.home-header {
height: 80px;
display: flex;
align-items: center;
border-bottom: 1px solid rgba(0, 94, 162, 0.14);
box-shadow: 0px 2px 4px 0px rgba(0, 94, 162, 0.04);
}

.first-time-content {
padding-inline: 116px;
width: 800px;
height: 700px;
background: white;
border: 1px solid #F0F0F0 !important;
}

.first-time-header {
color: #000;
font-size: 22px;
font-style: normal;
font-weight: 700;
line-height: normal;
}

.first-time-copy {
color: #000;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 162%;
}

.first-time-card {
border-radius: 5px;
border: 2px solid #F0F0F0;
background: #009EC1;
height: 300px;
width: 550px;
}

.img-copy {
color: #FFF;
font-size: 22px;
font-style: normal;
font-weight: 700;
line-height: normal;
}

.card-column-image {
padding-left: 36px;
width: 200px;
}
89 changes: 89 additions & 0 deletions frontend/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

// Mock the imports
vi.mock('./components/AppHeader/AppHeader.tsx', () => ({
AppHeader: () => <div data-testid="app-header">AppHeader</div>,
}));

vi.mock('./components/TemplatesIndex/TemplatesIndex.tsx', () => ({
TemplatesIndex: () => <div data-testid="templates-index">TemplatesIndex</div>,
}));

vi.mock('./assets/comment.svg', () => ({
default: 'comment.svg',
}));

vi.mock('./assets/csv.svg', () => ({
default: 'csv.svg',
}));

describe('App component', () => {
beforeEach(() => {
localStorage.clear();
});

const renderComponent = () => {
render(
<BrowserRouter>
<App />
</BrowserRouter>
);
};

it('renders the AppHeader component', () => {
renderComponent();
expect(screen.getByTestId('app-header')).toBeInTheDocument();
});

it('displays first-time experience content on initial visit', () => {
renderComponent();
expect(screen.getByTestId('first-time-exp')).toBeInTheDocument();
});

it('displays regular content on subsequent visits', () => {
localStorage.setItem('hasVisited', 'true');
renderComponent();
expect(screen.queryByTestId('first-time-exp')).not.toBeInTheDocument();
expect(screen.getByTestId('templates-index')).toBeInTheDocument();
});

it('navigates to the correct URL when a navigation link is clicked (0)', () => {
renderComponent();
const navLink = screen.getByTestId('nav-link-0');
fireEvent.click(navLink);
expect(navLink).toHaveAttribute('href', '/');
});

it('navigates to the correct URL when a navigation link is clicked (1)', () => {
renderComponent();
const navLink = screen.getByTestId('nav-link-1');
fireEvent.click(navLink);
expect(navLink).toHaveAttribute('href', '/labels');
});

it('navigates to the correct URL when a navigation link is clicked (2)', () => {
renderComponent();
const navLink = screen.getByTestId('nav-link-2');
fireEvent.click(navLink);
expect(navLink).toHaveAttribute('href', '/dashboard');
});

it('navigates to the new template upload page when the button is clicked', () => {
renderComponent();
const newTemplateButton = screen.getByTestId('new-template-button');
fireEvent.click(newTemplateButton);
expect(window.location.pathname).toBe('/new-template/upload');
});

it('renders navigation links correctly', () => {
renderComponent();
const navLinks = ['Annotate and Extract', 'Label Management', 'Dashboard'];
navLinks.forEach((_, idx) => {
expect(screen.getByTestId(`nav-link-${idx}`)).toBeInTheDocument();
});
});
});
94 changes: 73 additions & 21 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import "./App.scss";
import { Link } from "@trussworks/react-uswds";
import { useLocation } from "react-router-dom";
import { useState, useEffect } from "react";
import { Button, Link } from "@trussworks/react-uswds";
import { useLocation, useNavigate } from "react-router-dom";

import { AppHeader } from "./components/AppHeader/AppHeader.tsx";

import { TemplatesIndex } from "./components/TemplatesIndex/TemplatesIndex.tsx";

import Comment from './assets/comment.svg';
import CSV from './assets/csv.svg';
import "./App.scss";

function App() {
const { pathname } = useLocation();
const navigate = useNavigate();
const [isFirstVisit, setIsFirstVisit] = useState(false);

useEffect(() => {
const hasVisited = localStorage.getItem("hasVisited");
if (!hasVisited) {
setIsFirstVisit(true);
localStorage.setItem("hasVisited", "true");
}
}, []);

const navLinks = [
{ text: "Annotate and Extract", url: "/" },
{
Expand All @@ -19,37 +33,75 @@ function App() {

return (
<>
<div className="display-flex flex-column width-full height-full">
<div className="display-flex flex-column width-full height-full" data-testid="app-container">
<AppHeader jurisdiction={`Demo STLT`} />
<div className="display-flex flex-row height-full">
<div className="flex-3 padding-top-1 padding-left-1 padding-right-4 minw-15 usa-dark-background bg-primary-dark text-base-lightest display-flex flex-column flex-gap-1 maxw-30 side-nav">
<div className="display-flex flex-row height-full" data-testid="main-content">
<div className="flex-3 padding-top-1 padding-left-1 padding-right-4 minw-15 usa-dark-background bg-primary-dark text-base-lightest display-flex flex-column flex-gap-1 maxw-30 side-nav" data-testid="side-nav">
<div className="display-flex flex-column flex-align-start padding-top-2">
{navLinks.map((i, idx) => {
return (
<Link
key={idx}
href={i.url}
className={`border-left-2px padding-left-1 padding-top-2 padding-bottom-2 nav-link ${i.url === pathname ? "text-bold" : "border-primary-dark"}`}
data-testid={`nav-link-${idx}`}
>
{i.text}
</Link>
);
})}
</div>
</div>

<div className="flex-10 display-flex flex-column">
<h2 className="padding-left-2">Annotate and Extract</h2>
<div className=" flex-1 padding-left-2 padding-right-2 bg-idwa-light">
<p>
<span className="text-bold">Welcome Blake, </span>
</p>
<p>
Extract data from any PDFs, or images to send to your
surveillance systems using data from your saved templates or
create new segmentations.
</p>
<TemplatesIndex />
<div className="flex-10 display-flex flex-column bg-idwa-light" data-testid="content-area">
<h2 className="padding-left-2 bg-white margin-top-0 home-header" data-testid="home-header">Annotate and Extract</h2>
<div className="display-flex flex-justify-center app-content-container width-full" data-testid="app-content-container">
{isFirstVisit ? (
<div className="bg-white display-flex flex-column flex-justify flex-align-center first-time-content" data-testid="first-time-exp">
<h3 className="first-time-header" data-testid="first-time-header">
Welcome to Report Vision
</h3>
<p className="first-time-copy" data-testid="first-time-copy">
Let ReportVision take your lab reports from faxes and PDF’s and extract the data for seamless ingestion into your surveillance system.
</p>
<div className="first-time-card flex-row display-flex width-full flex-justify-center flex-align-center" data-testid="first-time-card">
<div className="display-flex flex-column flex-justify-center height-full card-column-image">
<img height="70px" width="130px" src={Comment} alt="comment" data-testid="comment-image" />
<img className="margin-top-6" height="100px" width="100px" src={CSV} alt="csv" data-testid="csv-image" />
</div>
<div className="display-flex flex-column flex-justify card-row">
<p className="img-copy margin-bottom-8" data-testid="img-copy-1">
1. Create templates for new lab reports.
</p>
<p className="img-copy" data-testid="img-copy-2">
2. Extract data and download it.
</p>
</div>
</div>
<p className="first-time-copy" data-testid="first-time-copy-2">
Let’s create your first annotated template for a lab report to enable quick extractions.
</p>
<Button
type="button"
className="usa-button display-flex flex-align-center margin-left-auto margin-right-auto margin-bottom-7"
onClick={() => navigate("/new-template/upload")}
data-testid="new-template-button"
>
+ New Template
</Button>
</div>
) : (
<div className="flex-1 padding-left-2 padding-right-2 bg-idwa-light" data-testid="regular-content">
<p>
<span className="text-bold">Welcome Blake, </span>
</p>
<p>
Extract data from any PDFs, or images to send to your
surveillance systems using data from your saved templates or
create new segmentations.
</p>
<TemplatesIndex />
</div>
)}
</div>
</div>
</div>
Expand All @@ -58,4 +110,4 @@ function App() {
);
}

export default App;
export default App;
Loading

0 comments on commit e2c2ce4

Please sign in to comment.