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

1422/finder scaffolding + Q1 #1448

Merged
merged 18 commits into from
Sep 26, 2022
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
1 change: 0 additions & 1 deletion sites/public/layouts/eligibility.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ const EligibilityLayout = (props: EligibilityLayoutProps) => {
t(`eligibility.progress.sections.${label}`)
)}
mounted={OnClientSide()}
routes={ELIGIBILITY_SECTIONS.map((_label, i) => eligibilityRoute(i))}
/>
</div>
</div>
Expand Down
9 changes: 8 additions & 1 deletion sites/public/page_content/locale_overrides/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,12 @@
"basicsVideo.incomeRestrictionsSubtitle": "In this video, learn about income requirements for affordable housing that is paid for by governmental resources.",
"basicsVideo.residentTutorial": "Detroit Home Connect Resident Tutorial",
"basicsVideo.residentTutorialSubtitle": "Learn how to use the City's affordable housing locator, Detroit Home Connect, to understand affordable housing options in the City.",
"basicsCard.sectionTitle": "Learn more about the basics of affordable housing"
"basicsCard.sectionTitle": "Learn more about the basics of affordable housing",
"finder.progress.housingLabel": "Housing Needs",
"finder.progress.builingLabel": "Building Types",
"finder.progress.stepPreposition": "of",
"finder.bedRoomSize.question": "How many bedrooms do you need?",
"finder.questionSubtitle": "We'll use your selection to highlight possible rentals that match.",
"finder.multiselectHelper": "Select all that apply:",
"finder.skip": "Skip this and show me listings"
}
213 changes: 213 additions & 0 deletions sites/public/pages/finder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import {
encodeToFrontendFilterString,
FrontendListingFilterStateKeys,
ListingFilterState,
} from "@bloom-housing/shared-helpers"
import {
AppearanceStyleType,
Button,
Field,
Form,
FormCard,
ProgressNav,
StepHeader,
t,
} from "@bloom-housing/ui-components"
import axios from "axios"
import router from "next/router"

import React, { useEffect, useState } from "react"
import { useForm } from "react-hook-form"
import Layout from "../layouts/application"

interface finderField {
label: string
translation: string
selected: boolean
}

interface finderQuestion {
fieldGroupName: string
fields: finderField[]
}

interface finderForm {
[key: number]: finderQuestion
}

