diff --git a/api/src/utilities/application-export-helpers.ts b/api/src/utilities/application-export-helpers.ts index cbcdfb497d..70c1464925 100644 --- a/api/src/utilities/application-export-helpers.ts +++ b/api/src/utilities/application-export-helpers.ts @@ -42,6 +42,10 @@ export const getExportHeaders = ( user.jurisdictions, FeatureFlagEnum.disableWorkInRegion, ); + const enableApplicationStatus = doAnyJurisdictionHaveFeatureFlagSet( + user.jurisdictions, + FeatureFlagEnum.enableApplicationStatus, + ); const headers: CsvHeader[] = [ { @@ -83,6 +87,34 @@ export const getExportHeaders = ( format: (val: string): string => formatLocalDate(val, dateFormat, timeZone ?? process.env.TIME_ZONE), }, + ], + ); + + if (enableApplicationStatus) { + headers.push( + ...[ + { + path: 'status', + label: 'Application Status', + }, + { + path: 'manualLotteryPositionNumber', + label: 'Lottery Position Number', + }, + { + path: 'accessibleUnitWaitlistNumber', + label: 'Waitlist Position (Accessible Unit)', + }, + { + path: 'conventionalUnitWaitlistNumber', + label: 'Waitlist Position (Conventional Unit)', + }, + ], + ); + } + + headers.push( + ...[ { path: 'applicant.firstName', label: 'Primary Applicant First Name', diff --git a/sites/partners/__tests__/components/applications/PaperApplicationForm/sections/FormApplicationData.test.tsx b/sites/partners/__tests__/components/applications/PaperApplicationForm/sections/FormApplicationData.test.tsx index 3aa3beb8eb..7ba0affa08 100644 --- a/sites/partners/__tests__/components/applications/PaperApplicationForm/sections/FormApplicationData.test.tsx +++ b/sites/partners/__tests__/components/applications/PaperApplicationForm/sections/FormApplicationData.test.tsx @@ -4,6 +4,7 @@ import userEvent from "@testing-library/user-event" import { LanguagesEnum, ApplicationStatusEnum, + ReviewOrderTypeEnum, } from "@bloom-housing/shared-helpers/src/types/backend-swagger" import { FormProviderWrapper } from "../../../../testUtils" import { FormApplicationData } from "../../../../../src/components/applications/PaperApplicationForm/sections/FormApplicationData" @@ -147,4 +148,66 @@ describe("", () => { expect((statusSelect as HTMLSelectElement).value).toBe(ApplicationStatusEnum.waitlistDeclined) }) }) + + describe("Application status fields", () => { + it("renders waitlist fields when status is waitlist", async () => { + render( + + + + ) + + const statusSelect = screen.getByLabelText(/status/i) + await userEvent.selectOptions(statusSelect, ApplicationStatusEnum.waitlist) + + expect(screen.getByLabelText(/accessible unit waitlist \(AUWL\)/i)).toBeInTheDocument() + expect(screen.getByLabelText(/conventional unit waitlist \(CUWL\)/i)).toBeInTheDocument() + expect(screen.queryByLabelText(/lottery number/i)).not.toBeInTheDocument() + }) + + it("renders waitlist fields when status is waitlistDeclined", async () => { + render( + + + + ) + + const statusSelect = screen.getByLabelText(/status/i) + await userEvent.selectOptions(statusSelect, ApplicationStatusEnum.waitlistDeclined) + + expect(screen.getByLabelText(/accessible unit waitlist \(AUWL\)/i)).toBeInTheDocument() + expect(screen.getByLabelText(/conventional unit waitlist \(CUWL\)/i)).toBeInTheDocument() + }) + + it("does not render waitlist fields when status is not waitlist and no numbers are present", async () => { + render( + + + + ) + + const statusSelect = screen.getByLabelText(/status/i) + await userEvent.selectOptions(statusSelect, ApplicationStatusEnum.submitted) + + const auwlInput = screen.getByLabelText(/accessible unit waitlist/i) + const cuwlInput = screen.getByLabelText(/conventional unit waitlist/i) + + // Check if the closest Grid.Cell has the hidden class + expect(auwlInput.closest(".hidden")).toBeInTheDocument() + expect(cuwlInput.closest(".hidden")).toBeInTheDocument() + }) + + it("renders lottery position field when reviewOrderType is lottery", () => { + render( + + + + ) + + expect(screen.getByLabelText(/lottery number/i)).toBeInTheDocument() + }) + }) }) diff --git a/sites/partners/__tests__/pages/application/index.test.tsx b/sites/partners/__tests__/pages/application/index.test.tsx index fae2866731..ba7a937e33 100644 --- a/sites/partners/__tests__/pages/application/index.test.tsx +++ b/sites/partners/__tests__/pages/application/index.test.tsx @@ -7,7 +7,9 @@ import { application, listing, user } from "@bloom-housing/shared-helpers/__test import ApplicationsList from "../../../src/pages/application/[id]" import { AlternateContactRelationship, + ApplicationStatusEnum, LanguagesEnum, + ReviewOrderTypeEnum, UnitTypeEnum, YesNoEnum, } from "@bloom-housing/shared-helpers/src/types/backend-swagger" diff --git a/sites/partners/page_content/locale_overrides/general.json b/sites/partners/page_content/locale_overrides/general.json index ed8aa5bec7..67bfafed9c 100644 --- a/sites/partners/page_content/locale_overrides/general.json +++ b/sites/partners/page_content/locale_overrides/general.json @@ -40,6 +40,9 @@ "application.details.applicationStatus.submitted": "Submitted", "application.details.applicationStatus.waitlist": "Wait list", "application.details.applicationStatus.waitlistDeclined": "Wait list - Declined", + "application.details.accessibleUnitWaitlistNumber": "Accessible unit waitlist (AUWL)", + "application.details.conventionalUnitWaitlistNumber": "Conventional unit waitlist (CUWL)", + "application.details.manualLotteryPositionNumber": "Lottery number", "application.details.householdIncome": "Declared household income", "application.details.householdMemberDetails": "Household member details", "application.details.householdSize": "Household size", diff --git a/sites/partners/src/components/applications/ApplicationsColDefs.tsx b/sites/partners/src/components/applications/ApplicationsColDefs.tsx index 513117280f..c75149de01 100644 --- a/sites/partners/src/components/applications/ApplicationsColDefs.tsx +++ b/sites/partners/src/components/applications/ApplicationsColDefs.tsx @@ -6,6 +6,7 @@ import customParseFormat from "dayjs/plugin/customParseFormat" import { Application, IncomePeriodEnum, + ReviewOrderTypeEnum, } from "@bloom-housing/shared-helpers/src/types/backend-swagger" dayjs.extend(customParseFormat) @@ -42,7 +43,8 @@ export function getColDefs( maxHouseholdSize: number, enableFullTimeStudentQuestion?: boolean, disableWorkInRegion?: boolean, - enableApplicationStatus?: boolean + enableApplicationStatus?: boolean, + reviewOrderType?: ReviewOrderTypeEnum ): ColDef[] { const defs: ColDef[] = [ { @@ -99,6 +101,34 @@ export function getColDefs( return t(`application.details.applicationStatus.${data.status}`) }, }, + { + headerName: t("application.details.accessibleUnitWaitlistNumber"), + field: "accessibleUnitWaitlistNumber", + sortable: false, + filter: false, + width: 120, + minWidth: 50, + }, + { + headerName: t("application.details.conventionalUnitWaitlistNumber"), + field: "conventionalUnitWaitlistNumber", + sortable: false, + filter: false, + width: 120, + minWidth: 50, + }, + ...(reviewOrderType === ReviewOrderTypeEnum.lottery + ? [ + { + headerName: t("application.details.manualLotteryPositionNumber"), + field: "manualLotteryPositionNumber", + sortable: false, + filter: false, + width: 120, + minWidth: 50, + }, + ] + : []), ] : []), { diff --git a/sites/partners/src/components/applications/PaperApplicationDetails/sections/DetailsApplicationData.tsx b/sites/partners/src/components/applications/PaperApplicationDetails/sections/DetailsApplicationData.tsx index 620f770d99..8a650335a6 100644 --- a/sites/partners/src/components/applications/PaperApplicationDetails/sections/DetailsApplicationData.tsx +++ b/sites/partners/src/components/applications/PaperApplicationDetails/sections/DetailsApplicationData.tsx @@ -4,8 +4,17 @@ import { FieldValue, Grid } from "@bloom-housing/ui-seeds" import { ApplicationContext } from "../../ApplicationContext" import { convertDataToLocal } from "../../../../lib/helpers" import SectionWithGrid from "../../../shared/SectionWithGrid" +import { ReviewOrderTypeEnum } from "@bloom-housing/shared-helpers/src/types/backend-swagger" -const DetailsApplicationData = () => { +type DetailsApplicationDataProps = { + enableApplicationStatus?: boolean + reviewOrderType?: ReviewOrderTypeEnum +} + +const DetailsApplicationData = ({ + enableApplicationStatus, + reviewOrderType, +}: DetailsApplicationDataProps) => { const application = useContext(ApplicationContext) const applicationDate = useMemo(() => { @@ -67,6 +76,32 @@ const DetailsApplicationData = () => { + {enableApplicationStatus && ( + + {application.accessibleUnitWaitlistNumber != null && ( + + + {application.accessibleUnitWaitlistNumber} + + + )} + {application.conventionalUnitWaitlistNumber != null && ( + + + {application.conventionalUnitWaitlistNumber} + + + )} + {reviewOrderType === ReviewOrderTypeEnum.lottery && + application.manualLotteryPositionNumber != null && ( + + + {application.manualLotteryPositionNumber} + + + )} + + )} ) } diff --git a/sites/partners/src/components/applications/PaperApplicationForm/PaperApplicationForm.tsx b/sites/partners/src/components/applications/PaperApplicationForm/PaperApplicationForm.tsx index c1db763aba..1dac54d944 100644 --- a/sites/partners/src/components/applications/PaperApplicationForm/PaperApplicationForm.tsx +++ b/sites/partners/src/components/applications/PaperApplicationForm/PaperApplicationForm.tsx @@ -243,7 +243,10 @@ const ApplicationForm = ({ listingId, editMode, application }: ApplicationFormPr
- + { +const FormApplicationData = ({ + enableApplicationStatus, + reviewOrderType, +}: FormApplicationDataProps) => { const formMethods = useFormContext() // eslint-disable-next-line @typescript-eslint/unbound-method @@ -25,6 +37,15 @@ const FormApplicationData = ({ enableApplicationStatus }: FormApplicationDataPro const isDateRequired = dateSubmittedValue?.day || dateSubmittedValue?.month || dateSubmittedValue?.year + const applicationStatus: ApplicationStatusEnum = watch("application.status") + + const accessibleUnitWaitlistNumberValue = watch("application.accessibleUnitWaitlistNumber") + const conventionalUnitWaitlistNumberValue = watch("application.conventionalUnitWaitlistNumber") + + const isWaitlistStatus = + applicationStatus === ApplicationStatusEnum.waitlist || + applicationStatus === ApplicationStatusEnum.waitlistDeclined + const applicationStatusOptions = Array.from(Object.values(ApplicationStatusEnum)) return ( @@ -74,19 +95,75 @@ const FormApplicationData = ({ enableApplicationStatus }: FormApplicationDataPro {enableApplicationStatus && ( - - - + + + + {reviewOrderType === ReviewOrderTypeEnum.lottery && ( + + + + )} + + + + {!!accessibleUnitWaitlistNumberValue && !isWaitlistStatus && ( + + + {accessibleUnitWaitlistNumberValue} + + + )} + + + + {!!conventionalUnitWaitlistNumberValue && !isWaitlistStatus && ( + + + {conventionalUnitWaitlistNumberValue} + + + )} + + )} ) diff --git a/sites/partners/src/lib/applications/FormTypes.ts b/sites/partners/src/lib/applications/FormTypes.ts index c3fdfe8aba..138722f2d8 100644 --- a/sites/partners/src/lib/applications/FormTypes.ts +++ b/sites/partners/src/lib/applications/FormTypes.ts @@ -62,6 +62,9 @@ export type ApplicationTypes = { reviewStatus?: ApplicationReviewStatusEnum status?: ApplicationStatusEnum phoneNumber?: string + accessibleUnitWaitlistNumber?: number + conventionalUnitWaitlistNumber?: number + manualLotteryPositionNumber?: number } export type FormTypes = { diff --git a/sites/partners/src/lib/applications/formatApplicationData.ts b/sites/partners/src/lib/applications/formatApplicationData.ts index 52b9658f48..dffef916fc 100644 --- a/sites/partners/src/lib/applications/formatApplicationData.ts +++ b/sites/partners/src/lib/applications/formatApplicationData.ts @@ -220,6 +220,12 @@ export const mapFormToApi = ({ return acc }, {}) + const { + accessibleUnitWaitlistNumber, + conventionalUnitWaitlistNumber, + manualLotteryPositionNumber, + } = data.application + const result = { submissionDate, language, @@ -248,6 +254,15 @@ export const mapFormToApi = ({ applicationsAlternateAddress: alternateAddress, householdMember: householdMembers, householdSize, + accessibleUnitWaitlistNumber: accessibleUnitWaitlistNumber + ? Number(accessibleUnitWaitlistNumber) + : null, + conventionalUnitWaitlistNumber: conventionalUnitWaitlistNumber + ? Number(conventionalUnitWaitlistNumber) + : null, + manualLotteryPositionNumber: manualLotteryPositionNumber + ? Number(manualLotteryPositionNumber) + : null, } return result @@ -334,6 +349,9 @@ export const mapApiToForm = (applicationData: ApplicationUpdate, listing: Listin additionalPhoneNumberType, alternateContact, status, + accessibleUnitWaitlistNumber, + conventionalUnitWaitlistNumber, + manualLotteryPositionNumber, } = applicationData const incomeVouchers = getYesNoValue(applicationData.incomeVouchers) @@ -379,6 +397,9 @@ export const mapApiToForm = (applicationData: ApplicationUpdate, listing: Listin alternateContact, programs, status, + accessibleUnitWaitlistNumber, + conventionalUnitWaitlistNumber, + manualLotteryPositionNumber, } return result diff --git a/sites/partners/src/pages/application/[id]/index.tsx b/sites/partners/src/pages/application/[id]/index.tsx index 1963006925..b0ee0bddd2 100644 --- a/sites/partners/src/pages/application/[id]/index.tsx +++ b/sites/partners/src/pages/application/[id]/index.tsx @@ -50,6 +50,11 @@ const ApplicationsList = () => { listingDto?.jurisdictions.id ) + const enableApplicationStatus = doJurisdictionsHaveFeatureFlagOn( + FeatureFlagEnum.enableApplicationStatus, + listingDto?.jurisdictions.id + ) + const swapCommunityTypeWithPrograms = doJurisdictionsHaveFeatureFlagOn( FeatureFlagEnum.swapCommunityTypeWithPrograms, listingDto?.jurisdictions.id @@ -123,7 +128,10 @@ const ApplicationsList = () => {
- + { maxHouseholdSize, enableFullTimeStudentQuestion, disableWorkInRegion, - enableApplicationStatus + enableApplicationStatus, + listingDto?.reviewOrderType ) }, [ maxHouseholdSize, enableFullTimeStudentQuestion, disableWorkInRegion, enableApplicationStatus, + listingDto?.reviewOrderType, ]) const gridComponents = { diff --git a/sites/partners/styles/overrides.scss b/sites/partners/styles/overrides.scss index a943a1d73b..e1ab051524 100644 --- a/sites/partners/styles/overrides.scss +++ b/sites/partners/styles/overrides.scss @@ -209,3 +209,18 @@ .darker-help-text { --field-value-help-text-color: var(--seeds-input-text-label-color); } + +.field-value-field-style { + [data-part="label"] { + font-family: var(--seeds-font-sans); + margin-bottom: 0; + padding-bottom: var(--seeds-s2); + padding-top: var(--seeds-s0_5); + } + + [data-part="value"] { + margin-top: 0; + padding-top: calc(0.75rem + 1px); + padding-left: calc(0.75rem + 1px); + } +}