Meke age optional in API requests

This commit is contained in:
MartinBraquet
2025-09-15 16:04:30 +02:00
parent 083ef3010d
commit 8f4c6b911a
18 changed files with 348 additions and 322 deletions

View File

@@ -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)

View File

@@ -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,

View File

@@ -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'),

2
common/src/constants.ts Normal file
View File

@@ -0,0 +1,2 @@
export const MAX_INT = 99999
export const MIN_INT = -MAX_INT

View File

@@ -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) => {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -52,6 +52,79 @@ export function DesktopFilters(props: {
on={isYourFilters}
hidden={!youLover}
/>
{/* CONNECTION */}
<CustomizeableDropdown
buttonContent={(open) => (
<DropdownButton
open={open}
content={
<Row className="items-center gap-1">
<FaUserGroup className="h-4 w-4" />
<RelationshipFilterText
relationship={
filters.pref_relation_styles as
| RelationshipType[]
| undefined
}
highlightedClass={open ? 'text-primary-500' : undefined}
/>
</Row>
}
/>
)}
dropdownMenuContent={
<RelationshipFilter filters={filters} updateFilter={updateFilter} />
}
popoverClassName="bg-canvas-50"
menuWidth="w-50"
/>
{/* LOCATION */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
content={
<LocationFilterText
youLover={youLover}
location={locationFilterProps.location}
radius={locationFilterProps.radius}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
open={open}
/>
)}
dropdownMenuContent={
<LocationFilter
youLover={youLover}
locationFilterProps={locationFilterProps}
/>
}
popoverClassName="bg-canvas-50"
menuWidth="w-80"
/>
{/* AGE RANGE */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
open={open}
content={
<AgeFilterText
pref_age_min={filters.pref_age_min}
pref_age_max={filters.pref_age_max}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
/>
)}
dropdownMenuContent={
<Col className="mx-2 mb-4">
<AgeFilter filters={filters} updateFilter={updateFilter} />
</Col>
}
popoverClassName="bg-canvas-50"
menuWidth="w-80"
/>
{/* GENDER */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
@@ -91,165 +164,94 @@ export function DesktopFilters(props: {
{/* }*/}
{/* popoverClassName="bg-canvas-50"*/}
{/*/>*/}
{/* AGE RANGE */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
open={open}
content={
<AgeFilterText
pref_age_min={filters.pref_age_min}
pref_age_max={filters.pref_age_max}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
/>
)}
dropdownMenuContent={
<Col className="mx-2 mb-4">
<AgeFilter filters={filters} updateFilter={updateFilter} />
</Col>
}
popoverClassName="bg-canvas-50"
menuWidth="w-80"
/>
{/* LOCATION */}
<CustomizeableDropdown
buttonContent={(open: boolean) => (
<DropdownButton
content={
<LocationFilterText
youLover={youLover}
location={locationFilterProps.location}
radius={locationFilterProps.radius}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
open={open}
/>
)}
dropdownMenuContent={
<LocationFilter
youLover={youLover}
locationFilterProps={locationFilterProps}
/>
}
popoverClassName="bg-canvas-50"
menuWidth="w-80"
/>
<CustomizeableDropdown
buttonContent={(open) => (
<DropdownButton
open={open}
content={
<Row className="items-center gap-1">
<FaUserGroup className="h-4 w-4" />
<RelationshipFilterText
relationship={
filters.pref_relation_styles as
| RelationshipType[]
| undefined
}
highlightedClass={open ? 'text-primary-500' : undefined}
/>
</Row>
}
/>
)}
dropdownMenuContent={
<RelationshipFilter filters={filters} updateFilter={updateFilter} />
}
popoverClassName="bg-canvas-50"
menuWidth="w-50"
/>
{/* WANTS KIDS */}
<DropdownMenu
items={[
{
name: wantsKidsLabels.no_preference.name,
icon: wantsKidsLabels.no_preference.icon,
onClick: () => {
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) => (
<DropdownButton
content={
<KidsLabel
strength={
filters.wants_kids_strength ??
wantsKidsLabels.no_preference.strength
}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
open={open}
/>
)}
menuItemsClass={'bg-canvas-50'}
menuWidth="w-48"
/>
{/*<DropdownMenu*/}
{/* items={[*/}
{/* {*/}
{/* name: wantsKidsLabels.no_preference.name,*/}
{/* icon: wantsKidsLabels.no_preference.icon,*/}
{/* onClick: () => {*/}
{/* 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) => (*/}
{/* <DropdownButton*/}
{/* content={*/}
{/* <KidsLabel*/}
{/* strength={*/}
{/* filters.wants_kids_strength ??*/}
{/* wantsKidsLabels.no_preference.strength*/}
{/* }*/}
{/* highlightedClass={open ? 'text-primary-500' : ''}*/}
{/* />*/}
{/* }*/}
{/* open={open}*/}
{/* />*/}
{/* )}*/}
{/* menuItemsClass={'bg-canvas-50'}*/}
{/* menuWidth="w-48"*/}
{/*/>*/}
{/* HAS KIDS */}
<DropdownMenu
items={[
{
name: hasKidsLabels.no_preference.name,
onClick: () => {
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) => (
<DropdownButton
content={
<HasKidsLabel
has_kids={filters.has_kids ?? -1}
highlightedClass={open ? 'text-primary-500' : ''}
/>
}
open={open}
/>
)}
menuItemsClass="bg-canvas-50"
menuWidth="w-40"
/>
{/*<DropdownMenu*/}
{/* items={[*/}
{/* {*/}
{/* name: hasKidsLabels.no_preference.name,*/}
{/* onClick: () => {*/}
{/* 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) => (*/}
{/* <DropdownButton*/}
{/* content={*/}
{/* <HasKidsLabel*/}
{/* has_kids={filters.has_kids ?? -1}*/}
{/* highlightedClass={open ? 'text-primary-500' : ''}*/}
{/* />*/}
{/* }*/}
{/* open={open}*/}
{/* />*/}
{/* )}*/}
{/* menuItemsClass="bg-canvas-50"*/}
{/* menuWidth="w-40"*/}
{/*/>*/}
<button
className="text-ink-500 hover:text-primary-500 underline"
onClick={clearFilters}

View File

@@ -68,6 +68,68 @@ export function MobileFilters(props: {
hidden={!youLover}
/>
</Col>
{/* RELATIONSHIP STYLE */}
<MobileFilterSection
title="Seeking"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={hasAny(filters.pref_relation_styles)}
selection={
<RelationshipFilterText
relationship={filters.pref_relation_styles as RelationshipType[]}
highlightedClass={
hasAny(filters.pref_relation_styles)
? 'text-primary-600'
: 'text-ink-400'
}
/>
}
>
<RelationshipFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/* LOCATION */}
<MobileFilterSection
title="Location"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={!!locationFilterProps.location}
selection={
<LocationFilterText
location={locationFilterProps.location}
radius={locationFilterProps.radius}
youLover={youLover}
highlightedClass={
!locationFilterProps.location
? 'text-ink-400'
: 'text-primary-600'
}
/>
}
>
<LocationFilter
youLover={youLover}
locationFilterProps={locationFilterProps}
/>
</MobileFilterSection>
{/* AGE RANGE */}
<MobileFilterSection
title="Age"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
childrenClassName={'pb-6'}
isActive={!noMinAge || !noMaxAge}
selection={
<AgeFilterText
pref_age_min={filters.pref_age_min}
pref_age_max={filters.pref_age_max}
highlightedClass={
noMinAge && noMaxAge ? 'text-ink-400' : 'text-primary-600'
}
/>
}
>
<AgeFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/* GENDER */}
<MobileFilterSection
title="Gender"
@@ -102,114 +164,52 @@ export function MobileFilters(props: {
{/*>*/}
{/* <PrefGenderFilter filters={filters} updateFilter={updateFilter} />*/}
{/*</MobileFilterSection>*/}
{/* AGE RANGE */}
<MobileFilterSection
title="Age"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
childrenClassName={'pb-6'}
isActive={!noMinAge || !noMaxAge}
selection={
<AgeFilterText
pref_age_min={filters.pref_age_min}
pref_age_max={filters.pref_age_max}
highlightedClass={
noMinAge && noMaxAge ? 'text-ink-400' : 'text-primary-600'
}
/>
}
>
<AgeFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/* LOCATION */}
<MobileFilterSection
title="Location"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={!!locationFilterProps.location}
selection={
<LocationFilterText
location={locationFilterProps.location}
radius={locationFilterProps.radius}
youLover={youLover}
highlightedClass={
!locationFilterProps.location
? 'text-ink-400'
: 'text-primary-600'
}
/>
}
>
<LocationFilter
youLover={youLover}
locationFilterProps={locationFilterProps}
/>
</MobileFilterSection>
{/* RELATIONSHIP STYLE */}
<MobileFilterSection
title="Relationship style"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={hasAny(filters.pref_relation_styles)}
selection={
<RelationshipFilterText
relationship={filters.pref_relation_styles as RelationshipType[]}
highlightedClass={
hasAny(filters.pref_relation_styles)
? 'text-primary-600'
: 'text-ink-400'
}
/>
}
>
<RelationshipFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/* WANTS KIDS */}
<MobileFilterSection
title="Wants kids"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={
filters.wants_kids_strength != null &&
filters.wants_kids_strength !== -1
}
icon={<WantsKidsIcon strength={filters.wants_kids_strength ?? -1} />}
selection={
<KidsLabel
strength={filters.wants_kids_strength ?? -1}
highlightedClass={
(filters.wants_kids_strength ?? -1) ==
wantsKidsLabels.no_preference.strength
? 'text-ink-400'
: 'text-primary-600'
}
mobile
/>
}
>
<WantsKidsFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/*<MobileFilterSection*/}
{/* title="Wants kids"*/}
{/* openFilter={openFilter}*/}
{/* setOpenFilter={setOpenFilter}*/}
{/* isActive={*/}
{/* filters.wants_kids_strength != null &&*/}
{/* filters.wants_kids_strength !== -1*/}
{/* }*/}
{/* icon={<WantsKidsIcon strength={filters.wants_kids_strength ?? -1} />}*/}
{/* selection={*/}
{/* <KidsLabel*/}
{/* strength={filters.wants_kids_strength ?? -1}*/}
{/* highlightedClass={*/}
{/* (filters.wants_kids_strength ?? -1) ==*/}
{/* wantsKidsLabels.no_preference.strength*/}
{/* ? 'text-ink-400'*/}
{/* : 'text-primary-600'*/}
{/* }*/}
{/* mobile*/}
{/* />*/}
{/* }*/}
{/*>*/}
{/* <WantsKidsFilter filters={filters} updateFilter={updateFilter} />*/}
{/*</MobileFilterSection>*/}
{/* HAS KIDS */}
<MobileFilterSection
title="Has kids"
openFilter={openFilter}
setOpenFilter={setOpenFilter}
isActive={filters.has_kids != null && filters.has_kids !== -1}
icon={<FaChild className="text-ink-400 h-4 w-4" />}
selection={
<HasKidsLabel
has_kids={filters.has_kids ?? -1}
highlightedClass={
(filters.has_kids ?? -1) == hasKidsLabels.no_preference.value
? 'text-ink-400'
: 'text-primary-600'
}
mobile
/>
}
>
<HasKidsFilter filters={filters} updateFilter={updateFilter} />
</MobileFilterSection>
{/*<MobileFilterSection*/}
{/* title="Has kids"*/}
{/* openFilter={openFilter}*/}
{/* setOpenFilter={setOpenFilter}*/}
{/* isActive={filters.has_kids != null && filters.has_kids !== -1}*/}
{/* icon={<FaChild className="text-ink-400 h-4 w-4" />}*/}
{/* selection={*/}
{/* <HasKidsLabel*/}
{/* has_kids={filters.has_kids ?? -1}*/}
{/* highlightedClass={*/}
{/* (filters.has_kids ?? -1) == hasKidsLabels.no_preference.value*/}
{/* ? 'text-ink-400'*/}
{/* : 'text-primary-600'*/}
{/* }*/}
{/* mobile*/}
{/* />*/}
{/* }*/}
{/*>*/}
{/* <HasKidsFilter filters={filters} updateFilter={updateFilter} />*/}
{/*</MobileFilterSection>*/}
<button
className="text-ink-500 hover:text-primary-500 underline"
onClick={clearFilters}

View File

@@ -45,8 +45,8 @@ export const initialFilters: Partial<FilterFields> = {
genders: undefined,
pref_age_max: undefined,
pref_age_min: undefined,
has_kids: -1,
wants_kids_strength: -1,
has_kids: undefined,
wants_kids_strength: undefined,
is_smoker: undefined,
pref_relation_styles: undefined,
pref_gender: undefined,
@@ -61,7 +61,21 @@ export const useFilters = (you: Lover | undefined) => {
)
const updateFilter = (newState: Partial<FilterFields>) => {
setFilters((prevState) => ({ ...prevState, ...newState }))
const updatedState = { ...newState }
if ('pref_age_min' in updatedState && updatedState.pref_age_min !== undefined) {
if (updatedState.pref_age_min != null && updatedState.pref_age_min <= 18) {
updatedState.pref_age_min = undefined
}
}
if ('pref_age_max' in updatedState && updatedState.pref_age_max !== undefined) {
if (updatedState.pref_age_max != null && updatedState.pref_age_max >= 99) {
updatedState.pref_age_max = undefined
}
}
setFilters((prevState) => ({ ...prevState, ...updatedState }))
}
const clearFilters = () => {
@@ -110,11 +124,11 @@ export const useFilters = (you: Lover | undefined) => {
(you?.wants_kids_strength ?? 2) as wantsKidsDatabase
),
}
console.log(you, yourFilters)
const isYourFilters =
!!you &&
!!location &&
location.id === you.geodb_city_id &&
(!location || location.id === you.geodb_city_id) &&
isEqual(filters.genders?.length ? filters.genders : undefined, yourFilters.genders?.length ? yourFilters.genders : undefined) &&
// isEqual(filters.pref_gender?.length ? filters.pref_gender[0] : undefined, you.gender) &&
// you?.pref_gender.length &&

View File

@@ -29,6 +29,10 @@ export function wantsKidsToHasKidsFilter(wantsKidsStrength: wantsKidsDatabase) {
export function wantsKidsDatabaseToWantsKidsFilter(
wantsKidsStrength: wantsKidsDatabase
) {
console.log(wantsKidsStrength)
if (wantsKidsStrength == wantsKidsLabels.no_preference.strength) {
return wantsKidsLabels.no_preference.strength
}
if (wantsKidsStrength > wantsKidsLabels.wants_kids.strength) {
return wantsKidsLabels.wants_kids.strength
}

View File

@@ -107,11 +107,11 @@ function Seeking(props: { lover: Lover }) {
})
const ageRangeText =
min == 18 && max == 99
min == 18 && max == 100
? 'of any age'
: min == max
? `exactly ${min} years old`
: max == 99
: max == 100
? `${min} or older`
: `between ${min} - ${max} years old`

View File

@@ -195,7 +195,7 @@ export const OptionalLoveUserForm = (props: {
<Input
type="number"
placeholder="Age"
value={lover['age'] > 0 ? lover['age'] : undefined}
value={lover['age'] ?? undefined}
min={18}
max={100}
onChange={(e) => setLover('age', Number(e.target.value))}
@@ -236,12 +236,13 @@ export const OptionalLoveUserForm = (props: {
<Col>
<span>Min</span>
<Select
value={lover['pref_age_min']}
value={lover['pref_age_min'] ?? ''}
onChange={(e) =>
setLover('pref_age_min', Number(e.target.value))
}
className={'w-18 border-ink-300 rounded-md'}
>
<option key={""} value={""}></option>
{range(18, 100).map((m) => (
<option key={m} value={m}>
{m}
@@ -252,12 +253,13 @@ export const OptionalLoveUserForm = (props: {
<Col>
<span>Max</span>
<Select
value={lover['pref_age_max']}
value={lover['pref_age_max'] ?? ''}
onChange={(e) =>
setLover('pref_age_max', Number(e.target.value))
}
className={'w-18 border-ink-300 rounded-md'}
>
<option key={""} value={""}></option>
{range(18, 100).map((m) => (
<option key={m} value={m}>
{m}

View File

@@ -38,17 +38,17 @@ export function ProfilesHome() {
const [isLoadingMore, setIsLoadingMore] = useState(false);
const [isReloading, setIsReloading] = useState(false);
const [debouncedAgeRange, setRawAgeRange] = useState({
min: filters.pref_age_min ?? PREF_AGE_MIN,
max: filters.pref_age_max ?? PREF_AGE_MAX,
});
const debouncedSetAge = useCallback(debounce((state) => setRawAgeRange(state), 50), []);
useEffect(() => {
if (!user) return;
debouncedSetAge({min: filters.pref_age_min ?? PREF_AGE_MIN, max: filters.pref_age_max ?? PREF_AGE_MAX});
}, [filters.pref_age_min, filters.pref_age_max]);
// const [debouncedAgeRange, setRawAgeRange] = useState({
// min: filters.pref_age_min ?? PREF_AGE_MIN,
// max: filters.pref_age_max ?? PREF_AGE_MAX,
// });
//
// const debouncedSetAge = useCallback(debounce((state) => setRawAgeRange(state), 50), []);
//
// useEffect(() => {
// if (!user) return;
// debouncedSetAge({min: filters.pref_age_min ?? PREF_AGE_MIN, max: filters.pref_age_max ?? PREF_AGE_MAX});
// }, [filters.pref_age_min, filters.pref_age_max]);
const id = useRef(0);
useEffect(() => {
@@ -66,7 +66,7 @@ export function ProfilesHome() {
.finally(() => {
if (current === id.current) setIsReloading(false);
});
}, [JSON.stringify(omit(filters, ['pref_age_min', 'pref_age_max'])), debouncedAgeRange.min, debouncedAgeRange.max]);
}, [filters]);
const {data: starredUserIds, refresh: refreshStars} = useGetter('star', user?.id, getStars);
const compatibleLovers = useCompatibleLovers(user?.id);

View File

@@ -15,11 +15,11 @@ import {SignupBio} from "web/components/bio/editable-bio";
import {JSONContent} from "@tiptap/core";
export const initialRequiredState = {
age: 30,
age: undefined,
gender: '',
pref_gender: [],
pref_age_min: 18,
pref_age_max: 100,
pref_age_min: undefined,
pref_age_max: undefined,
pref_relation_styles: [],
wants_kids_strength: -1,
looking_for_matches: true,

View File

@@ -70,7 +70,7 @@ function formatFilters(filters: Partial<FilterFields>, location: locationType |
const entries: ReactElement[] = []
let ageEntry = null
let ageMin: number | undefined = filters.pref_age_min
let ageMin: number | undefined | null = filters.pref_age_min
if (ageMin == 18) ageMin = undefined
let ageMax = filters.pref_age_max;
if (ageMax == 99 || ageMax == 100) ageMax = undefined

View File

@@ -11,7 +11,7 @@ import SiteLogo from 'web/components/site-logo'
import {useTracking} from 'web/hooks/use-tracking'
import {track} from 'web/lib/service/analytics'
import {safeLocalStorage} from 'web/lib/util/local'
import {removeUndefinedProps} from 'common/util/object'
import {removeNullOrUndefinedProps} from 'common/util/object'
import {useLoverByUserId} from 'web/hooks/use-lover'
import {LoverRow} from 'common/love/lover'
import {LovePage} from "web/components/love-page";
@@ -94,7 +94,7 @@ export default function SignupPage() {
console.log('loverForm', loverForm)
const lover = await api(
'create-lover',
removeUndefinedProps({
removeNullOrUndefinedProps({
...loverForm,
referred_by_username: referredByUsername,
}) as any