diff --git a/src/Components/BreadCrumbs/BreadCrumbs.tsx b/src/Components/BreadCrumbs/BreadCrumbs.tsx index 03ed49c..2d08925 100644 --- a/src/Components/BreadCrumbs/BreadCrumbs.tsx +++ b/src/Components/BreadCrumbs/BreadCrumbs.tsx @@ -1,11 +1,20 @@ -import { Link } from "react-router-dom"; +import { Link, useLocation } from "react-router-dom"; import { Icon } from "@justfixnyc/component-library"; +import { Address } from "../Pages/Home/Home"; +import { toTitleCase } from "../../helpers"; import "./BreadCrumbs.scss"; -interface BreadCrumbs { - crumbs: { path?: string; name?: string; active?: boolean }[]; -} -export const BreadCrumbs: React.FC = ({ crumbs }) => { +type Crumb = { path?: string; name?: string; active?: boolean }; + +type BreadCrumbs = { + address?: Address; +}; + +export const BreadCrumbs: React.FC = ({ address }) => { + const location = useLocation(); + console.log(location); + const crumbs = makeBreadCrumbs(location.pathname, address); + const crumbpath = crumbs.flatMap((crumb, index, array) => { const CrumbElement = crumb.active ? ( @@ -34,3 +43,34 @@ export const BreadCrumbs: React.FC = ({ crumbs }) => { }); return
{crumbpath}
; }; + +const makeBreadCrumbs = (pathname: string, address?: Address) => { + const crumbs: Crumb[] = [ + { path: "/", name: "Home" }, + { + path: "/confirm_address", + name: breadCrumbAddress(address), + }, + { path: "/form", name: "Survey" }, + { path: "/results", name: "Result" }, + ]; + + if (["/portfolio_size", "/rent_stabilization"].includes(pathname)) { + crumbs.push({ path: pathname, name: "Guide", active: true }); + return crumbs; + } else { + return crumbs.map((crumb) => { + return { ...crumb, active: crumb.path == pathname }; + }); + } +}; + +function breadCrumbAddress(address?: Address, maxLength = 45) { + if (!address) return "Your address"; + const addrShort = toTitleCase( + `${address?.houseNumber} ${address?.streetName}` + ); + return addrShort.length > maxLength + ? `${addrShort.substring(0, maxLength)}\u2026` + : addrShort; +} diff --git a/src/Components/Header/Header.scss b/src/Components/Header/Header.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/Components/Header/Header.tsx b/src/Components/Header/Header.tsx new file mode 100644 index 0000000..b192d46 --- /dev/null +++ b/src/Components/Header/Header.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { BreadCrumbs } from "../BreadCrumbs/BreadCrumbs"; +import { Address } from "../Pages/Home/Home"; +import { BackLink } from "../JFCLLinkInternal"; + +type HeaderProps = { + title: string | React.ReactNode; + subtitle?: string; + pageType?: string; + address?: Address; + isGuide?: boolean; + children?: React.ReactNode; +}; + +export const Header: React.FC = ({ + address, + pageType, + title, + subtitle, + isGuide = false, + children, +}) => { + return ( +
+
+ + {isGuide && ( +
+ Back to Coverage Result +
+ )} + {pageType && ( +
{pageType}
+ )} +

{title}

+ {subtitle && ( +
{subtitle}
+ )} + {children} +
+
+ ); +}; diff --git a/src/Components/Pages/ConfirmAddress/ConfirmAddress.scss b/src/Components/Pages/ConfirmAddress/ConfirmAddress.scss index 8517383..3199ab5 100644 --- a/src/Components/Pages/ConfirmAddress/ConfirmAddress.scss +++ b/src/Components/Pages/ConfirmAddress/ConfirmAddress.scss @@ -6,19 +6,7 @@ $mapBoxPadding: 1.5rem; // 24px $mapImgWidth: calc($contentBoxWidth - (2 * $mapBoxPadding)); // 838px $mapImgHeight: 356px; -.confirmation__wrapper { - .headline-section { - background-color: $OFF_WHITE_NEW; - padding-bottom: 0; - - .headline-section__content { - // width: calc($mapImgWidth + (2 * 1.5rem)); - .headline-section__subtitle { - margin-bottom: 0; - } - } - } - +#confirm-address-page { .content-box { padding: $mapBoxPadding; diff --git a/src/Components/Pages/ConfirmAddress/ConfirmAddress.tsx b/src/Components/Pages/ConfirmAddress/ConfirmAddress.tsx index 43db765..9fa29be 100644 --- a/src/Components/Pages/ConfirmAddress/ConfirmAddress.tsx +++ b/src/Components/Pages/ConfirmAddress/ConfirmAddress.tsx @@ -1,13 +1,13 @@ +import { useLoaderData, useNavigate } from "react-router-dom"; import { Button } from "@justfixnyc/component-library"; + import { Address } from "../Home/Home"; -import "./ConfirmAddress.scss"; -import { useLoaderData, useNavigate } from "react-router-dom"; import { ContentBox } from "../../ContentBox/ContentBox"; import { BackLink } from "../../JFCLLinkInternal"; -import { BreadCrumbs } from "../../BreadCrumbs/BreadCrumbs"; import { useGetBuildingData, useSendGceData } from "../../../api/hooks"; import { GCEUser } from "../../../types/APIDataTypes"; -import { breadCrumbAddress } from "../../../helpers"; +import { Header } from "../../Header/Header"; +import "./ConfirmAddress.scss"; export const ConfirmAddress: React.FC = () => { const navigate = useNavigate(); @@ -44,29 +44,12 @@ export const ConfirmAddress: React.FC = () => { }; return ( -
-
-
- - -

Confirm your address

-
- We'll use info about your building from public data sources to help - learn if you're covered -
-
-
+
+
diff --git a/src/Components/Pages/Form/Form.scss b/src/Components/Pages/Form/Form.scss index b707a7e..e84a6d6 100644 --- a/src/Components/Pages/Form/Form.scss +++ b/src/Components/Pages/Form/Form.scss @@ -4,12 +4,7 @@ $inputTopMargin: 1.5rem; //24px -.form__wrapper { - position: relative; - padding-top: calc(70px + 1rem); // TODO: use var for breadcrumbs height - padding-left: 3rem; // 48px - padding-right: 3rem; // 48px - +#survey-page { .jfcl-input-header__label { margin-top: 0; margin-bottom: 0; diff --git a/src/Components/Pages/Form/Form.tsx b/src/Components/Pages/Form/Form.tsx index ad8513c..5511000 100644 --- a/src/Components/Pages/Form/Form.tsx +++ b/src/Components/Pages/Form/Form.tsx @@ -7,11 +7,11 @@ import { Address } from "../Home/Home"; import { useGetBuildingData, useSendGceData } from "../../../api/hooks"; import { useSessionStorage } from "../../../hooks/useSessionStorage"; import { RadioGroup } from "../../RadioGroup/RadioGroup"; -import { BreadCrumbs } from "../../BreadCrumbs/BreadCrumbs"; import { InfoBox } from "../../InfoBox/InfoBox"; -import { breadCrumbAddress, formatNumber } from "../../../helpers"; +import { formatNumber } from "../../../helpers"; import { cleanFormFields } from "../../../api/helpers"; import { BuildingData, GCEUser } from "../../../types/APIDataTypes"; +import { Header } from "../../Header/Header"; import "./Form.scss"; export type FormFields = { @@ -82,25 +82,13 @@ export const Form: React.FC = () => { }; return ( -
-
- - -

Screener Survey

- -

- We'll use your answers to help determine your coverage. -

+
+
+
diff --git a/src/Components/Pages/PortfolioSize/PortfolioSize.scss b/src/Components/Pages/PortfolioSize/PortfolioSize.scss index 0113dfd..cff8010 100644 --- a/src/Components/Pages/PortfolioSize/PortfolioSize.scss +++ b/src/Components/Pages/PortfolioSize/PortfolioSize.scss @@ -1,7 +1,7 @@ @import "../content-page.scss"; @import "../../../colors.scss"; -#portfolio-size-guide { +#portfolio-size-page { .headline-section { padding-top: 2.5rem; // 40px } diff --git a/src/Components/Pages/PortfolioSize/PortfolioSize.tsx b/src/Components/Pages/PortfolioSize/PortfolioSize.tsx index ff091aa..552c630 100644 --- a/src/Components/Pages/PortfolioSize/PortfolioSize.tsx +++ b/src/Components/Pages/PortfolioSize/PortfolioSize.tsx @@ -18,6 +18,7 @@ import { } from "../../../helpers"; import "./PortfolioSize.scss"; import { InfoBox } from "../../InfoBox/InfoBox"; +import { Header } from "../../Header/Header"; // const LOOM_EMBED_URL = // "https://www.loom.com/embed/cef3632773a14617a0e8ec407c77e513?sid=93a986f7-ccdc-4048-903c-974fed826119"; @@ -45,26 +46,19 @@ export const PortfolioSize: React.FC = () => { const { data: bldgData, isLoading, error } = useGetBuildingData(bbl); return ( -
-
-
- Back to Coverage Result - {error && ( -
- There was an error loading your results, please try again in a few - minutes. -
- )} -
Guide
-

- Finding out if your landlord owns other apartments -

-
- Everything you need to know about researching your landlord’s other - potential properties. +
+
+ {error && ( +
+ There was an error loading your results, please try again in a few + minutes.
-
-
+ )} +
diff --git a/src/Components/Pages/Results/Results.scss b/src/Components/Pages/Results/Results.scss index cf67155..10c55d0 100644 --- a/src/Components/Pages/Results/Results.scss +++ b/src/Components/Pages/Results/Results.scss @@ -66,18 +66,23 @@ $eligibilityTablePaddingH: 36px; } } +.eligibility__table { + margin-top: 3rem; // 48px +} + .eligibility__table__header { display: flex; - padding-bottom: $eligibilityTablePaddingH; flex-direction: column; - gap: 10px; + padding: 1.125rem 1.125rem 2.25rem 1.125rem; // 20px 20px 36px 20px; + gap: 0.75rem; // 12px + border-bottom: 1px solid $GREY_NEW; - .eligibility__table__header-title { - @include eyebrow_small_desktop; + span { + @include body_large_desktop; } - - .eligibility__table__header-subtitle { - @include h3_desktop; + p { + @include body_standard_desktop; + margin: 0; } } diff --git a/src/Components/Pages/Results/Results.tsx b/src/Components/Pages/Results/Results.tsx index 78ec54e..20a4076 100644 --- a/src/Components/Pages/Results/Results.tsx +++ b/src/Components/Pages/Results/Results.tsx @@ -1,4 +1,4 @@ -import { useEffect, useLayoutEffect, useState } from "react"; +import { useEffect } from "react"; import { Link, NavigateFunction, @@ -7,7 +7,6 @@ import { useSearchParams, } from "react-router-dom"; import { Button, Icon } from "@justfixnyc/component-library"; -import classNames from "classnames"; import { useGetBuildingData, useSendGceData } from "../../../api/hooks"; import { BuildingData, GCEUser } from "../../../types/APIDataTypes"; @@ -23,9 +22,8 @@ import { extractDeterminations, } from "../../../api/helpers"; import { Address } from "../Home/Home"; -import { breadCrumbAddress, getDetermination } from "../../../helpers"; +import { getDetermination } from "../../../helpers"; import { ContentBox, ContentBoxItem } from "../../ContentBox/ContentBox"; -import { BreadCrumbs } from "../../BreadCrumbs/BreadCrumbs"; import JFCLLinkInternal from "../../JFCLLinkInternal"; import { GoodCauseExercisingRights, @@ -33,6 +31,7 @@ import { RentStabilizedProtections, UniversalProtections, } from "../../KYRContent/KYRContent"; +import { Header } from "../../Header/Header"; import "./Results.scss"; export const Results: React.FC = () => { @@ -86,21 +85,23 @@ export const Results: React.FC = () => { const isRentStabilized = eligibilityResults?.rentRegulation.determination === "INELIGIBLE"; - const [showTable, setShowTable] = useState(); - - // TODO: not sure this is right way to handle this. Should we get and store - // eligibility data on submission of the from on the previous page instead? - useLayoutEffect(() => { - if (determination && isRentStabilized !== undefined) { - setShowTable( - determination && determination === "INELIGIBLE" && !isRentStabilized - ); - } - }, [determination, isRentStabilized]); - return ( - <> -
+
+
+ ) : ( + "Loading your results..." + ) + } + subtitle="We'll use your answers to help determine your coverage" + address={address} + > {error && (
There was an error loading your results, please try again in a few @@ -111,69 +112,12 @@ export const Results: React.FC = () => {
Loading your results...
)} -
- -
Coverage Result
-
- Good Cause Eviction Screener -
- {bldgData && eligibilityResults && ( - <> -

- -

- -
- based on the data we have about your apartment and the - information you’ve provided. -
- - )} - {showTable !== undefined && ( - <> -
+
@@ -214,7 +158,7 @@ export const Results: React.FC = () => {
- +
); }; @@ -289,6 +233,15 @@ const EligibilityCriteriaTable: React.FC<{ eligibilityResults: EligibilityResults | undefined; }> = ({ eligibilityResults }) => (
+
+ + How we determined your coverage + +

+ Assessment of coverage is based on the publicly available data about + your building and the information you’ve provided. +

+
    {eligibilityResults?.rent && ( @@ -329,6 +282,7 @@ const EligibilityNextSteps: React.FC<{ eligibilityResults?.portfolioSize?.determination === "UNKNOWN"; const rentRegulationUnknown = eligibilityResults?.rentRegulation?.determination === "UNKNOWN"; + console.log([portfolioSizeUnknown, rentRegulationUnknown]); const steps = [portfolioSizeUnknown, rentRegulationUnknown].filter( Boolean ).length; @@ -374,7 +328,7 @@ const EligibilityNextSteps: React.FC<{ className="next-step" open > - {bldgData.related_properties.length ? ( + {bldgData.related_properties ? ( <>

    {`Good Cause Eviction law only covers tenants whose landlord owns diff --git a/src/Components/Pages/content-page.scss b/src/Components/Pages/content-page.scss index eea6cce..28d0739 100644 --- a/src/Components/Pages/content-page.scss +++ b/src/Components/Pages/content-page.scss @@ -21,14 +21,19 @@ $eligibilityTablePaddingH: 36px; .headline-section { position: relative; padding-top: 70px; - padding-bottom: 2.5rem; // 40px + padding-bottom: 3rem; // 48px background-color: $OFF_WHITE_200; + border-bottom: 1px solid $OFF_BLACK; .headline-section__content { + width: 100%; max-width: $contentBoxWidth; - @media (max-width: 772px) { - width: 100%; + margin-top: 3rem; // 48px + + .headline-section__back-link { + margin-bottom: 0.75rem; // 12px } + .headline-section__page-type { @include eyebrow_large_desktop; padding-top: 30px; @@ -46,7 +51,6 @@ $eligibilityTablePaddingH: 36px; .headline-section__title { display: flex; flex-direction: column; - margin: 2.625rem 0; //42px gap: 4px; @media print { margin: 24px 0; @@ -55,7 +59,7 @@ $eligibilityTablePaddingH: 36px; .headline-section__subtitle { @include body_large_desktop; - margin-bottom: 2.25rem; // 36px + margin-top: 1.125rem; // 18px @media print { margin-bottom: 0; } @@ -71,6 +75,7 @@ $eligibilityTablePaddingH: 36px; .content-section { background-color: $OFF_WHITE_NEW; + padding-top: 3rem; // 48px .content-section__content { max-width: $contentBoxWidth; diff --git a/src/helpers.ts b/src/helpers.ts index 88d3643..4ae257c 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -3,7 +3,7 @@ import { EligibilityResults, Determination } from "./hooks/eligibility"; import { RelatedProperty } from "./types/APIDataTypes"; import { Address } from "./Components/Pages/Home/Home"; -function toTitleCase(x: string) { +export function toTitleCase(x: string) { return x.replace( /\w\S*/g, (text: string) => diff --git a/src/types/APIDataTypes.ts b/src/types/APIDataTypes.ts index 6746093..db54b94 100644 --- a/src/types/APIDataTypes.ts +++ b/src/types/APIDataTypes.ts @@ -37,7 +37,7 @@ export type BuildingData = { end_421a: string; end_j51: string; acris_docs: AcrisDocument[]; - related_properties: RelatedProperty[]; + related_properties: RelatedProperty[] | null; }; // Tenants2 API