Skip to content

Commit fdd9650

Browse files
committed
Add politics filter
1 parent 2ad87a5 commit fdd9650

File tree

8 files changed

+188
-58
lines changed

8 files changed

+188
-58
lines changed

backend/api/src/get-profiles.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export type profileQueryType = {
1818
pref_relation_styles?: String[] | undefined,
1919
pref_romantic_styles?: String[] | undefined,
2020
diet?: String[] | undefined,
21+
political_beliefs?: String[] | undefined,
2122
wants_kids_strength?: number | undefined,
2223
has_kids?: number | undefined,
2324
is_smoker?: boolean | undefined,
@@ -49,6 +50,7 @@ export const loadProfiles = async (props: profileQueryType) => {
4950
pref_relation_styles,
5051
pref_romantic_styles,
5152
diet,
53+
political_beliefs,
5254
wants_kids_strength,
5355
has_kids,
5456
is_smoker,
@@ -89,6 +91,8 @@ export const loadProfiles = async (props: profileQueryType) => {
8991
intersection(pref_romantic_styles, l.pref_romantic_styles).length) &&
9092
(!diet ||
9193
intersection(diet, l.diet).length) &&
94+
(!political_beliefs ||
95+
intersection(political_beliefs, l.political_beliefs).length) &&
9296
(!wants_kids_strength ||
9397
wants_kids_strength == -1 ||
9498
!l.wants_kids_strength ||
@@ -172,6 +176,12 @@ export const loadProfiles = async (props: profileQueryType) => {
172176
{diet}
173177
),
174178

179+
political_beliefs?.length &&
180+
where(
181+
`political_beliefs IS NULL OR political_beliefs = '{}' OR political_beliefs && $(political_beliefs)`,
182+
{political_beliefs}
183+
),
184+
175185
!!wants_kids_strength &&
176186
wants_kids_strength !== -1 &&
177187
where(

common/src/api/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ export const API = (_apiTypeCheck = {
351351
pref_relation_styles: arraybeSchema.optional(),
352352
pref_romantic_styles: arraybeSchema.optional(),
353353
diet: arraybeSchema.optional(),
354+
political_beliefs: arraybeSchema.optional(),
354355
wants_kids_strength: z.coerce.number().optional(),
355356
has_kids: z.coerce.number().optional(),
356357
is_smoker: z.coerce.boolean().optional(),

common/src/filters.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type FilterFields = {
2323
| 'pref_relation_styles'
2424
| 'pref_romantic_styles'
2525
| 'diet'
26+
| 'political_beliefs'
2627
| 'is_smoker'
2728
| 'has_kids'
2829
| 'pref_gender'
@@ -64,6 +65,7 @@ export const initialFilters: Partial<FilterFields> = {
6465
pref_relation_styles: undefined,
6566
pref_romantic_styles: undefined,
6667
diet: undefined,
68+
political_beliefs: undefined,
6769
pref_gender: undefined,
6870
shortBio: undefined,
6971
orderBy: 'created_time',

web/components/filters/desktop-filters.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {ChevronDownIcon, ChevronUpIcon} from '@heroicons/react/outline'
2-
import {DietType, RelationshipType, RomanticType} from 'web/lib/util/convert-types'
2+
import {DietType, PoliticalType, RelationshipType, RomanticType} from 'web/lib/util/convert-types'
33
import {ReactNode} from 'react'
44
import {FaUserGroup} from 'react-icons/fa6'
55
import {Col} from 'web/components/layout/col'
@@ -22,6 +22,7 @@ import {HasKidsLabel} from "web/components/filters/has-kids-filter";
2222
import {RomanticFilter, RomanticFilterText} from "web/components/filters/romantic-filter";
2323
import {FaHeart} from "react-icons/fa";
2424
import {DietFilter, DietFilterText} from "web/components/filters/diet-filter";
25+
import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/political-filter";
2526

2627
export function DesktopFilters(props: {
2728
filters: Partial<FilterFields>
@@ -318,6 +319,32 @@ export function DesktopFilters(props: {
318319
menuWidth="w-50"
319320
/>
320321

322+
{/* POLITICS */}
323+
<CustomizeableDropdown
324+
buttonContent={(open) => (
325+
<DropdownButton
326+
open={open}
327+
content={
328+
<Row className="items-center gap-1">
329+
<PoliticalFilterText
330+
options={
331+
filters.political_beliefs as
332+
| PoliticalType[]
333+
| undefined
334+
}
335+
highlightedClass={open ? 'text-primary-500' : undefined}
336+
/>
337+
</Row>
338+
}
339+
/>
340+
)}
341+
dropdownMenuContent={
342+
<PoliticalFilter filters={filters} updateFilter={updateFilter}/>
343+
}
344+
popoverClassName="bg-canvas-50"
345+
menuWidth="w-50"
346+
/>
347+
321348
{/* Short Bios */}
322349
<ShortBioToggle
323350
updateFilter={updateFilter}

web/components/filters/mobile-filters.tsx

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {RelationshipFilter, RelationshipFilterText,} from './relationship-filter
1010
import {MyMatchesToggle} from './my-matches-toggle'
1111
import {Profile} from 'common/profiles/profile'
1212
import {Gender} from 'common/gender'
13-
import {DietType, RelationshipType, RomanticType} from 'web/lib/util/convert-types'
13+
import {DietType, PoliticalType, RelationshipType, RomanticType} from 'web/lib/util/convert-types'
1414
import {FilterFields} from "common/filters";
1515
import {ShortBioToggle} from "web/components/filters/short-bio-toggle";
1616
import {PrefGenderFilter, PrefGenderFilterText} from "./pref-gender-filter"
@@ -21,6 +21,7 @@ import {HasKidsFilter, HasKidsLabel} from "./has-kids-filter"
2121
import {hasKidsLabels} from "common/has-kids";
2222
import {RomanticFilter, RomanticFilterText} from "web/components/filters/romantic-filter";
2323
import {DietFilter, DietFilterText} from "web/components/filters/diet-filter";
24+
import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/political-filter";
2425

2526
function MobileFilters(props: {
2627
filters: Partial<FilterFields>
@@ -188,74 +189,94 @@ function MobileFilters(props: {
188189
<RomanticFilter filters={filters} updateFilter={updateFilter}/>
189190
</MobileFilterSection>
190191

191-
{/* WANTS KIDS */}
192-
<MobileFilterSection
193-
title="Wants kids"
194-
openFilter={openFilter}
195-
setOpenFilter={setOpenFilter}
196-
isActive={
197-
filters.wants_kids_strength != null &&
198-
filters.wants_kids_strength !== -1
199-
}
200-
icon={<WantsKidsIcon strength={filters.wants_kids_strength ?? -1}/>}
201-
selection={
202-
<KidsLabel
203-
strength={filters.wants_kids_strength ?? -1}
204-
highlightedClass={
205-
(filters.wants_kids_strength ?? -1) ==
206-
wantsKidsLabels.no_preference.strength
207-
? 'text-ink-900'
208-
: 'text-primary-600'
209-
}
210-
mobile
211-
/>
212-
}
213-
>
214-
<WantsKidsFilter filters={filters} updateFilter={updateFilter}/>
215-
</MobileFilterSection>
192+
{/* WANTS KIDS */}
193+
<MobileFilterSection
194+
title="Wants kids"
195+
openFilter={openFilter}
196+
setOpenFilter={setOpenFilter}
197+
isActive={
198+
filters.wants_kids_strength != null &&
199+
filters.wants_kids_strength !== -1
200+
}
201+
icon={<WantsKidsIcon strength={filters.wants_kids_strength ?? -1}/>}
202+
selection={
203+
<KidsLabel
204+
strength={filters.wants_kids_strength ?? -1}
205+
highlightedClass={
206+
(filters.wants_kids_strength ?? -1) ==
207+
wantsKidsLabels.no_preference.strength
208+
? 'text-ink-900'
209+
: 'text-primary-600'
210+
}
211+
mobile
212+
/>
213+
}
214+
>
215+
<WantsKidsFilter filters={filters} updateFilter={updateFilter}/>
216+
</MobileFilterSection>
216217

217-
{/* HAS KIDS */}
218+
{/* HAS KIDS */}
219+
<MobileFilterSection
220+
title="Has kids"
221+
openFilter={openFilter}
222+
setOpenFilter={setOpenFilter}
223+
isActive={filters.has_kids != null && filters.has_kids !== -1}
224+
icon={<FaChild className="text-ink-900 h-4 w-4"/>}
225+
selection={
226+
<HasKidsLabel
227+
has_kids={filters.has_kids ?? -1}
228+
highlightedClass={
229+
(filters.has_kids ?? -1) == hasKidsLabels.no_preference.value
230+
? 'text-ink-900'
231+
: 'text-primary-600'
232+
}
233+
mobile
234+
/>
235+
}
236+
>
237+
<HasKidsFilter filters={filters} updateFilter={updateFilter}/>
238+
</MobileFilterSection>
239+
240+
</>}
241+
242+
{/* DIET */}
218243
<MobileFilterSection
219-
title="Has kids"
244+
title="Diet"
220245
openFilter={openFilter}
221246
setOpenFilter={setOpenFilter}
222-
isActive={filters.has_kids != null && filters.has_kids !== -1}
223-
icon={<FaChild className="text-ink-900 h-4 w-4"/>}
247+
isActive={hasAny(filters.diet || undefined)}
224248
selection={
225-
<HasKidsLabel
226-
has_kids={filters.has_kids ?? -1}
249+
<DietFilterText
250+
options={filters.diet as DietType[]}
227251
highlightedClass={
228-
(filters.has_kids ?? -1) == hasKidsLabels.no_preference.value
229-
? 'text-ink-900'
230-
: 'text-primary-600'
252+
hasAny(filters.diet || undefined)
253+
? 'text-primary-600'
254+
: 'text-ink-900'
231255
}
232-
mobile
233256
/>
234257
}
235258
>
236-
<HasKidsFilter filters={filters} updateFilter={updateFilter}/>
259+
<DietFilter filters={filters} updateFilter={updateFilter}/>
237260
</MobileFilterSection>
238261

239-
</>}
240-
241-
{/* DIET */}
262+
{/* POLITICS */}
242263
<MobileFilterSection
243-
title="Diet"
264+
title="Politics"
244265
openFilter={openFilter}
245266
setOpenFilter={setOpenFilter}
246-
isActive={hasAny(filters.diet || undefined)}
267+
isActive={hasAny(filters.political_beliefs || undefined)}
247268
selection={
248-
<DietFilterText
249-
options={filters.diet as DietType[]}
269+
<PoliticalFilterText
270+
options={filters.political_beliefs as PoliticalType[]}
250271
highlightedClass={
251-
hasAny(filters.diet || undefined)
272+
hasAny(filters.political_beliefs || undefined)
252273
? 'text-primary-600'
253274
: 'text-ink-900'
254275
}
255276
/>
256277
}
257278
>
258-
<DietFilter filters={filters} updateFilter={updateFilter}/>
279+
<PoliticalFilter filters={filters} updateFilter={updateFilter}/>
259280
</MobileFilterSection>
260281

261282
{/* Short Bios */}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import clsx from 'clsx'
2+
import {convertPoliticalTypes, PoliticalType,} from 'web/lib/util/convert-types'
3+
import stringOrStringArrayToText from 'web/lib/util/string-or-string-array-to-text'
4+
import {MultiCheckbox} from 'web/components/multi-checkbox'
5+
6+
import {POLITICAL_CHOICES} from "web/components/filters/choices";
7+
import {FilterFields} from "common/filters";
8+
9+
export function PoliticalFilterText(props: {
10+
options: PoliticalType[] | undefined
11+
highlightedClass?: string
12+
}) {
13+
const {options, highlightedClass} = props
14+
const length = (options ?? []).length
15+
16+
if (!options || length < 1) {
17+
return (
18+
<span className={clsx('text-semibold', highlightedClass)}>Any politics</span>
19+
)
20+
}
21+
22+
const convertedTypes = options.map((r) =>
23+
convertPoliticalTypes(r)
24+
)
25+
26+
if (length > 1) {
27+
return (
28+
<span>
29+
<span className={clsx('font-semibold', highlightedClass)}>
30+
Multiple
31+
</span>
32+
</span>
33+
)
34+
}
35+
return (
36+
<div>
37+
<span className={clsx('font-semibold', highlightedClass)}>
38+
{stringOrStringArrayToText({
39+
text: convertedTypes,
40+
capitalizeFirstLetterOption: true,
41+
})}{' '}
42+
</span>
43+
</div>
44+
)
45+
}
46+
47+
export function PoliticalFilter(props: {
48+
filters: Partial<FilterFields>
49+
updateFilter: (newState: Partial<FilterFields>) => void
50+
}) {
51+
const {filters, updateFilter} = props
52+
return (
53+
<MultiCheckbox
54+
selected={filters.political_beliefs ?? []}
55+
choices={POLITICAL_CHOICES as any}
56+
onChange={(c) => {
57+
updateFilter({political_beliefs: c})
58+
}}
59+
/>
60+
)
61+
}

web/components/filters/use-filters.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const useFilters = (you: Profile | undefined) => {
8585
pref_relation_styles: you?.pref_relation_styles.length ? you.pref_relation_styles : undefined,
8686
pref_romantic_styles: you?.pref_romantic_styles?.length ? you.pref_romantic_styles : undefined,
8787
diet: you?.diet?.length ? you.diet : undefined,
88+
political_beliefs: you?.political_beliefs?.length ? you.political_beliefs : undefined,
8889
wants_kids_strength: wantsKidsDatabaseToWantsKidsFilter(
8990
(you?.wants_kids_strength ?? 2) as wantsKidsDatabase
9091
),
@@ -95,16 +96,17 @@ export const useFilters = (you: Profile | undefined) => {
9596
console.debug(you, yourFilters)
9697

9798
const isYourFilters =
98-
!!you &&
99-
(!location || location.id === you.geodb_city_id) &&
100-
isEqual(filters.genders?.length ? filters.genders : undefined, yourFilters.genders?.length ? yourFilters.genders : undefined) &&
101-
filters.pref_gender?.length == 1 && isEqual(filters.pref_gender?.length ? filters.pref_gender[0] : undefined, you.gender) &&
102-
isEqual(new Set(filters.pref_romantic_styles), new Set(you.pref_romantic_styles)) &&
103-
isEqual(new Set(filters.pref_relation_styles), new Set(you.pref_relation_styles)) &&
104-
isEqual(new Set(filters.diet), new Set(you.diet)) &&
105-
filters.pref_age_max == yourFilters.pref_age_max &&
106-
filters.pref_age_min == yourFilters.pref_age_min &&
107-
filters.wants_kids_strength == yourFilters.wants_kids_strength
99+
!!you
100+
&& (!location || location.id === you.geodb_city_id)
101+
&& isEqual(filters.genders?.length ? filters.genders : undefined, yourFilters.genders?.length ? yourFilters.genders : undefined)
102+
&& (!you.gender || filters.pref_gender?.length == 1 && isEqual(filters.pref_gender?.length ? filters.pref_gender[0] : undefined, you.gender))
103+
&& isEqual(new Set(filters.pref_romantic_styles), new Set(you.pref_romantic_styles))
104+
&& isEqual(new Set(filters.pref_relation_styles), new Set(you.pref_relation_styles))
105+
&& isEqual(new Set(filters.diet), new Set(you.diet))
106+
&& isEqual(new Set(filters.political_beliefs), new Set(you.political_beliefs))
107+
&& filters.pref_age_max == yourFilters.pref_age_max
108+
&& filters.pref_age_min == yourFilters.pref_age_min
109+
&& filters.wants_kids_strength == yourFilters.wants_kids_strength
108110

109111
const setYourFilters = (checked: boolean) => {
110112
if (checked) {

web/lib/util/convert-types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import {
22
REVERTED_DIET_CHOICES,
33
REVERTED_RELATIONSHIP_CHOICES,
4-
REVERTED_ROMANTIC_CHOICES
4+
REVERTED_ROMANTIC_CHOICES,
5+
REVERTED_POLITICAL_CHOICES
56
} from "web/components/filters/choices";
67

78
export type RelationshipType = keyof typeof REVERTED_RELATIONSHIP_CHOICES
89
export type RomanticType = keyof typeof REVERTED_ROMANTIC_CHOICES
910
export type DietType = keyof typeof REVERTED_DIET_CHOICES
11+
export type PoliticalType = keyof typeof REVERTED_POLITICAL_CHOICES
1012

1113
export function convertRelationshipType(relationshipType: RelationshipType) {
1214
return REVERTED_RELATIONSHIP_CHOICES[relationshipType]
@@ -19,3 +21,7 @@ export function convertRomanticTypes(romanticType: RomanticType) {
1921
export function convertDietTypes(dietType: DietType) {
2022
return REVERTED_DIET_CHOICES[dietType]
2123
}
24+
25+
export function convertPoliticalTypes(politicalType: PoliticalType) {
26+
return REVERTED_POLITICAL_CHOICES[politicalType]
27+
}

0 commit comments

Comments
 (0)