Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
24791d0
add naive process & icon list React components
Jul 14, 2022
2351891
add new copy (english)
Jun 21, 2022
7992d3e
add welcome step (will rename)
Jun 21, 2022
f9deb37
add WelcomeStep to the flow
Jun 21, 2022
a2b098f
organize list components into directories
Jun 21, 2022
d5f8f64
rename ipp/welcome to ipp/prepare
Jun 21, 2022
3ca3554
finish styling prepare component
Jun 22, 2022
9dd3f1f
cleanup
Jun 22, 2022
1135cb1
add placement location page
Jun 22, 2022
98727b1
new component for submit button in troubleshooting
Jun 23, 2022
b980674
LG-6087: Update IPP flow button styles to match accompanying links
NavaTim Jun 24, 2022
0ab9f74
LG-6087: Update IPP flow button styles to override other styles more …
NavaTim Jun 24, 2022
839b754
LG-6087: Fix minor issues with IPP button styling changes
NavaTim Jun 24, 2022
72eb0d6
remove errors
Jun 27, 2022
98d6432
collapse icon & process list components
Jun 27, 2022
49164a9
remove location & prepare steps
Jun 27, 2022
96a5d20
gate inclusion of in person steps
Jun 28, 2022
799b6be
add location collection and item
Jul 1, 2022
3ea860b
copied and modified uswds collection item class to follow design
Jul 7, 2022
3b462c1
use mockdata and props for locationCollectionItem
Jul 7, 2022
939655a
removed select from forms i18n
Jul 7, 2022
d0700df
add hours to en yml
Jul 8, 2022
bfe3264
align button on right side of container
Jul 8, 2022
57a7f53
add route and controller for locations
Jul 11, 2022
f0c1a70
fix controller location & route position
Jul 11, 2022
62e8c42
add controller and consume data in js app
Jul 14, 2022
6013b80
display data from request facilities json and transform data in js app
Jul 15, 2022
9d4b50a
error catching if response fails
Jul 15, 2022
cbae4a2
fixed import error
Jul 16, 2022
5a35166
fix locationcollectionitem key error
Jul 16, 2022
b01d0b5
add interface for postoffice and update formatlocation input type
Jul 16, 2022
51bd0f7
fix leftovers from rebase
Jul 18, 2022
fdb1ca1
move pilot facilities to proofer & refactor
Jul 18, 2022
2826724
update type in formatlocation
Jul 18, 2022
8ec532e
fix foreach error
Jul 18, 2022
ffd0496
location collection test added
Jul 18, 2022
65b67c4
location collection item test
Jul 18, 2022
739c9ef
updated locationCollectionItem tests
Jul 19, 2022
bdd2a09
btn submit
Jul 19, 2022
cea0af0
update button for mobile design
Jul 20, 2022
be4c590
update strings to remove spc and lengthen text
Jul 20, 2022
1bc1d2d
fix en merge issue
Jul 20, 2022
ea6502d
resolve merge conflicts with main
Jul 21, 2022
9644213
replace continue with select in in person spec
Jul 21, 2022
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
40 changes: 40 additions & 0 deletions app/assets/stylesheets/components/_location-collection-item.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.location-collection-item {
max-width: 64ex;
margin-bottom: 0;
margin-top: 0;
list-style-type: none;
padding-left: 0;
align-items: flex-start;
border-bottom-width: 1px;
border-bottom-style: solid;
display: flex;
margin-bottom: 1rem;
margin-top: 1rem;
padding-bottom: 1rem;
border-color: #CEDCED;
}

@media screen {
.wrap-name{
overflow-wrap: break-word;
}
}

@media screen and (min-width: 320px){
.usa-button-mobile {
width: -webkit-fill-available;
margin-top: 8px;
}
}

@media screen and (max-width: 480px){
.usa-button-mobile-hidden {
display: none;
}
}

@media screen and (min-width: 481px){
.usa-button-desktop-hidden {
display: none;
}
}
1 change: 1 addition & 0 deletions app/assets/stylesheets/components/all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
@import 'troubleshooting-options';
@import 'validated-checkbox';
@import 'i18n-dropdown';
@import 'location-collection-item';
18 changes: 18 additions & 0 deletions app/controllers/idv/in_person/usps_locations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require "json"

