Skip to content

Commit a4bb184

Browse files
committed
Add filter: religion
1 parent 940c1f5 commit a4bb184

File tree

11 files changed

+146
-18
lines changed

11 files changed

+146
-18
lines changed

backend/api/src/get-profiles.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type profileQueryType = {
2222
pref_romantic_styles?: String[] | undefined,
2323
diet?: String[] | undefined,
2424
political_beliefs?: String[] | undefined,
25+
religion?: String[] | undefined,
2526
wants_kids_strength?: number | undefined,
2627
has_kids?: number | undefined,
2728
is_smoker?: boolean | undefined,
@@ -57,6 +58,7 @@ export const loadProfiles = async (props: profileQueryType) => {
5758
pref_romantic_styles,
5859
diet,
5960
political_beliefs,
61+
religion,
6062
wants_kids_strength,
6163
has_kids,
6264
is_smoker,
@@ -102,6 +104,8 @@ export const loadProfiles = async (props: profileQueryType) => {
102104
intersection(diet, l.diet).length) &&
103105
(!political_beliefs ||
104106
intersection(political_beliefs, l.political_beliefs).length) &&
107+
(!religion ||
108+
intersection(religion, l.religion).length) &&
105109
(!wants_kids_strength ||
106110
wants_kids_strength == -1 ||
107111
!l.wants_kids_strength ||
@@ -199,6 +203,12 @@ export const loadProfiles = async (props: profileQueryType) => {
199203
{political_beliefs}
200204
),
201205

206+
religion?.length &&
207+
where(
208+
`religion IS NULL OR religion = '{}' OR religion && $(religion)`,
209+
{religion}
210+
),
211+
202212
!!wants_kids_strength &&
203213
wants_kids_strength !== -1 &&
204214
where(

common/src/api/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ export const API = (_apiTypeCheck = {
402402
pref_age_max: z.coerce.number().optional(),
403403
drinks_min: z.coerce.number().optional(),
404404
drinks_max: z.coerce.number().optional(),
405+
religion: arraybeSchema.optional(),
405406
pref_relation_styles: arraybeSchema.optional(),
406407
pref_romantic_styles: arraybeSchema.optional(),
407408
diet: arraybeSchema.optional(),

common/src/api/zod-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const optionalProfilesSchema = z.object({
7777
political_beliefs: z.array(z.string()).optional(),
7878
religious_belief_strength: z.number().optional(),
7979
religious_beliefs: z.string().optional(),
80+
religion: z.array(z.string()).optional(),
8081
ethnicity: z.array(z.string()).optional(),
8182
born_in_location: z.string().optional(),
8283
height_in_inches: z.number().optional(),

common/src/filters.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type FilterFields = {
3232
| 'pref_gender'
3333
| 'pref_age_min'
3434
| 'pref_age_max'
35+
| 'religion'
3536
>
3637

3738
export const orderProfiles = (
@@ -70,6 +71,7 @@ export const initialFilters: Partial<FilterFields> = {
7071
pref_romantic_styles: undefined,
7172
diet: undefined,
7273
political_beliefs: undefined,
74+
religion: undefined,
7375
pref_gender: undefined,
7476
shortBio: undefined,
7577
drinks_min: undefined,

common/src/searches.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const filterLabels: Record<string, string> = {
1717
wants_kids_strength: "Kids",
1818
is_smoker: "",
1919
pref_relation_styles: "Seeking",
20+
religion: "",
2021
pref_gender: "",
2122
orderBy: "",
2223
diet: "Diet",

common/src/util/sorting.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {MAX_INT} from "common/constants";
2+
3+
export function getSortedOptions(options: string[], order: string[] | Record<string, string>) {
4+
let parsedOrder: string[]
5+
if (Array.isArray(order)) {
6+
parsedOrder = order
7+
} else {
8+
parsedOrder = Object.keys(order)
9+
}
10+
return options
11+
.slice()
12+
.sort((a, b) => {
13+
const ia = parsedOrder.indexOf(a as any)
14+
const ib = parsedOrder.indexOf(b as any)
15+
const sa = ia === -1 ? MAX_INT : ia
16+
const sb = ib === -1 ? MAX_INT : ib
17+
if (sa !== sb) return sa - sb
18+
return String(a).localeCompare(String(b))
19+
});
20+
}

web/components/filters/desktop-filters.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/polit
2626
import {GiFruitBowl} from "react-icons/gi";
2727
import {RiScales3Line} from "react-icons/ri";
2828
import {EducationFilter, EducationFilterText} from "web/components/filters/education-filter";
29-
import {LuGraduationCap} from "react-icons/lu";
29+
import {LuCigarette, LuGraduationCap} from "react-icons/lu";
3030
import {DrinksFilter, DrinksFilterText} from "web/components/filters/drinks-filter";
3131
import {MdLocalBar} from 'react-icons/md'
32-
import {SmokerFilter, SmokerFilterText} from 'web/components/filters/smoker-filter'
33-
import {LuCigarette} from 'react-icons/lu'
32+
import {SmokerFilter, SmokerFilterText} from "web/components/filters/smoker-filter"
33+
import {ReligionFilter, ReligionFilterText} from "web/components/filters/religion-filter";
34+
import {PiHandsPrayingBold} from "react-icons/pi";
3435

3536
export function DesktopFilters(props: {
3637
filters: Partial<FilterFields>
@@ -381,6 +382,33 @@ export function DesktopFilters(props: {
381382
menuWidth="w-50"
382383
/>
383384

385+
{/* RELIGION */}
386+
<CustomizeableDropdown
387+
buttonContent={(open) => (
388+
<DropdownButton
389+
open={open}
390+
content={
391+
<Row className="items-center gap-1">
392+
<PiHandsPrayingBold className="h-4 w-4"/>
393+
<ReligionFilterText
394+
options={
395+
filters.religion as
396+
| string[]
397+
| undefined
398+
}
399+
highlightedClass={open ? 'text-primary-500' : undefined}
400+
/>
401+
</Row>
402+
}
403+
/>
404+
)}
405+
dropdownMenuContent={
406+
<ReligionFilter filters={filters} updateFilter={updateFilter}/>
407+
}
408+
popoverClassName="bg-canvas-50"
409+
menuWidth="w-50"
410+
/>
411+
384412
{/* SMOKER */}
385413
<CustomizeableDropdown
386414
buttonContent={(open) => (
@@ -399,7 +427,7 @@ export function DesktopFilters(props: {
399427
)}
400428
dropdownMenuContent={
401429
<Col className="mx-2 mb-4">
402-
<SmokerFilter filters={filters} updateFilter={updateFilter} />
430+
<SmokerFilter filters={filters} updateFilter={updateFilter}/>
403431
</Col>
404432
}
405433
popoverClassName="bg-canvas-50"

web/components/filters/education-filter.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {FilterFields} from "common/filters";
55
import {EDUCATION_CHOICES} from "web/components/filters/choices";
66
import {convertEducationTypes} from "web/lib/util/convert-types";
77
import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text";
8-
import {MAX_INT} from "common/constants";
8+
import {getSortedOptions} from "common/util/sorting";
99

1010
export function EducationFilterText(props: {
1111
options: string[] | undefined
@@ -20,20 +20,9 @@ export function EducationFilterText(props: {
2020
)
2121
}
2222

23-
const order = Object.values(EDUCATION_CHOICES)
24-
const sortedOptions = options
25-
.slice()
26-
.sort((a, b) => {
27-
const ia = order.indexOf(a as any)
28-
const ib = order.indexOf(b as any)
29-
const sa = ia === -1 ? MAX_INT : ia
30-
const sb = ib === -1 ? MAX_INT : ib
31-
if (sa !== sb) return sa - sb
32-
return String(a).localeCompare(String(b))
33-
})
34-
23+
const sortedOptions = getSortedOptions(options, EDUCATION_CHOICES)
3524
const convertedTypes = sortedOptions.map((r) => convertEducationTypes(r as any))
36-
25+
3726
return (
3827
<div>
3928
<span className={clsx('font-semibold', highlightedClass)}>

web/components/filters/mobile-filters.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/polit
2424
import {EducationFilter, EducationFilterText} from "web/components/filters/education-filter";
2525
import {DrinksFilter, DrinksFilterText, getNoMinMaxDrinks} from "./drinks-filter";
2626
import {SmokerFilter, SmokerFilterText} from "./smoker-filter";
27+
import {ReligionFilter, ReligionFilterText} from "web/components/filters/religion-filter";
2728

2829
function MobileFilters(props: {
2930
filters: Partial<FilterFields>
@@ -329,6 +330,24 @@ function MobileFilters(props: {
329330
<PoliticalFilter filters={filters} updateFilter={updateFilter}/>
330331
</MobileFilterSection>
331332

333+
{/* RELIGION */}
334+
<MobileFilterSection
335+
title="Religion"
336+
openFilter={openFilter}
337+
setOpenFilter={setOpenFilter}
338+
isActive={hasAny(filters.religion || undefined)}
339+
selection={
340+
<ReligionFilterText
341+
options={filters.religion as string[]}
342+
highlightedClass={
343+
hasAny(filters.religion || undefined) ? 'text-primary-600' : 'text-ink-900'
344+
}
345+
/>
346+
}
347+
>
348+
<ReligionFilter filters={filters} updateFilter={updateFilter}/>
349+
</MobileFilterSection>
350+
332351
{/* EDUCATION */}
333352
<MobileFilterSection
334353
title="Education"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import clsx from 'clsx'
2+
import {MultiCheckbox} from 'web/components/multi-checkbox'
3+
4+
import {FilterFields} from "common/filters";
5+
import {RELIGION_CHOICES} from "web/components/filters/choices";
6+
import {convertReligionTypes} from "web/lib/util/convert-types";
7+
import stringOrStringArrayToText from "web/lib/util/string-or-string-array-to-text";
8+
import {getSortedOptions} from "common/util/sorting";
9+
10+
11+
export function ReligionFilterText(props: {
12+
options: string[] | undefined
13+
highlightedClass?: string
14+
}) {
15+
const {options, highlightedClass} = props
16+
const length = (options ?? []).length
17+
18+
if (!options || length < 1) {
19+
return (
20+
<span className={clsx('text-semibold', highlightedClass)}>Any religion</span>
21+
)
22+
}
23+
24+
const sortedOptions = getSortedOptions(options, RELIGION_CHOICES)
25+
const convertedTypes = sortedOptions.map((r) => convertReligionTypes(r as any))
26+
27+
return (
28+
<div>
29+
<span className={clsx('font-semibold', highlightedClass)}>
30+
{stringOrStringArrayToText({
31+
text: convertedTypes,
32+
capitalizeFirstLetterOption: true,
33+
})}{' '}
34+
</span>
35+
</div>
36+
)
37+
}
38+
39+
export function ReligionFilter(props: {
40+
filters: Partial<FilterFields>
41+
updateFilter: (newState: Partial<FilterFields>) => void
42+
}) {
43+
const {filters, updateFilter} = props
44+
return (
45+
<>
46+
<MultiCheckbox
47+
selected={filters.religion ?? []}
48+
choices={RELIGION_CHOICES}
49+
onChange={(c) => {
50+
updateFilter({religion: c})
51+
}}
52+
/>
53+
</>
54+
)
55+
}

0 commit comments

Comments
 (0)