const Finder = () => {
// eslint-disable-next-line @typescript-eslint/unbound-method
const { register, handleSubmit, getValues } = useForm()
const [currentStep, setCurrentStep] = useState<number>(1)
const [formData, setFormData] = useState<finderForm>(null)
const activeQuestion = formData?.[currentStep]

const translationStringMap = {
studio: "studioPlus",
oneBdrm: "onePlus",
twoBdrm: "twoPlus",
threeBdrm: "threePlus",
fourBdrm: "fourPlus",
}

const stepLabels = [
t("finder.progress.housingLabel"),
t("t.accessibility"),
t("finder.progress.builingLabel"),
]

const onSubmit = (data: ListingFilterState) => {
void router.push(`/listings/filtered?page=${1}&limit=${8}${encodeToFrontendFilterString(data)}`)
}
useEffect(() => {
const getAndSetOptions = async () => {
try {
const response = await axios.get(`${process.env.backendApiBase}/listings/meta`)
const formQuestions: finderForm = {}
if (response?.data?.unitTypes) {
const bedroomFields = response.data.unitTypes.map((elem) => ({
label: elem.name,
translation: translationStringMap[elem.name],
selected: false,
}))
formQuestions[1] = { fieldGroupName: "bedRoomSize", fields: bedroomFields }
}
setFormData(formQuestions)
} catch (e) {
console.error(e)
}
}
void getAndSetOptions()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const ProgressHeader = () => {
return (
<div className="flex flex-col w-full px-2 md:px-0">
<div className="flex flex-row flex-wrap justify-between gap-y-4 gap-x-0.5">
<div className="md:text-xl capitalize font-bold">
{t("listingFilters.buttonTitleExtended")}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In mobile view the header and stepHeader doesn't have any padding between it and the site header
image

</div>
<StepHeader
currentStep={currentStep}
totalSteps={3}
stepPreposition={t("finder.progress.stepPreposition")}
stepLabeling={stepLabels}
></StepHeader>
</div>
<ProgressNav
currentPageSection={currentStep}
completedSections={currentStep - 1}
labels={stepLabels}
mounted={true}
style="bar"
></ProgressNav>
</div>
)
}

const nextQuestion = () => {
const userSelections = getValues()[formData[currentStep]["fieldGroupName"]]
const formCopy = { ...formData }
formCopy[currentStep]["fields"].forEach(
(field) => (field["selected"] = userSelections.includes(field))
)
setFormData(formCopy)
setCurrentStep(currentStep + 1)
}
const previousQuestion = () => {
const userSelections = getValues()[formData[currentStep]["fieldGroupName"]]
const formCopy = { ...formData }
formCopy[currentStep]["fields"].forEach(
(field) => (field["selected"] = userSelections.includes(field))
)
setFormData(formCopy)
setCurrentStep(currentStep - 1)
}

return (
<Layout>
<Form onSubmit={handleSubmit(onSubmit)} className="bg-gray-300 border-t border-gray-450">
<div className="md:mb-8 mt-8 mx-auto max-w-5xl">
{ProgressHeader()}
<FormCard>
{formData && (
<>
<div className="px-10 md:px-20 pt-6 md:pt-12 ">
<div className="">
<div className="text-3xl pb-4">
{t(`finder.${activeQuestion?.fieldGroupName}.question`)}
</div>
<div className="pb-8 border-b border-gray-450">
{t("finder.questionSubtitle")}
</div>
</div>
<div className="py-8">
<p className="pb-4">{t("finder.multiselectHelper")}</p>
<div className="finder-grid">
{activeQuestion?.fields?.map((field) => {
return (
<div
className="finder-grid__field"
key={FrontendListingFilterStateKeys[field.label]}
>
<Field
name="bedRoomSize"
register={register}
id={FrontendListingFilterStateKeys[field.label]}
label={t(`listingFilters.bedroomsOptions.${field.translation}`)}
key={FrontendListingFilterStateKeys[field.label]}
type="checkbox"
inputProps={{
value: FrontendListingFilterStateKeys[field.label],
defaultChecked: field.selected,
}}
bordered
/>
</div>
)
})}
</div>
</div>
</div>

<div className="bg-gray-300 flex flex-row-reverse justify-between py-8 px-20">
{currentStep === Object.keys(formData).length ? (
<Button type="submit" styleType={AppearanceStyleType.primary}>
{t("t.submit")}
</Button>
) : (
<Button
type="button"
onClick={nextQuestion}
styleType={AppearanceStyleType.primary}
>
{t("t.next")}
</Button>
)}
{currentStep > 1 && (
<Button
type="button"
onClick={previousQuestion}
styleType={AppearanceStyleType.primary}
>
{t("t.back")}
</Button>
)}
</div>

<div className="flex justify-center align-center bg-white py-8">
<a className="underline" href="/listings">
{t("finder.skip")}
</a>
</div>
</>
)}
</FormCard>
</div>
</Form>
</Layout>
)
}

export default Finder
7 changes: 6 additions & 1 deletion sites/public/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ export default function Home({ latestListings, comingSoonListings }) {
const heroInset: React.ReactNode = (
<>
<Link href="/listings">
<a className="hero__button hero__home-button">{t("welcome.seeRentalListings")}</a>
<a className="hero__button hero__rentals-button">{t("welcome.seeRentalListings")}</a>
</Link>
<Link href="/finder">
<a className="hero__button hero__finder-button">
{t("listingFilters.buttonTitleExtended")}
</a>
</Link>
</>
)
Expand Down
23 changes: 21 additions & 2 deletions sites/public/styles/forms.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.progress-nav {
padding: 20px 0;
padding-top: 1rem;
padding-bottom: 1.5rem;
@screen md {
padding: 31px 0;
padding-bottom: 3rem;
padding-top: 2rem;
}
}

Expand Down Expand Up @@ -45,3 +47,20 @@ li.progress-nav__item {
.field-note {
@apply font-normal;
}

.finder-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
row-gap: 0.5rem;
column-gap: 0.5rem;
.finder-grid__field {
.field {
--leftward-margin: 0rem;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦑

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol

}
width: 100%;
@screen md {
width: calc(50% - 0.25rem);
}
}
}
14 changes: 12 additions & 2 deletions sites/public/styles/headers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@
}

.hero__button {
color: black;
display: inline-block;
font-size: large;
max-width: 100%;
Expand All @@ -292,14 +291,25 @@
}
}

.hero__home-button {
.hero__rentals-button {
color: black;
background-color: #ffbe42;

&:hover {
@apply bg-primary;
color: white;
}
}
.hero__finder-button {
color: var(--bloom-color-white);
background-color: var(--bloom-color-primary-dark);
margin-left: var(--bloom-s2);
&:hover {
color: var(--bloom-color-white);
box-shadow: 0 0 0 var(--bloom-s0_5) var(--bloom-color-primary-dark) inset;
background-color: var(--bloom-color-black);
}
Comment on lines +307 to +311
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normal Detroit button on hover doesn't go to a darker color, but rather switches to an outlined version. Is this the standard that we want to keep? https://storybook.bloom.exygy.dev/?path=/story/actions-button--detroit-style

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ludtkemorgan Talked about this one offline a bit with Jesse and he pointed me to these docs: https://www.figma.com/file/slSZvBKEUduz5ldBiDsIzE/detroit-style-guide?node-id=0%3A33. Seems like storybook dev will need to be updated though to reflect this.

}

.page-header__title {
font-size: 1.5rem;
Expand Down
1 change: 1 addition & 0 deletions ui-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export * from "./src/headers/Hero"
export * from "./src/headers/PageHeader"
export * from "./src/headers/SiteHeader"
export * from "./src/headers/Heading"
export * from "./src/headers/StepHeader"

/* Helpers */
// export * from "./src/helpers/tableSummaries"
Expand Down
54 changes: 54 additions & 0 deletions ui-components/src/forms/Field.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,57 @@ export const CurrencyFieldError = () => {
/>
)
}

export const checkboxDefault = () => {
const { register, getValues, setValue } = useForm({ mode: "onChange" })
return (
<Field
register={register}
name={"Test Input"}
describedBy={"Test Input"}
label={"Test Input"}
type={"checkbox"}
/>
)
}

export const checkboxBordered = () => {
const { register, getValues, setValue } = useForm({ mode: "onChange" })
return (
<Field
register={register}
name={"Test Input"}
describedBy={"Test Input"}
label={"Test Input"}
type={"checkbox"}
bordered
/>
)
}

export const radioDefault = () => {
const { register, getValues, setValue } = useForm({ mode: "onChange" })
return (
<Field
register={register}
name={"Test Input"}
describedBy={"Test Input"}
label={"Test Input"}
type={"radio"}
/>
)
}

export const radioBordered = () => {
const { register, getValues, setValue } = useForm({ mode: "onChange" })
return (
<Field
register={register}
name={"Test Input"}
describedBy={"Test Input"}
label={"Test Input"}
type={"radio"}
bordered
/>
)
}
Loading