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

Allow frontend filtering by neighborhood #222

Merged
merged 78 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c723612
1320/additional eligibility, listings management (#1374)
emilyjablonski Jun 21, 2021
e49c46b
1349/leasing agent section, listings management (#1376)
emilyjablonski Jun 21, 2021
04417a3
Issue 1328/move property to the listing model (#1361)
pbn4 Jun 21, 2021
f4488a3
Align dev with master (#1399)
pbn4 Jun 23, 2021
b787c0b
1351 Preview (#1359)
seanmalbert Jun 24, 2021
61e898b
1318/additional fees, listings management (#1377)
emilyjablonski Jun 24, 2021
e05c8e0
Fix units availability display (#1398)
software-project Jun 24, 2021
eacdd10
1388/date component update take 2 (#1392)
emilyjablonski Jun 25, 2021
48d060d
Adds uuid extension step to e2e tests, and update to .env.template (#…
avaleske Jun 25, 2021
1ebc130
Add reserved_community_type seed migration (#1411)
pbn4 Jun 25, 2021
1450488
1177/add image to listing (#1413)
pbn4 Jun 25, 2021
1c52a63
1408/submission due date (#1409)
pbn4 Jun 28, 2021
9cb31b2
1418/cache and cleanup (#1422)
seanmalbert Jun 28, 2021
377a2e4
Add assets endpoints for list and retrieve by id (#1412)
pbn4 Jun 28, 2021
4f926eb
1317/listings management, building details & intro (#1420)
emilyjablonski Jun 28, 2021
1dc6fca
1319/listings management, building features (#1421)
emilyjablonski Jun 28, 2021
97d0d25
1178 add result and waitlist related fields to Listing (#1434)
pbn4 Jun 29, 2021
a30fb13
1383/listings management, ranking and results (#1433)
emilyjablonski Jul 1, 2021
37197bd
1350 / Units (#1448)
seanmalbert Jul 2, 2021
32b916c
1381/listings management, application addresses (#1425)
emilyjablonski Jul 2, 2021
b00cf44
1st attempt at frontend listing pagination
abbiefarr Jul 2, 2021
74196bf
1382/listings management, application dates (#1432)
emilyjablonski Jul 2, 2021
55b3097
set fallback to true for getStaticPaths so new paths can be added (#1…
seanmalbert Jul 2, 2021
d567071
Dev - adds cache revalidation to frontend app (#1462)
seanmalbert Jul 2, 2021
0b84134
removes listing controller update (#1464)
seanmalbert Jul 2, 2021
13fbea8
Application method/paperpickup (#1469)
seanmalbert Jul 2, 2021
34639e0
Paginate public listings page
abbiefarr Jul 3, 2021
7f7dd7a
Merge branch 'main' into afarr-listing-pagination
abbiefarr Jul 4, 2021
cf214be
removes preview logic from ListingView (#1476)
seanmalbert Jul 6, 2021
f95fbca
1153 Dropzone-style file upload component (#1437)
jaredcwhite Jul 6, 2021
e354904
1331/hide eligibility header if no sections present (#1457)
emilyjablonski Jul 7, 2021
3e7e625
Add Github action for running Prettier on PRs (#1440)
willrlin Jul 7, 2021
e00edcd
Fix code style issues with Prettier
lint-action Jul 7, 2021
2bae4bb
Entries for unreleased and adds 1.0.4
seanmalbert Jul 7, 2021
efe2f74
Fix code style issues with Prettier
lint-action Jul 7, 2021
25e86f7
initial style fixes
avaleske Jul 7, 2021
bab97cb
initial request for filtered state
avaleske Jul 8, 2021
3b2e6fa
1444/optional fields (#1470)
pbn4 Jul 8, 2021
b93ccf2
Fix code style issues with Prettier
lint-action Jul 8, 2021
14f3951
remove prop type
avaleske Jul 8, 2021
f5bf42a
1454/listings management visual QA round (#1463)
emilyjablonski Jul 9, 2021
6ee60d9
Refactor/user module 2 (#1474)
pbn4 Jul 9, 2021
f90479b
1404/add action block (#1459)
software-project Jul 12, 2021
34cd0ce
Connect ag-grid sort with the API (#1492)
dominikx96 Jul 13, 2021
b2d1742
Add commands to run Cypress tests in "headless" mode (#1505)
anders-schneider Jul 14, 2021
996cfbc
1503/fix out of sync swagger (#1504)
pbn4 Jul 14, 2021
cb3508f
Merge branch 'main' into feature/avaleske-request-filtered-results
abbiefarr Jul 14, 2021
8acafcf
Add storybook a11y testing #142 (#1450)
akegan Jul 14, 2021
476b863
1480/ Fix double submit (#1508)
seanmalbert Jul 14, 2021
de5b8fe
Fix code style issues with Prettier
lint-action Jul 14, 2021
36df264
Remove unused inverse relations from entities (#1520)
pbn4 Jul 15, 2021
912bbe4
just playing
abbiefarr Jul 15, 2021
946c679
Fixes bug with listing form (#1521)
seanmalbert Jul 15, 2021
21bc55f
Merge branch 'main' into feature/avaleske-request-filtered-results
abbiefarr Jul 15, 2021
d7fa329
Final touches on filtering ui MVP
abbiefarr Jul 15, 2021
7fa688e
1184/unit type rent (#1439)
pbn4 Jul 16, 2021
ca08d32
Adds additional checks for unit type and priority (#1525)
seanmalbert Jul 16, 2021
dcbecca
Add preview (disabled) state for Listings Application button (#1502)
jaredcwhite Jul 16, 2021
b650a05
Update jest-backend ci/cd job environment variables sourced through .…
pbn4 Jul 19, 2021
bf16cfb
Merge branch 'main' into feature/avaleske-request-filtered-results
abbiefarr Jul 19, 2021
ef05c8b
1348/Add photo upload to the Listing form (#1491)
jaredcwhite Jul 19, 2021
0f5cf39
1352/Add flagged and mark as duplicate to CSV export (#1500)
software-project Jul 19, 2021
509bf8e
Listings close & unpublish (#1498)
dominikx96 Jul 19, 2021
925d583
Incorporate modal
abbiefarr Jul 19, 2021
6bfa92e
Merge branch 'main' into feature/avaleske-request-filtered-results
abbiefarr Jul 19, 2021
804d43b
Convert listing address jsonb columns to separate address tables (#1512)
pbn4 Jul 20, 2021
a124754
Recreated foreign keys constraints (#1514)
pbn4 Jul 20, 2021
352891d
Add debug flags and instructions for debugging frontends (#1519)
avaleske Jul 20, 2021
7ebc906
1445/move listing events to table (#1515)
pbn4 Jul 20, 2021
a7ca7a1
Fix code style issues with Prettier
lint-action Jul 20, 2021
bb6c7b6
Merge branch 'dev' of github.com:bloom-housing/bloom into afarr/pull-…
abbiefarr Jul 21, 2021
d260c31
re-add lint config
abbiefarr Jul 21, 2021
f4834ea
Merge branch 'afarr/pull-upstream-dev'
abbiefarr Jul 22, 2021
0e3dbd6
Merge branch 'main' of github.com:CityOfDetroit/bloom
abbiefarr Jul 22, 2021
39ea3e3
Merge branch 'main' into request-filtered-results
abbiefarr Jul 22, 2021
a968d4b
address review comments
abbiefarr Jul 22, 2021
846642c
Merge branch 'feature/avaleske-request-filtered-results' of github.co…
abbiefarr Jul 22, 2021
5479afb
Merge branch 'main' into request-filtered-results
abbiefarr Jul 22, 2021
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
41 changes: 27 additions & 14 deletions sites/public/lib/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useContext, useEffect, useRef } from "react"
import { useContext, useEffect } from "react"
import { useRouter } from "next/router"
import axios from "axios"
import useSWR from "swr"
import { isInternalLink, AuthContext } from "@bloom-housing/ui-components"
import { isInternalLink } from "@bloom-housing/ui-components"
import { AppSubmissionContext } from "./AppSubmissionContext"
import { ParsedUrlQuery } from "querystring"
import { ListingsService } from "@bloom-housing/backend-core/types"

export const useRedirectToPrevPage = (defaultPath = "/") => {
const router = useRouter()
Expand Down Expand Up @@ -33,22 +33,35 @@ export const useFormConductor = (stepName: string) => {
return context
}

const listingsFetcher = function (listingsService: ListingsService) {
return (_url: string, page: number, limit: number) => {
const params = {
page,
limit,
}
return listingsService?.list(params)
// TODO: consolidate filter definitions (#253)
export interface FilterOptions {
preferredUnit?: string
accessibility?: string
community?: string
neighborhood?: string
}

function filterStringFromFilters(filters: FilterOptions) {
if (!filters || filters.neighborhood == "") return ""

// Only `neighborhood` filter is currently supported.
return `&filter[$comparison]==&filter[neighborhood]=${filters.neighborhood}`
}

const listingsFetcher = function () {
return async (url: string, page: number, limit: number, filters: FilterOptions) => {
const res = await axios.get(
`${url}?page=${page}&limit=${limit}${filterStringFromFilters(filters)}`
)
return res.data
}
}

// TODO: move this so it can be shared with the partner site.
export function useListingsData(pageIndex: number, limit = 10) {
const { listingsService } = useContext(AuthContext)
export function useListingsData(pageIndex: number, limit = 10, filters: FilterOptions) {
const { data, error } = useSWR(
[`${process.env.listingServiceUrl}`, pageIndex, limit],
listingsFetcher(listingsService)
[`${process.env.listingServiceUrl}`, pageIndex, limit, filters],
listingsFetcher()
)

return {
Expand Down
136 changes: 61 additions & 75 deletions sites/public/pages/listings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,81 @@ import Head from "next/head"
import {
ListingsList,
PageHeader,
AgPagination,
Button,
AppearanceSizeType,
Modal,
Drawer,
AppearanceStyleType,
AppearanceBorderType,
t,
Select,
AgPagination,
Form,
SelectOption,
} from "@bloom-housing/ui-components"
import { useForm } from "react-hook-form"
import Layout from "../layouts/application"
import { MetaTags } from "../src/MetaTags"
import React, { useEffect, useState } from "react"
import { useRouter } from "next/router"
import { useListingsData } from "../lib/hooks"
import { FilterOptions, useListingsData } from "../lib/hooks"

const ListingsPage = () => {
const router = useRouter()

/* Pagination state */
// Pagination state
const [currentPage, setCurrentPage] = useState<number>(1)
const [filterState, setFilterState] = useState<FilterOptions>(null)
const itemsPerPage = 10

function setPage(page: number) {
if (page != currentPage) {
// Filter state
const [filterModalVisible, setFilterModalVisible] = useState<boolean>(false)

// TODO: Select options should come from the database (#252)
const preferredUnitOptions = ["", "1", "2", "3", "4", "studio"]
const accessibilityOptions = ["", "n", "y"]
const communityOptions = ["", "general", "senior", "assisted"]
const neighborhoodOptions: SelectOption[] = [
{ value: "", label: "" },
{ value: "Foster City", label: "Foster City" },
]

function setPageAndFilterState(page: number, filters = filterState) {
if (page != currentPage || filters != filterState) {
setCurrentPage(page)
setFilterState(filters)
// TODO(abbiefarr): update the url with filter data (#240)
void router.push(
{
pathname: "/listings",
query: { page: page },
query: {
page: page,
},
},
undefined,
{ shallow: true }
)
setCurrentPage(page)
}
}

// Checks if the url is updated manually.
// Checks for changes in url params.
useEffect(() => {
if (router.query.page && Number(router.query.page) != currentPage) {
setCurrentPage(Number(router.query.page))
}
}, [currentPage, router.query.page])
// TODO(abbiefarr): update filter params if the url is manually updated (#240)
}, [router.query])

const { listingsData, listingsLoading } = useListingsData(currentPage, itemsPerPage)
const { listingsData, listingsLoading } = useListingsData(currentPage, itemsPerPage, filterState)

const pageTitle = `${t("pageTitle.rent")} - ${t("nav.siteTitle")}`
const metaDescription = t("pageDescription.welcome", { regionName: t("region.name") })
const metaImage = "" // TODO: replace with hero image
const [filterModalVisible, setFilterModalVisible] = useState<boolean>(false)
const [filterDrawerVisible, setFilterDrawerVisible] = useState<boolean>(false)

const preferredUnitOptions = ["1", "2", "3", "4", "studio"]
const accessibilityOptions = ["n", "y"]
const communityOptions = ["general", "senior", "assisted"]
/* Form Handler */
// eslint-disable-next-line @typescript-eslint/unbound-method
const { handleSubmit, register } = useForm()
const onSubmit = () => {
// Not yet implemented.
const onSubmit = (data: FilterOptions) => {
setFilterModalVisible(false)
setPageAndFilterState(/*page=*/ 1, data)
}

return (
Expand All @@ -76,92 +89,67 @@ const ListingsPage = () => {
<Modal
open={filterModalVisible}
title={t("listingFilters.modalTitle")}
actions={[
<Button
onClick={() => setFilterModalVisible(false)}
styleType={AppearanceStyleType.primary}
>
Apply
</Button>,
<Button
onClick={() => setFilterModalVisible(false)}
styleType={AppearanceStyleType.secondary}
border={AppearanceBorderType.borderless}
>
Close
</Button>,
]}
actions={[]}
hideCloseIcon
>
<Form onSubmit={handleSubmit(onSubmit)}>
<div className="form-card__group">
<p className="field-note mb-4">{t("listingFilters.modalHeader")}</p>
<Select
id="filter.unitOptions"
name="filter.unitOptions"
id="unitOptions"
name="preferredUnit"
label={t("listingFilters.unitOptions.label")}
validation={{ required: true }}
register={register}
controlClassName="control"
options={preferredUnitOptions}
keyPrefix="listingFilters.unitOptions.unitOptionsTypes"
defaultValue={filterState?.preferredUnit}
/>
<Select
id="filter.accessibilityOptions"
name="filter.accessibilityOptions"
id="accessibilityOptions"
name="accessibility"
label={t("listingFilters.accessibilityOptions.label")}
validation={{ required: true }}
register={register}
controlClassName="control"
options={accessibilityOptions}
keyPrefix="listingFilters.accessibilityOptions.accessibilityOptionsTypes"
defaultValue={filterState?.accessibility}
/>
<Select
id="filter.communityOptions"
name="filter.communityOptions"
id="communityOptions"
name="community"
label={t("listingFilters.communityOptions.label")}
validation={{ required: true }}
register={register}
controlClassName="control"
options={communityOptions}
keyPrefix="listingFilters.communityOptions.communityOptionsTypes"
defaultValue={filterState?.community}
/>
<Select
id="neighborhoodOptions"
name="neighborhood"
label={t("listingFilters.neighborhoodOptions.label")}
register={register}
controlClassName="control"
options={neighborhoodOptions}
defaultValue={filterState?.neighborhood}
/>
</div>
<div className="text-center mt-6">
<Button styleType={AppearanceStyleType.primary}>Apply Filters</Button>
</div>
<div className="text-center mt-6">
<a href="#" onClick={() => setFilterModalVisible(false)}>
{t("t.cancel")}
</a>
</div>
</Form>
</Modal>
<Drawer
open={filterDrawerVisible}
title="Drawer Title"
onClose={() => setFilterDrawerVisible(false)}
actions={[
<Button
key={0}
onClick={() => setFilterDrawerVisible(false)}
styleType={AppearanceStyleType.primary}
>
Submit
</Button>,
<Button
key={1}
onClick={() => setFilterDrawerVisible(false)}
styleType={AppearanceStyleType.secondary}
border={AppearanceBorderType.borderless}
>
Cancel
</Button>,
]}
>
<p>Placeholder for future text</p>
</Drawer>
<div className="max-w-3xl m-auto">
<Button size={AppearanceSizeType.small} onClick={() => setFilterModalVisible(true)}>
{/* TODO:avaleske make this a string */}
Filter listings
</Button>
<Button size={AppearanceSizeType.small} onClick={() => setFilterDrawerVisible(true)}>
{/* TODO:avaleske make this a string */}
Filter listings (drawer)
</Button>
</div>
{!listingsLoading && (
<div>
Expand All @@ -171,14 +159,12 @@ const ListingsPage = () => {
totalPages={listingsData?.meta.totalPages}
currentPage={currentPage}
itemsPerPage={itemsPerPage}
sticky={true}
quantityLabel={t("listings.totalListings")}
setCurrentPage={setPage}
quantityLabel={t("applications.totalApplications")}
setCurrentPage={setPageAndFilterState}
/>
</div>
)}
</Layout>
)
}

export default ListingsPage
3 changes: 3 additions & 0 deletions ui-components/src/locales/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,9 @@
"senior": "Senior",
"assisted": "Assisted"
}
},
"neighborhoodOptions":{
"label": "Neighborhood:"
}
},
"eligibility": {
Expand Down