diff --git a/backend/api/src/get-lovers.ts b/backend/api/src/get-lovers.ts index edb2442c..6e038700 100644 --- a/backend/api/src/get-lovers.ts +++ b/backend/api/src/get-lovers.ts @@ -4,6 +4,7 @@ import {createSupabaseDirectClient} from 'shared/supabase/init' import {from, join, limit, orderBy, renderSql, select, where,} from 'shared/supabase/sql-builder' import {getCompatibleLovers} from 'api/compatible-lovers' import {intersection} from 'lodash' +import {MAX_INT, MIN_INT} from "common/constants"; export const getLovers: APIHandler<'get-lovers'> = async (props, _auth) => { const pg = createSupabaseDirectClient() @@ -37,8 +38,8 @@ export const getLovers: APIHandler<'get-lovers'> = async (props, _auth) => { (!name || l.user.name.toLowerCase().includes(name.toLowerCase())) && (!genders || genders.includes(l.gender)) && (!pref_gender || intersection(pref_gender, l.pref_gender).length) && - (!pref_age_min || l.age >= pref_age_min) && - (!pref_age_max || l.age <= pref_age_max) && + (!pref_age_min || (l.age ?? MAX_INT) >= pref_age_min) && + (!pref_age_max || (l.age ?? MIN_INT) <= pref_age_max) && (!pref_relation_styles || intersection(pref_relation_styles, l.pref_relation_styles).length) && (!wants_kids_strength || @@ -87,18 +88,18 @@ export const getLovers: APIHandler<'get-lovers'> = async (props, _auth) => { pref_gender?.length && where(`pref_gender && $(pref_gender)`, {pref_gender}), - pref_age_min !== undefined && - where(`age >= $(pref_age_min)`, {pref_age_min}), + pref_age_min && + where(`age >= $(pref_age_min) or age is null`, {pref_age_min}), - pref_age_max !== undefined && - where(`age <= $(pref_age_max)`, {pref_age_max}), + pref_age_max && + where(`age <= $(pref_age_max) or age is null`, {pref_age_max}), pref_relation_styles?.length && where(`pref_relation_styles && $(pref_relation_styles)`, { pref_relation_styles, }), - wants_kids_strength !== undefined && + !!wants_kids_strength && wants_kids_strength !== -1 && where( wants_kids_strength >= 2 @@ -125,7 +126,7 @@ export const getLovers: APIHandler<'get-lovers'> = async (props, _auth) => { limit(limitParam) ) - // console.debug('query:', query) + // console.log('query:', query) const lovers = await pg.map(query, [], convertRow) diff --git a/backend/supabase/lovers.sql b/backend/supabase/lovers.sql index 7e2d42f0..a0305f3f 100644 --- a/backend/supabase/lovers.sql +++ b/backend/supabase/lovers.sql @@ -7,7 +7,7 @@ END IF; END$$; CREATE TABLE IF NOT EXISTS lovers ( - age INTEGER DEFAULT 18 NOT NULL, + age INTEGER NULL, bio JSON, born_in_location TEXT, city TEXT NOT NULL, @@ -36,8 +36,8 @@ CREATE TABLE IF NOT EXISTS lovers ( photo_urls TEXT[], pinned_url TEXT, political_beliefs TEXT[], - pref_age_max INTEGER DEFAULT 100 NOT NULL, - pref_age_min INTEGER DEFAULT 18 NOT NULL, + pref_age_max INTEGER NULL, + pref_age_min INTEGER NULL, pref_gender TEXT[] NOT NULL, pref_relation_styles TEXT[] NOT NULL, referred_by_username TEXT, diff --git a/common/src/api/zod-types.ts b/common/src/api/zod-types.ts index 1d8b49b6..6153e75c 100644 --- a/common/src/api/zod-types.ts +++ b/common/src/api/zod-types.ts @@ -44,11 +44,11 @@ const genderTypes = z.array(genderType) export const baseLoversSchema = z.object({ // Required fields - age: z.number().min(18).max(100), + age: z.number().min(18).max(100).optional(), gender: genderType, pref_gender: genderTypes, - pref_age_min: z.number().min(18).max(999), - pref_age_max: z.number().min(18).max(1000), + pref_age_min: z.number().min(18).max(100).optional(), + pref_age_max: z.number().min(18).max(100).optional(), pref_relation_styles: z.array( z.union([ z.literal('collaboration'), diff --git a/common/src/constants.ts b/common/src/constants.ts new file mode 100644 index 00000000..e77f7d3a --- /dev/null +++ b/common/src/constants.ts @@ -0,0 +1,2 @@ +export const MAX_INT = 99999 +export const MIN_INT = -MAX_INT diff --git a/common/src/love/compatibility-util.ts b/common/src/love/compatibility-util.ts index e3a9bedf..fa9c646c 100644 --- a/common/src/love/compatibility-util.ts +++ b/common/src/love/compatibility-util.ts @@ -1,4 +1,5 @@ import { LoverRow } from 'common/love/lover' +import {MAX_INT, MIN_INT} from "common/constants"; const isPreferredGender = ( preferredGenders: string[] | undefined, @@ -25,8 +26,8 @@ export const areGenderCompatible = (lover1: LoverRow, lover2: LoverRow) => { ) } -const satisfiesAgeRange = (lover: LoverRow, age: number) => { - return age >= lover.pref_age_min && age <= lover.pref_age_max +const satisfiesAgeRange = (lover: LoverRow, age: number | null | undefined) => { + return (age ?? MAX_INT) >= (lover.pref_age_min ?? MIN_INT) && (age ?? MIN_INT) <= (lover.pref_age_max ?? MAX_INT) } export const areAgeCompatible = (lover1: LoverRow, lover2: LoverRow) => { diff --git a/common/src/love/og-image.ts b/common/src/love/og-image.ts index 734d7ee9..35643db5 100644 --- a/common/src/love/og-image.ts +++ b/common/src/love/og-image.ts @@ -19,7 +19,7 @@ export function getLoveOgImageUrl(user: User, lover?: LoverRow | null) { avatarUrl: lover?.pinned_url, username: user.username, name: user.name, - age: lover?.age.toString() ?? '25', + age: lover?.age?.toString() ?? '25', city: lover?.city ?? 'Internet', gender: lover?.gender ?? '???', } as LoveOgProps diff --git a/common/src/supabase/schema.ts b/common/src/supabase/schema.ts index ab8075f1..46c0dc98 100644 --- a/common/src/supabase/schema.ts +++ b/common/src/supabase/schema.ts @@ -262,7 +262,7 @@ export type Database = { } lovers: { Row: { - age: number + age: number | null bio: Json | null bio_text: unknown | null born_in_location: string | null @@ -292,8 +292,8 @@ export type Database = { photo_urls: string[] | null pinned_url: string | null political_beliefs: string[] | null - pref_age_max: number - pref_age_min: number + pref_age_max: number | null + pref_age_min: number | null pref_gender: string[] pref_relation_styles: string[] referred_by_username: string | null @@ -308,7 +308,7 @@ export type Database = { website: string | null } Insert: { - age?: number + age?: number | null bio?: Json | null bio_text?: unknown | null born_in_location?: string | null @@ -338,8 +338,8 @@ export type Database = { photo_urls?: string[] | null pinned_url?: string | null political_beliefs?: string[] | null - pref_age_max?: number - pref_age_min?: number + pref_age_max?: number | null + pref_age_min?: number | null pref_gender: string[] pref_relation_styles: string[] referred_by_username?: string | null @@ -354,7 +354,7 @@ export type Database = { website?: string | null } Update: { - age?: number + age?: number | null bio?: Json | null bio_text?: unknown | null born_in_location?: string | null @@ -384,8 +384,8 @@ export type Database = { photo_urls?: string[] | null pinned_url?: string | null political_beliefs?: string[] | null - pref_age_max?: number - pref_age_min?: number + pref_age_max?: number | null + pref_age_min?: number | null pref_gender?: string[] pref_relation_styles?: string[] referred_by_username?: string | null diff --git a/web/components/filters/age-filter.tsx b/web/components/filters/age-filter.tsx index 6218f24f..9bd164f9 100644 --- a/web/components/filters/age-filter.tsx +++ b/web/components/filters/age-filter.tsx @@ -3,11 +3,11 @@ import { FilterFields } from './search' import { RangeSlider } from 'web/components/widgets/slider' export const PREF_AGE_MIN = 18 -export const PREF_AGE_MAX = 99 +export const PREF_AGE_MAX = 100 export function getNoMinMaxAge( - pref_age_min: number | undefined, - pref_age_max: number | undefined + pref_age_min: number | null | undefined, + pref_age_max: number | null | undefined ) { const noMinAge = !pref_age_min || pref_age_min <= PREF_AGE_MIN const noMaxAge = !pref_age_max || pref_age_max >= PREF_AGE_MAX @@ -15,8 +15,8 @@ export function getNoMinMaxAge( } export function AgeFilterText(props: { - pref_age_min: number | undefined - pref_age_max: number | undefined + pref_age_min: number | null | undefined + pref_age_max: number | null | undefined highlightedClass?: string }) { const { pref_age_min, pref_age_max, highlightedClass } = props diff --git a/web/components/filters/desktop-filters.tsx b/web/components/filters/desktop-filters.tsx index c3d30e96..55eb89d7 100644 --- a/web/components/filters/desktop-filters.tsx +++ b/web/components/filters/desktop-filters.tsx @@ -52,6 +52,79 @@ export function DesktopFilters(props: { on={isYourFilters} hidden={!youLover} /> + {/* CONNECTION */} + ( + + + + + } + /> + )} + dropdownMenuContent={ + + } + popoverClassName="bg-canvas-50" + menuWidth="w-50" + /> + {/* LOCATION */} + ( + + } + open={open} + /> + )} + dropdownMenuContent={ + + } + popoverClassName="bg-canvas-50" + menuWidth="w-80" + /> + {/* AGE RANGE */} + ( + + } + /> + )} + dropdownMenuContent={ + + + + } + popoverClassName="bg-canvas-50" + menuWidth="w-80" + /> + {/* GENDER */} ( */} - {/* AGE RANGE */} - ( - - } - /> - )} - dropdownMenuContent={ - - - - } - popoverClassName="bg-canvas-50" - menuWidth="w-80" - /> - {/* LOCATION */} - ( - - } - open={open} - /> - )} - dropdownMenuContent={ - - } - popoverClassName="bg-canvas-50" - menuWidth="w-80" - /> - ( - - - - - } - /> - )} - dropdownMenuContent={ - - } - popoverClassName="bg-canvas-50" - menuWidth="w-50" - /> {/* WANTS KIDS */} - { - updateFilter({ - wants_kids_strength: wantsKidsLabels.no_preference.strength, - }) - }, - }, - { - name: wantsKidsLabels.wants_kids.name, - icon: wantsKidsLabels.wants_kids.icon, - onClick: () => { - updateFilter({ - wants_kids_strength: wantsKidsLabels.wants_kids.strength, - }) - }, - }, - { - name: wantsKidsLabels.doesnt_want_kids.name, - icon: wantsKidsLabels.doesnt_want_kids.icon, - onClick: () => { - updateFilter({ - wants_kids_strength: wantsKidsLabels.doesnt_want_kids.strength, - }) - }, - }, - ]} - closeOnClick - buttonClass={'!text-ink-600 !hover:!text-ink-600'} - buttonContent={(open: boolean) => ( - - } - open={open} - /> - )} - menuItemsClass={'bg-canvas-50'} - menuWidth="w-48" - /> + {/* {*/} + {/* updateFilter({*/} + {/* wants_kids_strength: wantsKidsLabels.no_preference.strength,*/} + {/* })*/} + {/* },*/} + {/* },*/} + {/* {*/} + {/* name: wantsKidsLabels.wants_kids.name,*/} + {/* icon: wantsKidsLabels.wants_kids.icon,*/} + {/* onClick: () => {*/} + {/* updateFilter({*/} + {/* wants_kids_strength: wantsKidsLabels.wants_kids.strength,*/} + {/* })*/} + {/* },*/} + {/* },*/} + {/* {*/} + {/* name: wantsKidsLabels.doesnt_want_kids.name,*/} + {/* icon: wantsKidsLabels.doesnt_want_kids.icon,*/} + {/* onClick: () => {*/} + {/* updateFilter({*/} + {/* wants_kids_strength: wantsKidsLabels.doesnt_want_kids.strength,*/} + {/* })*/} + {/* },*/} + {/* },*/} + {/* ]}*/} + {/* closeOnClick*/} + {/* buttonClass={'!text-ink-600 !hover:!text-ink-600'}*/} + {/* buttonContent={(open: boolean) => (*/} + {/* */} + {/* }*/} + {/* open={open}*/} + {/* />*/} + {/* )}*/} + {/* menuItemsClass={'bg-canvas-50'}*/} + {/* menuWidth="w-48"*/} + {/*/>*/} {/* HAS KIDS */} - { - updateFilter({ has_kids: hasKidsLabels.no_preference.value }) - }, - }, - { - name: hasKidsLabels.doesnt_have_kids.name, - onClick: () => { - updateFilter({ has_kids: hasKidsLabels.doesnt_have_kids.value }) - }, - }, - { - name: hasKidsLabels.has_kids.name, - onClick: () => { - updateFilter({ has_kids: hasKidsLabels.has_kids.value }) - }, - }, - ]} - closeOnClick - buttonClass={'!text-ink-600 !hover:!text-ink-600'} - buttonContent={(open: boolean) => ( - - } - open={open} - /> - )} - menuItemsClass="bg-canvas-50" - menuWidth="w-40" - /> + {/* {*/} + {/* updateFilter({ has_kids: hasKidsLabels.no_preference.value })*/} + {/* },*/} + {/* },*/} + {/* {*/} + {/* name: hasKidsLabels.doesnt_have_kids.name,*/} + {/* onClick: () => {*/} + {/* updateFilter({ has_kids: hasKidsLabels.doesnt_have_kids.value })*/} + {/* },*/} + {/* },*/} + {/* {*/} + {/* name: hasKidsLabels.has_kids.name,*/} + {/* onClick: () => {*/} + {/* updateFilter({ has_kids: hasKidsLabels.has_kids.value })*/} + {/* },*/} + {/* },*/} + {/* ]}*/} + {/* closeOnClick*/} + {/* buttonClass={'!text-ink-600 !hover:!text-ink-600'}*/} + {/* buttonContent={(open: boolean) => (*/} + {/* */} + {/* }*/} + {/* open={open}*/} + {/* />*/} + {/* )}*/} + {/* menuItemsClass="bg-canvas-50"*/} + {/* menuWidth="w-40"*/} + {/*/>*/}