Skip to content

Commit f6db93a

Browse files
authored
1324 Add category filters to Advanced Search component (#1345)
* 1324 Desktop and mobile styling of collapsed state of advanced search component * 1324 Implement mobile styles and search functionality * Prettier * 1324 Add category filters to Advanced Search component * 1324 Add category refinements * 1324 Add eligibility filter dropdowns to Advanced Search * 1324 PR cleaenup and prettier * 1324 PR feedback * 1324 remove test static parent eligibility. oops
1 parent 639d31a commit f6db93a

10 files changed

+362
-31
lines changed

app/assets/img/ic-filter-white.svg

+3
Loading

app/components/ui/inline/Checkbox/Checkbox.module.scss

+8
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,11 @@
5858
box-shadow: initial;
5959
}
6060
}
61+
62+
.label {
63+
cursor: pointer;
64+
padding-left: 12px;
65+
font-weight: 600;
66+
font-size: 16px;
67+
color: $color-grey8;
68+
}

app/components/ui/inline/Checkbox/Checkbox.tsx

+18-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type CheckboxProps = {
99
checked?: boolean;
1010
addClass?: string;
1111
id?: string;
12+
label?: string;
1213
};
1314

1415
export const Checkbox = ({
@@ -18,14 +19,22 @@ export const Checkbox = ({
1819
checked,
1920
addClass,
2021
id,
22+
label,
2123
}: CheckboxProps) => (
22-
<input
23-
name={name}
24-
onChange={onChange}
25-
value={value}
26-
checked={checked}
27-
className={`${styles.inputDefaults} ${addClass || ""}`}
28-
id={id}
29-
type="checkbox"
30-
/>
24+
<>
25+
<input
26+
name={name}
27+
onChange={onChange}
28+
value={value}
29+
checked={checked}
30+
className={`${styles.inputDefaults} ${addClass || ""}`}
31+
id={id}
32+
type="checkbox"
33+
/>
34+
{label && (
35+
<label className={styles.label} htmlFor={id}>
36+
{label}
37+
</label>
38+
)}
39+
</>
3140
);

app/pages/HomePage/HomePage.tsx

+24-4
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,75 @@ import { whiteLabel } from "../../utils";
1212

1313
const { showBreakingNews } = whiteLabel;
1414

15-
const covidResources = [
16-
{ name: "Food", icon: "food", categorySlug: "food-resources" },
15+
export const coreCategories = [
1716
{
17+
algoliaCategoryName: "Covid-food",
18+
name: "Food",
19+
icon: "food",
20+
categorySlug: "food-resources",
21+
},
22+
{
23+
algoliaCategoryName: "Covid-health",
1824
name: "Health and COVID-19",
1925
icon: "hospital",
2026
categorySlug: "medical-services-resources",
2127
},
2228
{
29+
algoliaCategoryName: "Covid-hygiene",
2330
name: "Showers, Hygiene and other Services",
2431
icon: "shower",
2532
categorySlug: "hygiene-resources",
2633
},
27-
{ name: "Shelters", icon: "bed", categorySlug: "shelter-resources" },
2834
{
35+
algoliaCategoryName: "Covid-shelter",
36+
name: "Shelters",
37+
icon: "bed",
38+
categorySlug: "shelter-resources",
39+
},
40+
{
41+
algoliaCategoryName: "Covid-longtermhousing",
2942
name: "Long-term Housing",
3043
icon: "longterm-housing",
3144
categorySlug: "longterm-housing-resources",
3245
},
3346
{
47+
algoliaCategoryName: "Covid-housing",
3448
name: "Rental Assistance and Eviction Prevention",
3549
icon: "housing-heart",
3650
categorySlug: "rental-assistance-resources",
3751
},
3852
{
53+
algoliaCategoryName: "Covid-finance",
3954
name: "Financial Assistance",
4055
icon: "wallet",
4156
categorySlug: "financial-resources",
4257
},
4358
{
59+
algoliaCategoryName: "Covid-jobs",
4460
name: "Jobs",
4561
icon: "employment",
4662
categorySlug: "job-assistance-resources",
4763
},
4864
{
65+
algoliaCategoryName: "Covid-internet",
4966
name: "Internet, Devices & Technology Training",
5067
icon: "devices",
5168
categorySlug: "internet-access-resources",
5269
},
5370
{
71+
algoliaCategoryName: "Covid-lgbtqa",
5472
name: "LGBTQ+ Resources",
5573
icon: "community",
5674
categorySlug: "lgbtq-resources",
5775
},
5876
{
77+
algoliaCategoryName: "Covid-domesticviolence",
5978
name: "Resources for Domestic Violence Survivors",
6079
icon: "warning",
6180
categorySlug: "domestic-violence-resources",
6281
},
6382
{
83+
algoliaCategoryName: "Covid-substanceuse",
6484
name: "Substance Use Resources",
6585
icon: "substance-use",
6686
categorySlug: "substance-use-resources",
@@ -87,7 +107,7 @@ export const HomePage = () => {
87107
<>
88108
{showBreakingNews && <NewsArticles />}
89109
<HomePageSection title="Find essential services in San Francisco">
90-
<ResourceList resources={covidResources} />
110+
<ResourceList resources={coreCategories} />
91111
</HomePageSection>
92112
<HomePageSection
93113
title="Browse Directory"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@import "~styles/utils/_helpers.scss";
2+
3+
.categoryFilters {
4+
margin: 30px 0 55px;
5+
}
6+
7+
.categoryTypeHeader {
8+
color: $color-grey5;
9+
font-weight: 600;
10+
margin-bottom: 23px;
11+
}
12+
13+
.categoryCheckboxList {
14+
display: grid;
15+
grid-template-columns: repeat(4, 1fr);
16+
row-gap: 15px;
17+
column-gap: 30px;
18+
19+
@media screen and (max-width: $break-tablet-l) {
20+
grid-template-columns: repeat(2, 1fr);
21+
}
22+
23+
@media screen and (max-width: $break-tablet-s) {
24+
grid-template-columns: repeat(1, 1fr);
25+
}
26+
}
27+
28+
.checkboxItem {
29+
display: grid;
30+
grid-template-columns: auto 1fr;
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from "react";
2+
import { Checkbox } from "components/ui/inline/Checkbox/Checkbox";
3+
import { coreCategories } from "pages/HomePage";
4+
import styles from "./CategoryFilters.module.scss";
5+
6+
export interface SelectedCategories {
7+
[key: string]: boolean;
8+
}
9+
10+
export const CategoryFilters = ({
11+
selectedCategories,
12+
setSelectedCategories,
13+
}: {
14+
selectedCategories: SelectedCategories;
15+
setSelectedCategories: (updatedCategories: SelectedCategories) => void;
16+
}) => {
17+
const handleCategoryClick = (categoryName: string) => {
18+
const newValue = !selectedCategories[categoryName];
19+
const updatedCategories = { ...selectedCategories };
20+
21+
setSelectedCategories({
22+
...updatedCategories,
23+
[categoryName]: newValue,
24+
});
25+
};
26+
27+
return (
28+
<div className={styles.categoryFilters}>
29+
<p className={styles.categoryTypeHeader}>Service Type</p>
30+
<ul className={styles.categoryCheckboxList}>
31+
{coreCategories.map((c) => (
32+
<li key={c.algoliaCategoryName} className={styles.checkboxItem}>
33+
<Checkbox
34+
name={c.name}
35+
id={c.name}
36+
checked={selectedCategories[c.algoliaCategoryName]}
37+
onChange={() => handleCategoryClick(c.algoliaCategoryName)}
38+
label={c.name}
39+
/>
40+
</li>
41+
))}
42+
</ul>
43+
</div>
44+
);
45+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@import "~styles/utils/_helpers.scss";
2+
3+
.eligibilityFilters {
4+
display: grid;
5+
grid-template-columns: repeat(2, 1fr);
6+
column-gap: 40px;
7+
row-gap: 14px;
8+
@media screen and (max-width: $break-tablet-s) {
9+
grid-template-columns: repeat(1, 1fr);
10+
}
11+
}
12+
13+
.eligibilitySelectLabel {
14+
color: $color-grey5;
15+
font-weight: 600;
16+
margin-bottom: 5px;
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from "react";
2+
import Select from "react-select";
3+
4+
import styles from "./EligibilityFilters.module.scss";
5+
6+
interface SelectOption {
7+
label: string;
8+
value: number;
9+
}
10+
11+
export type SelectOptions = SelectOption[];
12+
13+
export const EligibilityFilters = ({
14+
optionsGroupArray,
15+
selectedEligibilities,
16+
setSelectedEligibilities,
17+
parentEligibilities,
18+
}: {
19+
optionsGroupArray: SelectOptions[];
20+
selectedEligibilities: SelectOptions[];
21+
setSelectedEligibilities: (eligibilities: SelectOptions[]) => void;
22+
parentEligibilities: { id: number; name: string }[];
23+
}) => {
24+
return (
25+
<div className={styles.eligibilityFilters}>
26+
{optionsGroupArray.map((filters, index) => (
27+
<div key={parentEligibilities[index].id}>
28+
<label>
29+
<p className={styles.eligibilitySelectLabel}>
30+
{parentEligibilities[index].name}
31+
</p>
32+
<Select
33+
id={`eligibilityDropdown-${index}`}
34+
name={`${parentEligibilities[index].name}`}
35+
options={filters}
36+
value={selectedEligibilities[index]}
37+
multi
38+
searchable={false}
39+
onChange={(newValues) => {
40+
const newEligibilities = selectedEligibilities.map((el, i) => {
41+
if (i === index) {
42+
return newValues as SelectOptions;
43+
}
44+
return el;
45+
});
46+
setSelectedEligibilities(newEligibilities);
47+
}}
48+
/>
49+
</label>
50+
</div>
51+
))}
52+
</div>
53+
);
54+
};

app/pages/NavigatorDashboard/NavigatorDashboard.module.scss

+39-5
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
width: 100%;
1515
padding: 15px;
1616
box-shadow: none;
17-
border-left: none;
18-
border-right: none;
19-
border-radius: 0;
17+
border: none;
2018
}
2119
}
2220

@@ -32,19 +30,24 @@
3230
.searchBoxForm {
3331
background: #f5f5f5;
3432
border-radius: 8px;
33+
padding: 14px 26px;
34+
@media screen and (max-width: $break-tablet-p) {
35+
padding: 14px 15px;
36+
}
37+
}
38+
39+
.searchInputContainer {
3540
display: grid;
3641
grid-template-areas: "input button filter";
3742
grid-template-columns: 66fr 18fr 50px;
3843
gap: 35px;
39-
padding: 14px 26px;
4044
@media screen and (max-width: $break-tablet-p) {
4145
grid-template-areas:
4246
"input filter"
4347
"button button";
4448
grid-template-columns: repeat(1, 1fr);
4549
row-gap: 7px;
4650
column-gap: 4px;
47-
padding: 14px 15px;
4851
}
4952
}
5053

@@ -64,13 +67,19 @@
6467
}
6568
}
6669

70+
.submitButton,
6771
.searchButton {
6872
height: 50px;
6973
max-width: 200px;
7074
grid-area: button;
7175
@media screen and (max-width: $break-tablet-p) {
7276
max-width: none;
7377
}
78+
&.disabled {
79+
background: $color-brand-light;
80+
pointer-events: none;
81+
cursor: default;
82+
}
7483
}
7584

7685
.searchFilterButton {
@@ -81,9 +90,34 @@
8190
padding: 0;
8291
background-color: #fff;
8392
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
93+
&.expandedOptions {
94+
background-color: $color-brand;
95+
}
8496
&:active {
8597
box-shadow: none;
8698
}
8799
}
88100

101+
.submitButtonRow {
102+
display: grid;
103+
justify-items: end;
104+
margin-top: 14px;
105+
@media screen and (max-width: $break-tablet-s) {
106+
display: block;
107+
margin-top: 20px;
108+
}
109+
}
110+
111+
.submitButton {
112+
width: 200px;
113+
margin-bottom: 12px;
114+
@media screen and (max-width: $break-tablet-p) {
115+
width: 125px;
116+
}
117+
@media screen and (max-width: $break-tablet-s) {
118+
width: 100%;
119+
max-width: none;
120+
}
121+
}
122+
89123
// End Advanced Search Box Styles

0 commit comments

Comments
 (0)