Skip to content

Commit 342a0c6

Browse files
committed
Add filter for smoking
1 parent f1f9970 commit 342a0c6

File tree

7 files changed

+116
-10
lines changed

7 files changed

+116
-10
lines changed

backend/api/src/get-profiles.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export const loadProfiles = async (props: profileQueryType) => {
113113
has_kids == -1 ||
114114
(has_kids == 0 && !l.has_kids) ||
115115
(l.has_kids && l.has_kids > 0)) &&
116-
(!is_smoker || l.is_smoker === is_smoker) &&
116+
(is_smoker === undefined || l.is_smoker === is_smoker) &&
117117
(l.id.toString() != skipId) &&
118118
(!geodbCityIds ||
119119
(l.geodb_city_id && geodbCityIds.includes(l.geodb_city_id))) &&
@@ -209,7 +209,12 @@ export const loadProfiles = async (props: profileQueryType) => {
209209
has_kids === 0 && where(`has_kids IS NULL OR has_kids = 0`),
210210
has_kids && has_kids > 0 && where(`has_kids > 0`),
211211

212-
is_smoker !== undefined && where(`is_smoker = $(is_smoker)`, {is_smoker}),
212+
is_smoker !== undefined && (
213+
where(
214+
(is_smoker ? '' : 'is_smoker IS NULL OR ') + // smokers are rare, so we don't include the people who didn't answer if we're looking for smokers
215+
`is_smoker = $(is_smoker)`, {is_smoker}
216+
)
217+
),
213218

214219
geodbCityIds?.length &&
215220
where(`geodb_city_id = ANY($(geodbCityIds))`, {geodbCityIds}),

common/src/api/schema.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
contentSchema,
33
combinedProfileSchema,
44
baseProfilesSchema,
5-
arraybeSchema,
5+
arraybeSchema, zBoolean,
66
} from 'common/api/zod-types'
77
import {PrivateChatMessage} from 'common/chat-message'
88
import {CompatibilityScore} from 'common/profiles/compatibility-score'
@@ -357,8 +357,8 @@ export const API = (_apiTypeCheck = {
357357
political_beliefs: arraybeSchema.optional(),
358358
wants_kids_strength: z.coerce.number().optional(),
359359
has_kids: z.coerce.number().optional(),
360-
is_smoker: z.coerce.boolean().optional(),
361-
shortBio: z.coerce.boolean().optional(),
360+
is_smoker: zBoolean.optional().optional(),
361+
shortBio: zBoolean.optional().optional(),
362362
geodbCityIds: arraybeSchema.optional(),
363363
lat: z.coerce.number().optional(),
364364
lon: z.coerce.number().optional(),

common/src/api/zod-types.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ const genderType = z.string()
4242
// ])
4343
const genderTypes = z.array(genderType)
4444

45+
export const zBoolean = z
46+
.union([z.boolean(), z.string()])
47+
.transform((val) => val === true || val === "true");
48+
4549
export const baseProfilesSchema = z.object({
4650
// Required fields
4751
age: z.number().min(18).max(100).optional(),
@@ -51,7 +55,7 @@ export const baseProfilesSchema = z.object({
5155
pref_age_max: z.number().min(18).max(100).optional(),
5256
pref_relation_styles: z.array(z.string()),
5357
wants_kids_strength: z.number(),
54-
looking_for_matches: z.boolean(),
58+
looking_for_matches: zBoolean,
5559
photo_urls: z.array(z.string()),
5660
visibility: z.union([z.literal('public'), z.literal('member')]),
5761

@@ -76,17 +80,17 @@ const optionalProfilesSchema = z.object({
7680
ethnicity: z.array(z.string()).optional(),
7781
born_in_location: z.string().optional(),
7882
height_in_inches: z.number().optional(),
79-
has_pets: z.boolean().optional(),
83+
has_pets: zBoolean.optional().optional(),
8084
education_level: z.string().optional(),
81-
is_smoker: z.boolean().optional(),
85+
is_smoker: zBoolean.optional().optional(),
8286
drinks_per_month: z.number().min(0).optional(),
8387
diet: z.array(z.string()).optional(),
8488
has_kids: z.number().min(0).optional(),
8589
university: z.string().optional(),
8690
occupation_title: z.string().optional(),
8791
occupation: z.string().optional(),
8892
company: z.string().optional(),
89-
comments_enabled: z.boolean().optional(),
93+
comments_enabled: zBoolean.optional().optional(),
9094
website: z.string().optional(),
9195
bio: contentSchema.optional().nullable(),
9296
twitter: z.string().optional(),

common/src/envs/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const IS_DEPLOYED = IS_GOOGLE_CLOUD || IS_VERCEL
1414
export const IS_LOCAL = !IS_DEPLOYED
1515
export const HOSTING_ENV = IS_GOOGLE_CLOUD ? 'Google Cloud' : IS_VERCEL ? 'Vercel' : IS_LOCAL ? 'local' : 'unknown'
1616

17-
if (IS_LOCAL && !process.env.ENVIRONMENT) {
17+
if (IS_LOCAL && !process.env.ENVIRONMENT && !process.env.NEXT_PUBLIC_FIREBASE_ENV) {
1818
console.warn("No ENVIRONMENT set, defaulting to DEV")
1919
process.env.ENVIRONMENT = 'DEV'
2020
}

web/components/filters/desktop-filters.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {EducationFilter, EducationFilterText} from "web/components/filters/educa
2929
import {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'
3234

3335
export function DesktopFilters(props: {
3436
filters: Partial<FilterFields>
@@ -379,6 +381,31 @@ export function DesktopFilters(props: {
379381
menuWidth="w-50"
380382
/>
381383

384+
{/* SMOKER */}
385+
<CustomizeableDropdown
386+
buttonContent={(open) => (
387+
<DropdownButton
388+
open={open}
389+
content={
390+
<Row className="items-center gap-1">
391+
<LuCigarette className="h-4 w-4"/>
392+
<SmokerFilterText
393+
is_smoker={filters.is_smoker}
394+
highlightedClass={open ? 'text-primary-500' : undefined}
395+
/>
396+
</Row>
397+
}
398+
/>
399+
)}
400+
dropdownMenuContent={
401+
<Col className="mx-2 mb-4">
402+
<SmokerFilter filters={filters} updateFilter={updateFilter} />
403+
</Col>
404+
}
405+
popoverClassName="bg-canvas-50"
406+
menuWidth="w-50"
407+
/>
408+
382409
{/* EDUCATION */}
383410
<CustomizeableDropdown
384411
buttonContent={(open: boolean) => (

web/components/filters/mobile-filters.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {DietFilter, DietFilterText} from "web/components/filters/diet-filter";
2323
import {PoliticalFilter, PoliticalFilterText} from "web/components/filters/political-filter";
2424
import {EducationFilter, EducationFilterText} from "web/components/filters/education-filter";
2525
import {DrinksFilter, DrinksFilterText, getNoMinMaxDrinks} from "./drinks-filter";
26+
import {SmokerFilter, SmokerFilterText} from "./smoker-filter";
2627

2728
function MobileFilters(props: {
2829
filters: Partial<FilterFields>
@@ -277,6 +278,23 @@ function MobileFilters(props: {
277278
<DrinksFilter filters={filters} updateFilter={updateFilter} />
278279
</MobileFilterSection>
279280

281+
{/* SMOKER */}
282+
<MobileFilterSection
283+
title="Smoker"
284+
openFilter={openFilter}
285+
setOpenFilter={setOpenFilter}
286+
isActive={filters.is_smoker != null}
287+
selection={
288+
<SmokerFilterText
289+
is_smoker={filters.is_smoker}
290+
highlightedClass={filters.is_smoker == null ? 'text-ink-900' : 'text-primary-600'}
291+
mobile
292+
/>
293+
}
294+
>
295+
<SmokerFilter filters={filters} updateFilter={updateFilter} />
296+
</MobileFilterSection>
297+
280298
{/* POLITICS */}
281299
<MobileFilterSection
282300
title="Politics"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import clsx from 'clsx'
2+
import {Row} from 'web/components/layout/row'
3+
import {ChoicesToggleGroup} from 'web/components/widgets/choices-toggle-group'
4+
import {FilterFields} from 'common/filters'
5+
6+
export function SmokerFilterText(props: {
7+
is_smoker: boolean | null | undefined
8+
highlightedClass?: string
9+
mobile?: boolean
10+
}) {
11+
const {is_smoker, highlightedClass, mobile} = props
12+
return (
13+
<Row className="items-center gap-0.5">
14+
<span className={clsx(highlightedClass, is_smoker != null && 'font-semibold')}>
15+
{is_smoker == null
16+
? mobile ? 'Either' : 'Either'
17+
: is_smoker
18+
? mobile ? 'Yes' : 'Smoker'
19+
: mobile ? 'No' : "Non-smoker"}
20+
</span>
21+
</Row>
22+
)
23+
}
24+
25+
export function SmokerFilter(props: {
26+
filters: Partial<FilterFields>
27+
updateFilter: (newState: Partial<FilterFields>) => void
28+
}) {
29+
const {filters, updateFilter} = props
30+
31+
const choicesMap = {
32+
Either: 'either',
33+
Yes: 'yes',
34+
No: 'no',
35+
} as const
36+
37+
const currentChoice =
38+
filters.is_smoker == null ? choicesMap.Either : filters.is_smoker ? choicesMap.Yes : choicesMap.No
39+
40+
return (
41+
<ChoicesToggleGroup
42+
currentChoice={currentChoice}
43+
choicesMap={choicesMap}
44+
setChoice={(c) => {
45+
if (c === choicesMap.Either) updateFilter({is_smoker: undefined})
46+
else if (c === choicesMap.Yes) updateFilter({is_smoker: true})
47+
else updateFilter({is_smoker: false})
48+
}}
49+
toggleClassName="w-1/3 justify-center"
50+
/>
51+
)
52+
}

0 commit comments

Comments
 (0)