module Idv
module InPerson
class UspsLocationsController < ApplicationController

def index
begin
uspsResponse = UspsInPersonProofer.new.request_pilot_facilities()
rescue Faraday::ConnectionFailed => error
print error
end

render body: uspsResponse.to_json, content_type: 'application/json'
end
end
end
end
2 changes: 2 additions & 0 deletions app/javascript/packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export { default as IconListItem } from './icon-list/icon-list-item';
export { default as IconListTitle } from './icon-list/icon-list-title';
export { default as Link } from './link';
export { default as PageFooter } from './page-footer';
export { default as LocationCollection } from './location-collection';
export { default as LocationCollectionItem } from './location-collection-item';
export { default as PageHeading } from './page-heading';
export { default as ProcessList } from './process-list/process-list';
export { default as ProcessListHeading } from './process-list/process-list-heading';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { render } from '@testing-library/react';
import LocationCollectionItem from './location-collection-item';

describe('LocationCollectionItem', () => {
it('renders the component with expected class and children', () => {
const { container } = render(
<LocationCollectionItem
name=""
streetAddress=""
addressLine2=""
weekdayHours=""
saturdayHours=""
sundayHours=""
/>,
);

const wrapper = container.firstElementChild!;
expect(wrapper.classList.contains('location-collection-item')).to.be.true();
const locationCollectionItem = wrapper.firstElementChild!;
expect(locationCollectionItem.classList.contains('usa-collection__body')).to.be.true();
const display = locationCollectionItem.firstElementChild!;
expect(display.classList.contains('display-flex')).to.be.true();
expect(display.classList.contains('flex-justify')).to.be.true();
const heading = display.firstElementChild!;
expect(heading.classList.contains('usa-collection__heading')).to.be.true();
});

it('renders the component with expected data', () => {
const { getByText } = render(
<LocationCollectionItem
name="test name"
streetAddress="123 Test Address"
addressLine2="City, State 12345-1234"
weekdayHours="9 AM - 5 PM"
saturdayHours="9 AM - 6 PM"
sundayHours="Closed"
/>,
);

const name = getByText('123 Test Address').parentElement!;
expect(name.textContent).to.contain('test name');
const streetAddress = getByText('123 Test Address').parentElement!;
expect(streetAddress.textContent).to.contain('123 Test Address');
const addressLine2 = getByText('123 Test Address').parentElement!;
expect(addressLine2.textContent).to.contain('City, State 12345-1234');
const wkDayHours = getByText(
'in_person_proofing.body.location.retail_hours_weekday 9 AM - 5 PM',
).parentElement!;
expect(wkDayHours.textContent).to.contain('9 AM - 5 PM');
const satHours = getByText('in_person_proofing.body.location.retail_hours_sat 9 AM - 6 PM')
.parentElement!;
expect(satHours.textContent).to.contain('9 AM - 6 PM');
const sunHours = getByText('in_person_proofing.body.location.retail_hours_sun Closed')
.parentElement!;
expect(sunHours.textContent).to.contain('Closed');
});
});
45 changes: 45 additions & 0 deletions app/javascript/packages/components/location-collection-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Button } from '@18f/identity-components';
import { useI18n } from '@18f/identity-react-i18n';

export interface LocationCollectionItemProps {
name: string;
streetAddress: string;
addressLine2: string;
weekdayHours: string;
saturdayHours: string;
sundayHours: string;
}

function LocationCollectionItem({
name,
streetAddress,
addressLine2,
weekdayHours,
saturdayHours,
sundayHours,
}: LocationCollectionItemProps) {
const { t } = useI18n();
return (
<li className="location-collection-item">
<div className="usa-collection__body">
<div className="display-flex flex-justify">
<h3 className="usa-collection__heading wrap-name">{name}</h3>
<Button className="usa-button-mobile-hidden" type="submit">
{t('in_person_proofing.body.location.location_button')}
</Button>
</div>
<div>{streetAddress}</div>
<div>{addressLine2}</div>
<h4>{t('in_person_proofing.body.location.retail_hours_heading')}</h4>
<div>{`${t('in_person_proofing.body.location.retail_hours_weekday')} ${weekdayHours}`}</div>
<div>{`${t('in_person_proofing.body.location.retail_hours_sat')} ${saturdayHours}`}</div>
<div>{`${t('in_person_proofing.body.location.retail_hours_sun')} ${sundayHours}`}</div>
<Button className="usa-button-mobile usa-button-desktop-hidden" type="submit">
{t('in_person_proofing.body.location.location_button')}
</Button>
</div>
</li>
);
}

