Skip to content

Commit

Permalink
1383/listings management, ranking and results (#1433)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilyjablonski committed Jul 1, 2021
1 parent 97d0d25 commit a30fb13
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ All notable changes to this project will be documented in this file. The format
- Add Additional Fees section to listing management ([#1377](https://github.com/bloom-housing/bloom/pull/1377)) (Emily Jablonski)
- Add Building Details and Intro section to listing management ([#1420](https://github.com/bloom-housing/bloom/pull/1420)) (Emily Jablonski)
- Add Building Features section to listing management ([#1412](https://github.com/bloom-housing/bloom/pull/1412)) (Emily Jablonski)
- Add Rankings and Results section to listing management ([#1433](https://github.com/bloom-housing/bloom/pull/1433)) (Emily Jablonski)

- Fixed:

Expand Down
2 changes: 2 additions & 0 deletions backend/core/archer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ export const ArcherListing: Listing = {
waitlistMaxSize: 300,
name: "Archer Studios",
waitlistCurrentSize: 300,
waitlistOpenSpots: 0,
isWaitlistOpen: true,
// Addng displayWaitListSize for #707
displayWaitlistSize: false,
// TODO confirm not used anywhere
Expand Down
6 changes: 6 additions & 0 deletions backend/core/src/seeds/listings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2477,6 +2477,8 @@ const defaultListing: ListingSeedType = {
specialNotes: "Custom special notes text",
status: ListingStatus.active,
waitlistCurrentSize: null,
waitlistOpenSpots: null,
isWaitlistOpen: false,
waitlistMaxSize: null,
whatToExpect: {
allInfoWillBeVerified: "Custom all info will be verified text",
Expand Down Expand Up @@ -2544,6 +2546,8 @@ const tritonListing: ListingSeedType = {
status: ListingStatus.active,
waitlistCurrentSize: 400,
waitlistMaxSize: 600,
waitlistOpenSpots: 200,
isWaitlistOpen: true,
whatToExpect: null,
}

Expand Down Expand Up @@ -2610,6 +2614,8 @@ const coliseumListing: ListingSeedType = {
status: ListingStatus.active,
waitlistCurrentSize: 0,
waitlistMaxSize: 3000,
waitlistOpenSpots: 3000,
isWaitlistOpen: true,
whatToExpect: null,
}

Expand Down
2 changes: 2 additions & 0 deletions sites/partners/pages/listings/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import DetailAdditionalEligibility from "../../../src/listings/PaperListingDetai
import DetailLeasingAgent from "../../../src/listings/PaperListingDetails/sections/DetailLeasingAgent"
import DetailAdditionalFees from "../../../src/listings/PaperListingDetails/sections/DetailAdditionalFees"
import DetailBuildingFeatures from "../../../src/listings/PaperListingDetails/sections/DetailBuildingFeatures"
import DetailRankingsAndResults from "../../../src/listings/PaperListingDetails/sections/DetailRankingsAndResults"

export default function ApplicationsList() {
const router = useRouter()
Expand Down Expand Up @@ -111,6 +112,7 @@ export default function ApplicationsList() {
<DetailBuildingFeatures />
<DetailAdditionalEligibility />
<DetailAdditionalDetails />
<DetailRankingsAndResults />
<DetailLeasingAgent />
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useContext } from "react"
import { t, GridSection, ViewItem } from "@bloom-housing/ui-components"
import { ListingContext } from "../../ListingContext"

const DetailRankingsAndResults = () => {
const listing = useContext(ListingContext)

return (
<GridSection
className="bg-primary-lighter"
title={t("listings.sections.rankingsResultsTitle")}
grid={false}
inset
>
<GridSection columns={3}>
<ViewItem label={t("listings.waitlist.openQuestion")}>
{listing.isWaitlistOpen ? t("t.yes") : t("t.no")}
</ViewItem>
</GridSection>
{listing.isWaitlistOpen && (
<GridSection columns={3}>
<ViewItem label={t("listings.waitlist.sizeQuestion")}>
{listing.waitlistMaxSize ? t("t.yes") : t("t.no")}
</ViewItem>
</GridSection>
)}
{listing.waitlistMaxSize && (
<GridSection columns={3}>
<ViewItem label={t("listings.waitlist.maxSize")}>{listing.waitlistMaxSize}</ViewItem>
<ViewItem label={t("listings.waitlist.currentSize")}>
{listing.waitlistCurrentSize}
</ViewItem>
<ViewItem label={t("listings.waitlist.openSize")}>{listing.waitlistOpenSpots}</ViewItem>
</GridSection>
)}
</GridSection>
)
}

export default DetailRankingsAndResults
40 changes: 31 additions & 9 deletions sites/partners/src/listings/PaperListingForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
CSVFormattingType,
CountyCode,
} from "@bloom-housing/backend-core/types"
import { YesNoAnswer } from "../../applications/PaperApplicationForm/FormTypes"

import Aside from "../Aside"
import FormListingData from "./sections/FormListingData"
Expand All @@ -29,8 +30,13 @@ import AdditionalFees from "./sections/AdditionalFees"
import BuildingDetails from "./sections/BuildingDetails"
import ListingIntro from "./sections/ListingIntro"
import BuildingFeatures from "./sections/BuildingFeatures"
import RankingsAndResults from "./sections/RankingsAndResults"

type FormListing = ListingCreate & ListingUpdate
export type FormListing = ListingCreate &
ListingUpdate & {
waitlistOpenQuestion?: YesNoAnswer
waitlistSizeQuestion?: YesNoAnswer
}

type ListingFormProps = {
listing?: FormListing
Expand Down Expand Up @@ -81,8 +87,10 @@ const defaults: FormListing = {
rentalHistory: "",
requiredDocuments: "",
status: ListingStatus.pending,
waitlistCurrentSize: 0,
waitlistMaxSize: 0,
waitlistCurrentSize: null,
waitlistMaxSize: null,
isWaitlistOpen: null,
waitlistOpenSpots: null,
whatToExpect: [],
units: [],
accessibility: "",
Expand Down Expand Up @@ -137,6 +145,22 @@ const ListingForm = ({ listing, editMode }: ListingFormProps) => {
}
}

const formatFormData = (data: FormListing) => {
const showWaitlistNumber =
data.waitlistOpenQuestion === YesNoAnswer.Yes && data.waitlistSizeQuestion === YesNoAnswer.Yes
return {
...data,
isWaitlistOpen: data.waitlistOpenQuestion === YesNoAnswer.Yes,
yearBuilt: data.yearBuilt ? Number(data.yearBuilt) : null,
waitlistCurrentSize:
data.waitlistCurrentSize && showWaitlistNumber ? Number(data.waitlistCurrentSize) : null,
waitlistMaxSize:
data.waitlistMaxSize && showWaitlistNumber ? Number(data.waitlistMaxSize) : null,
waitlistOpenSpots:
data.waitlistOpenSpots && showWaitlistNumber ? Number(data.waitlistOpenSpots) : null,
}
}

/*
@data: form data comes from the react-hook-form
@redirect: open listing details or reset form
Expand All @@ -145,16 +169,13 @@ const ListingForm = ({ listing, editMode }: ListingFormProps) => {
setAlert(null)
setLoading(true)
try {
const typedData: FormListing = {
...data,
yearBuilt: data.yearBuilt ? Number(data.yearBuilt) : null,
}
const formattedData = formatFormData(data)
const result = editMode
? await listingsService.update({
listingId: listing.id,
body: { id: listing.id, ...typedData },
body: { id: listing.id, ...formattedData },
})
: await listingsService.create({ body: typedData })
: await listingsService.create({ body: formattedData })
setLoading(false)

if (result) {
Expand Down Expand Up @@ -228,6 +249,7 @@ const ListingForm = ({ listing, editMode }: ListingFormProps) => {
<BuildingFeatures />
<AdditionalEligibility />
<AdditionalDetails />
<RankingsAndResults listing={listing} />
<LeasingAgent />
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const AdditionalEligibility = () => {
{t("listings.sections.additionalEligibilityTitle")}
</span>
<span className="form-section__description">
{t("listings.sections.additionalEligibilitySubtext")}{" "}
{t("listings.sections.additionalEligibilitySubtext")}
</span>
<GridSection columns={2}>
<Textarea
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const AdditionalFees = () => {
<GridSection grid={false} separator>
<span className="form-section__title">{t("listings.sections.additionalFees")}</span>
<span className="form-section__description">
{t("listings.sections.additionalFeesSubtitle")}{" "}
{t("listings.sections.additionalFeesSubtitle")}
</span>
<GridSection columns={3}>
<Field
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React from "react"
import { useFormContext } from "react-hook-form"
import { t, GridSection, Field, FieldGroup, GridCell } from "@bloom-housing/ui-components"

import { YesNoAnswer } from "../../../applications/PaperApplicationForm/FormTypes"
import { FormListing } from "../index"

type RankingsAndResultsProps = {
listing?: FormListing
}

const RankingsAndResults = ({ listing }: RankingsAndResultsProps) => {
const formMethods = useFormContext()

// eslint-disable-next-line @typescript-eslint/unbound-method
const { register, watch } = formMethods

const waitlistOpen: YesNoAnswer = watch(
"waitlistOpenQuestion",
listing?.isWaitlistOpen ? YesNoAnswer.Yes : YesNoAnswer.No
)
const showWaitlistSize: YesNoAnswer = watch(
"waitlistSizeQuestion",
listing?.waitlistMaxSize ? YesNoAnswer.Yes : YesNoAnswer.No
)

const yesNoRadioOptions = [
{
label: t("t.yes"),
value: YesNoAnswer.Yes,
},
{
label: t("t.no"),
value: YesNoAnswer.No,
},
]

return (
<div>
<GridSection grid={false} separator>
<span className="form-section__title">{t("listings.sections.rankingsResultsTitle")}</span>
<span className="form-section__description">
{t("listings.sections.rankingsResultsSubtitle")}
</span>
<GridSection columns={8} className={"flex items-center"}>
<GridCell span={2}>
<p className="field-label m-4 ml-0">{t("listings.waitlist.openQuestion")}</p>
</GridCell>
<FieldGroup
name="waitlistOpenQuestion"
type="radio"
register={register}
fields={[
{
...yesNoRadioOptions[0],
id: "waitlistOpenYes",
defaultChecked: listing && listing.isWaitlistOpen,
},

{
...yesNoRadioOptions[1],
id: "waitlistOpenNo",
defaultChecked: listing && !listing.isWaitlistOpen,
},
]}
/>
</GridSection>
{waitlistOpen === YesNoAnswer.Yes && (
<GridSection columns={8} className={"flex items-center"}>
<GridCell span={2}>
<p className="field-label m-4 ml-0">{t("listings.waitlist.sizeQuestion")}</p>
</GridCell>
<FieldGroup
name="waitlistSizeQuestion"
type="radio"
register={register}
fields={[
{
...yesNoRadioOptions[0],
id: "showWaitlistSizeYes",
defaultChecked: listing && listing.waitlistMaxSize !== null,
},
{
...yesNoRadioOptions[1],
id: "showWaitlistSizeNo",
defaultChecked: listing && !listing.waitlistMaxSize,
},
]}
/>
</GridSection>
)}
{showWaitlistSize === YesNoAnswer.Yes && waitlistOpen === YesNoAnswer.Yes && (
<GridSection columns={3} className={"flex items-center"}>
<Field
name="waitlistMaxSize"
id="waitlistMaxSize"
register={register}
label={t("listings.waitlist.maxSizeQuestion")}
placeholder={t("listings.waitlist.maxSize")}
type={"number"}
/>
<Field
name="waitlistCurrentSize"
id="waitlistCurrentSize"
register={register}
label={t("listings.waitlist.currentSizeQuestion")}
placeholder={t("listings.waitlist.currentSize")}
type={"number"}
/>
<Field
name="waitlistOpenSpots"
id="waitlistOpenSpots"
register={register}
label={t("listings.waitlist.openSizeQuestion")}
placeholder={t("listings.waitlist.openSize")}
type={"number"}
/>
</GridSection>
)}
</GridSection>
</div>
)
}

export default RankingsAndResults
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ describe("<ApplicationSection>", () => {
const listing = Object.assign({}, ArcherListing) as Listing
const days = 10
listing.applicationOpenDate = new Date(moment().format())
listing.waitlistCurrentSize = 0
listing.waitlistCurrentSize = 25
listing.isWaitlistOpen = true
listing.waitlistMaxSize = 100
listing.waitlistOpenSpots = 75
listing.applicationDueDate = new Date(moment().add(days, "days").format())
const { getByText, getAllByText } = render(
<ApplicationSection listing={listing} internalFormRoute="/forms" />
Expand Down
9 changes: 8 additions & 1 deletion ui-components/__tests__/page_components/Waitlist.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ archer.unitsSummarized = {}
archer.unitsSummarized.byNonReservedUnitType = []
archer.unitsSummarized.byReservedType = []
archer.waitlistCurrentSize = 300
archer.waitlistMaxSize = 500
archer.waitlistOpenSpots = 200

// @ts-ignore
triton.unitsSummarized = {}
Expand All @@ -23,16 +25,19 @@ afterEach(cleanup)

describe("<Waitlist>", () => {
it("renders with a closed waitlist", () => {
archer.isWaitlistOpen = false
const { getByText, getAllByText } = render(<Waitlist listing={archer} />)
expect(getByText("Waitlist Closed")).toBeTruthy()
expect(getByText("Current Waitlist Size"))
expect(getByText("Final Waitlist Size"))
expect(getAllByText("300").length).toBe(2)
expect(getAllByText("300").length).toBe(1)
})
it("renders with an open waitlist", () => {
triton.unitsAvailable = 0
triton.waitlistCurrentSize = 40
triton.waitlistMaxSize = 100
triton.waitlistOpenSpots = 60
triton.isWaitlistOpen = true
const { getByText } = render(<Waitlist listing={triton} />)
expect(getByText("Waitlist is open")).toBeTruthy()
expect(getByText("Current Waitlist Size"))
Expand All @@ -46,6 +51,8 @@ describe("<Waitlist>", () => {
newListing.unitsAvailable = 1
newListing.waitlistCurrentSize = 0
newListing.waitlistMaxSize = 10
newListing.waitlistOpenSpots = 10
newListing.isWaitlistOpen = true
const { getByText } = render(<Waitlist listing={newListing} />)
expect(
getByText(
Expand Down
Loading

0 comments on commit a30fb13

Please sign in to comment.