Skip to content
4 changes: 2 additions & 2 deletions shared-helpers/src/locales/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@
"listings.costsNotIncluded": "Costs not included",
"listings.confirmedPreferenceList": "Confirmed %{preference} List",
"listings.creditHistory": "Credit History",
"listings.criminalBackground": "Criminal Background",
"listings.criminalBackground": "Justice Involvement",
"listings.depositMayBeHigherForLowerCredit": "May be higher for lower credit scores",
"listings.depositOrMonthsRent": "or one month's rent",
"listings.developmentalDisabilities": "Persons with developmental disabilities",
Expand Down Expand Up @@ -1122,6 +1122,6 @@
"welcome.underConstructionButton": "See all under construction",
"welcome.viewAdditionalHousing": "View additional housing opportunities and resources",
"welcome.viewAdditionalHousingTruncated": "View resources",
"whatToExpect.default": "Applicants will be contacted by the property agent in rank order until vacancies are filled. All of the information that you have provided will be verified and your eligibility confirmed. Your application will be removed from the waitlist if you have made any fraudulent statements. If we cannot verify a housing preference that you have claimed, you will not receive the preference but will not be otherwise penalized. Should your application be chosen, be prepared to fill out a more detailed application and provide required supporting documents.",
"whatToExpect.default": "Applicants will be contacted by the property manager on a first come, first serve basis, until vacancies are filled. All of the information that you have provided will be verified and your eligibility confirmed. Your application may be removed if you have knowingly or unknowingly made any false statements.",
"whatToExpect.label": "What to Expect"
}
1 change: 1 addition & 0 deletions sites/partners/page_content/locale_overrides/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@
"listings.marketingSection.seasons": "Seasons",
"listings.maxAnnualIncome": "Maximum Annual Income",
"listings.newListing": "New Listing",
"listings.newNonRegulatedListing": "New Non-Regulated Listing",
"listings.pdfHelperText": "Select PDF file",
"listings.pickupAddress": "Pickup Address",
"listings.postmarksConsideredQuestion": "Are postmarks considered?",
Expand Down
289 changes: 187 additions & 102 deletions sites/partners/src/components/listings/PaperListingForm/UnitForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ type UnitFormProps = {
defaultUnit: TempUnit | undefined
nextId: number
draft: boolean
isNonRegulated?: boolean
}

const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormProps) => {
const UnitForm = ({
onSubmit,
onClose,
defaultUnit,
nextId,
draft,
isNonRegulated,
}: UnitFormProps) => {
const { amiChartsService } = useContext(AuthContext)

const [amiChartsOptions, setAmiChartsOptions] = useState([])
Expand Down Expand Up @@ -73,6 +81,11 @@ const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormPro
name: "maxOccupancy",
})

const isFixedRent: string = useWatch({
control,
name: "isFixedRent",
})

const maxAmiHouseholdSize = 8

const getAmiChartTableData = () => {
Expand Down Expand Up @@ -353,6 +366,14 @@ const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormPro
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [rentType])

// Set rent type to "fixed" for non-regulated listings
useEffect(() => {
if (isNonRegulated) {
setValue("rentType", "fixed")
setValue("isFixedRent", "true")
}
}, [isNonRegulated, setValue])