export default LocationCollectionItem;
31 changes: 31 additions & 0 deletions app/javascript/packages/components/location-collection.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { render } from '@testing-library/react';
import LocationCollection from './location-collection';

describe('LocationCollection', () => {
it('renders the component with expected class and children', () => {
const { getByText } = render(
<LocationCollection>
<div>LCI</div>
</LocationCollection>,
);

const child = getByText('LCI');
const item = child.parentElement!;

expect(item.classList.contains('usa-collection')).to.be.true();
expect(item.textContent).to.equal('LCI');
});

it('renders the component with custom class', () => {
const { getByText } = render(
<LocationCollection className="custom-class">
<div>LCI</div>
</LocationCollection>,
);

const child = getByText('LCI');
const item = child.parentElement!;

expect(item.classList.contains('custom-class')).to.be.true();
});
});
14 changes: 14 additions & 0 deletions app/javascript/packages/components/location-collection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { ReactNode } from 'react';

interface LocationCollectionProps {
className?: string;

children?: ReactNode;
}

function LocationCollection({ children, className }: LocationCollectionProps) {
const classes = ['usa-collection', className].filter(Boolean).join(' ');
return <ul className={classes}>{children}</ul>;
}

export default LocationCollection;
Original file line number Diff line number Diff line change
@@ -1,14 +1,80 @@
import { PageHeading } from '@18f/identity-components';
import { FormStepsButton } from '@18f/identity-form-steps';
import { useState, useEffect } from 'react';
import { useI18n } from '@18f/identity-react-i18n';
import { PageHeading, LocationCollectionItem, LocationCollection } from '@18f/identity-components';
import { LocationCollectionItemProps } from '@18f/identity-components/location-collection-item';

interface PostOffice {
address: string;
city: string;
name: string;
saturday_hours: string;
state: string;
sunday_hours: string;
weekday_hours: string;
zip_code_4: string;
zip_code_5: string;
}

const getResponse = async () => {
const response = await fetch('http://localhost:3000/verify/in_person/usps_locations').then(
(res) =>
res.json().catch((error) => {
throw error;
}),
);
return response;
};

const formatLocation = (postOffices: PostOffice[]) => {
const formattedLocations = [] as LocationCollectionItemProps[];
postOffices.forEach((po: PostOffice) => {
const location = {
name: po.name,
streetAddress: po.address,
addressLine2: `${po.city}, ${po.state}, ${po.zip_code_5}-${po.zip_code_4}`,
weekdayHours: po.weekday_hours,
saturdayHours: po.saturday_hours,
sundayHours: po.sunday_hours,
} as LocationCollectionItemProps;
formattedLocations.push(location);
});
return formattedLocations;
};

function InPersonLocationStep() {
const { t } = useI18n();
const [locationData, setLocationData] = useState([] as LocationCollectionItemProps[]);

useEffect(() => {
(async () => {
const fetchedLocations = await getResponse().catch((error) => {
throw error;
});
const formattedLocations = formatLocation(fetchedLocations);
setLocationData(formattedLocations);
})();
}, []);

return (
<>
<PageHeading>{t('in_person_proofing.headings.location')}</PageHeading>
<FormStepsButton.Continue />

<p>{t('in_person_proofing.body.location.location_step_about')}</p>
<LocationCollection>
{locationData &&
locationData.map((item) => (
<LocationCollectionItem
key={item.name}
name={`${item.name} — ${t('in_person_proofing.body.location.post_office')}`}
streetAddress={item.streetAddress}
addressLine2={item.addressLine2}
weekdayHours={item.weekdayHours}
saturdayHours={item.saturdayHours}
sundayHours={item.sundayHours}
/>
))}
{locationData.length < 1 && <h4>No locations found.</h4>}
</LocationCollection>
</>
);
}
Expand Down
Loading