// sets the options for the ami charts
useEffect(() => {
if (amiCharts.length === 0 || amiChartsOptions.length) return
Expand Down Expand Up @@ -480,84 +501,90 @@ const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormPro
</Grid.Row>
</SectionWithGrid>

<hr className="spacer-section-above spacer-section" />
<SectionWithGrid heading={t("listings.unit.eligibility")}>
<Grid.Row columns={4}>
<Select
id="amiChart.id"
name="amiChart.id"
label={t("listings.unit.amiChart")}
placeholder={t("listings.unit.amiChart")}
register={register}
controlClassName="control"
options={amiChartsOptions}
error={fieldHasError(errors?.amiChart?.id)}
errorMessage={t("errors.requiredFieldError")}
validation={{ required: true }}
inputProps={{
onChange: (value) => {
setValue("amiPercentage", undefined)
clearErrors("amiPercentage")
clearErrors("amiChart.id")
;[...Array(maxAmiHouseholdSize)].forEach((_, index) => {
setValue(`maxIncomeHouseholdSize${index + 1}`, undefined)
})
if (value?.target?.value && !loading && amiChartsOptions) {
void fetchAmiChart(value.target?.value)
setIsAmiPercentageDirty(true)
}
},
}}
/>

<Select
id={"amiPercentage"}
name="amiPercentage"
label={t("listings.unit.amiPercentage")}
placeholder={t("listings.unit.amiPercentage")}
register={register}
controlClassName="control"
options={amiChartPercentageOptions}
inputProps={{
onChange: () => {
setIsAmiPercentageDirty(true)
clearErrors("amiPercentage")
},
}}
error={fieldHasError(errors?.amiPercentage)}
errorMessage={t("errors.requiredFieldError")}
validation={{ required: !!amiChartID }}
disabled={!amiChartID}
/>
</Grid.Row>
</SectionWithGrid>
{!isNonRegulated && (
<>
<hr className="spacer-section-above spacer-section" />
<SectionWithGrid heading={t("listings.unit.eligibility")}>
<Grid.Row columns={4}>
<Select
id="amiChart.id"
name="amiChart.id"
label={t("listings.unit.amiChart")}
placeholder={t("listings.unit.amiChart")}
register={register}
controlClassName="control"
options={amiChartsOptions}
error={fieldHasError(errors?.amiChart?.id)}
errorMessage={t("errors.requiredFieldError")}
validation={{ required: true }}
inputProps={{
onChange: (value) => {
setValue("amiPercentage", undefined)
clearErrors("amiPercentage")
clearErrors("amiChart.id")
;[...Array(maxAmiHouseholdSize)].forEach((_, index) => {
setValue(`maxIncomeHouseholdSize${index + 1}`, undefined)
})
if (value?.target?.value && !loading && amiChartsOptions) {
void fetchAmiChart(value.target?.value)
setIsAmiPercentageDirty(true)
}
},
}}
/>

<section className="mb-6 sm:w-1/2 sm:pr-3">
<table className={"w-full text-xs td-plain th-plain"}>
<thead>
<tr>
<th>{t("listings.householdSize")}</th>
<th>{t("listings.maxAnnualIncome")}</th>
</tr>
</thead>
<tbody>{getAmiChartTableData()}</tbody>
</table>
</section>
<Select
id={"amiPercentage"}
name="amiPercentage"
label={t("listings.unit.amiPercentage")}
placeholder={t("listings.unit.amiPercentage")}
register={register}
controlClassName="control"
options={amiChartPercentageOptions}
inputProps={{
onChange: () => {
setIsAmiPercentageDirty(true)
clearErrors("amiPercentage")
},
}}
error={fieldHasError(errors?.amiPercentage)}
errorMessage={t("errors.requiredFieldError")}
validation={{ required: !!amiChartID }}
disabled={!amiChartID}
/>
</Grid.Row>
</SectionWithGrid>

<section className="mb-6 sm:w-1/2 sm:pr-3">
<table className={"w-full text-xs td-plain th-plain"}>
<thead>
<tr>
<th>{t("listings.householdSize")}</th>
<th>{t("listings.maxAnnualIncome")}</th>
</tr>
</thead>
<tbody>{getAmiChartTableData()}</tbody>
</table>
</section>
</>
)}

<Grid>
<Grid.Row columns={4}>
<FieldGroup
name="rentType"
type="radio"
register={register}
fields={rentTypeOptions}
fieldClassName="m-0"
fieldGroupClassName="flex h-12 items-center"
groupLabel={t("listings.unit.rentType")}
fieldLabelClassName={styles["label-option"]}
/>
{!isNonRegulated && (
<FieldGroup
name="rentType"
type="radio"
register={register}
fields={rentTypeOptions}
fieldClassName="m-0"
fieldGroupClassName="flex h-12 items-center"
groupLabel={t("listings.unit.rentType")}
fieldLabelClassName={styles["label-option"]}
/>
)}

{rentType === "fixed" && (
{(rentType === "fixed" || isNonRegulated) && (
<>
<Grid.Cell>
<Field
Expand All @@ -571,20 +598,74 @@ const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormPro
/>
</Grid.Cell>

<Grid.Cell>
<Field
id="monthlyRent"
name="monthlyRent"
label={t("listings.unit.monthlyRent")}
placeholder="0.00"
register={register}
type="number"
prepend="$"
/>
</Grid.Cell>
{isNonRegulated && (
<Grid.Cell>
<FieldGroup
name="isFixedRent"
type="radio"
register={register}
groupLabel="Rent Type"
fieldLabelClassName={`${styles["label-option"]} seeds-m-bs-2`}
fields={[
{
label: "Fixed Rent",
value: "true",
id: "isFixedRentYes",
},
{
label: "Rent Range",
value: "false",
id: "isFixedRentNo",
},
]}
/>
</Grid.Cell>
)}

{(!isNonRegulated || (isNonRegulated && isFixedRent === "true")) && (
<Grid.Cell>
<Field
id="monthlyRent"
name="monthlyRent"
label={t("listings.unit.monthlyRent")}
placeholder="0.00"
register={register}
type="number"
prepend="$"
/>
</Grid.Cell>
)}

{isNonRegulated && isFixedRent === "false" && (
<>
<Grid.Cell>
<Field
id="monthlyRateLowEnd"
name="monthlyRateLowEnd"
label="Monthly Rent From:"
placeholder="0.00"
register={register}
type="number"
prepend="$"
/>
</Grid.Cell>

<Grid.Cell>
<Field
id="monthlyRateHighEnd"
name="monthlyRateHighEnd"
label="Monthly Rent To:"
placeholder="0.00"
register={register}
type="number"
prepend="$"
/>
</Grid.Cell>
</>
)}
</>
)}
{rentType === "percentage" && (
{!isNonRegulated && rentType === "percentage" && (
<Grid.Cell>
<Field
id="monthlyRentAsPercentOfIncome"
Expand All @@ -599,22 +680,26 @@ const UnitForm = ({ onSubmit, onClose, defaultUnit, nextId, draft }: UnitFormPro
</Grid.Row>
</Grid>

<hr className="spacer-section-above spacer-section" />
<SectionWithGrid heading={t("t.accessibility")}>
<Grid.Row columns={4}>
<Grid.Cell>
<Select
id="unitAccessibilityPriorityTypes.id"
name="unitAccessibilityPriorityTypes.id"
label={t("listings.unit.accessibilityPriorityType")}
placeholder={t("listings.unit.accessibilityPriorityType")}
register={register}
controlClassName="control"
options={unitPrioritiesOptions}
/>
</Grid.Cell>
</Grid.Row>
</SectionWithGrid>
{!isNonRegulated && (
<>
<hr className="spacer-section-above spacer-section" />
<SectionWithGrid heading={t("t.accessibility")}>
<Grid.Row columns={4}>
<Grid.Cell>
<Select
id="unitAccessibilityPriorityTypes.id"
name="unitAccessibilityPriorityTypes.id"
label={t("listings.unit.accessibilityPriorityType")}
placeholder={t("listings.unit.accessibilityPriorityType")}
register={register}
controlClassName="control"
options={unitPrioritiesOptions}
/>
</Grid.Cell>
</Grid.Row>
</SectionWithGrid>
</>
)}
</Card.Section>
</Card>
</Form>
Expand Down
Loading