diff --git a/backend/api/src/get-profiles.ts b/backend/api/src/get-profiles.ts index ae919e78..beb6fd6c 100644 --- a/backend/api/src/get-profiles.ts +++ b/backend/api/src/get-profiles.ts @@ -89,7 +89,7 @@ export const loadProfiles = async (props: profileQueryType) => { const profiles = compatibleProfiles.filter( (l) => (!name || l.user.name.toLowerCase().includes(name.toLowerCase())) && - (!genders || genders.includes(l.gender)) && + (!genders || genders.includes(l.gender ?? '')) && (!education_levels || education_levels.includes(l.education_level ?? '')) && (!pref_gender || intersection(pref_gender, l.pref_gender).length) && (!pref_age_min || (l.age ?? MAX_INT) >= pref_age_min) && diff --git a/backend/shared/src/profiles/parse-photos.ts b/backend/shared/src/profiles/parse-photos.ts index 633407a2..77adc71a 100644 --- a/backend/shared/src/profiles/parse-photos.ts +++ b/backend/shared/src/profiles/parse-photos.ts @@ -1,6 +1,6 @@ export const removePinnedUrlFromPhotoUrls = async (parsedBody: { pinned_url?: string - photo_urls?: string[] + photo_urls?: string[] | null }) => { if (parsedBody.photo_urls && parsedBody.pinned_url) { parsedBody.photo_urls = parsedBody.photo_urls.filter( diff --git a/common/src/api/zod-types.ts b/common/src/api/zod-types.ts index 98cfc7d7..55256dd2 100644 --- a/common/src/api/zod-types.ts +++ b/common/src/api/zod-types.ts @@ -47,56 +47,56 @@ export const zBoolean = z .transform((val) => val === true || val === "true"); export const baseProfilesSchema = z.object({ - age: z.number().min(18).max(100).optional(), + age: z.number().min(18).max(100).optional().nullable(), bio: contentSchema.optional().nullable(), bio_length: z.number().optional().nullable(), city: z.string(), - city_latitude: z.number().optional(), - city_longitude: z.number().optional(), - country: z.string().optional(), + city_latitude: z.number().optional().nullable(), + city_longitude: z.number().optional().nullable(), + country: z.string().optional().nullable(), gender: genderType, - geodb_city_id: z.string().optional(), + geodb_city_id: z.string().optional().nullable(), looking_for_matches: zBoolean, - photo_urls: z.array(z.string()), + photo_urls: z.array(z.string()).nullable(), pinned_url: z.string(), - pref_age_max: z.number().min(18).max(100).optional(), - pref_age_min: z.number().min(18).max(100).optional(), - pref_gender: genderTypes, - pref_relation_styles: z.array(z.string()), - referred_by_username: z.string().optional(), - region_code: z.string().optional(), + pref_age_max: z.number().min(18).max(100).optional().nullable(), + pref_age_min: z.number().min(18).max(100).optional().nullable(), + pref_gender: genderTypes.nullable(), + pref_relation_styles: z.array(z.string()).nullable(), + referred_by_username: z.string().optional().nullable(), + region_code: z.string().optional().nullable(), visibility: z.union([z.literal('public'), z.literal('member')]), - wants_kids_strength: z.number(), + wants_kids_strength: z.number().nullable(), }) const optionalProfilesSchema = z.object({ - avatar_url: z.string().optional(), + avatar_url: z.string().optional().nullable(), bio: contentSchema.optional().nullable(), - born_in_location: z.string().optional(), + born_in_location: z.string().optional().nullable(), comments_enabled: zBoolean.optional(), - company: z.string().optional(), - diet: z.array(z.string()).optional(), + company: z.string().optional().nullable(), + diet: z.array(z.string()).optional().nullable(), disabled: zBoolean.optional(), - drinks_max: z.number().min(0).optional(), - drinks_min: z.number().min(0).optional(), - drinks_per_month: z.number().min(0).optional(), - education_level: z.string().optional(), - ethnicity: z.array(z.string()).optional(), - has_kids: z.number().min(0).optional(), - has_pets: zBoolean.optional(), - height_in_inches: z.number().optional(), - is_smoker: zBoolean.optional(), - occupation: z.string().optional(), - occupation_title: z.string().optional(), - political_beliefs: z.array(z.string()).optional(), - political_details: z.string().optional(), - pref_romantic_styles: z.array(z.string()), - religion: z.array(z.string()).optional(), - religious_belief_strength: z.number().optional(), - religious_beliefs: z.string().optional(), - twitter: z.string().optional(), - university: z.string().optional(), - website: z.string().optional(), + drinks_max: z.number().min(0).optional().nullable(), + drinks_min: z.number().min(0).optional().nullable(), + drinks_per_month: z.number().min(0).optional().nullable(), + education_level: z.string().optional().nullable(), + ethnicity: z.array(z.string()).optional().nullable(), + has_kids: z.number().min(0).optional().nullable(), + has_pets: zBoolean.optional().nullable(), + height_in_inches: z.number().optional().nullable(), + is_smoker: zBoolean.optional().nullable(), + occupation: z.string().optional().nullable(), + occupation_title: z.string().optional().nullable(), + political_beliefs: z.array(z.string()).optional().nullable(), + political_details: z.string().optional().nullable(), + pref_romantic_styles: z.array(z.string()).nullable(), + religion: z.array(z.string()).optional().nullable(), + religious_belief_strength: z.number().optional().nullable(), + religious_beliefs: z.string().optional().nullable(), + twitter: z.string().optional().nullable(), + university: z.string().optional().nullable(), + website: z.string().optional().nullable(), }) export const combinedProfileSchema = diff --git a/common/src/profiles/compatibility-util.ts b/common/src/profiles/compatibility-util.ts index 6bf33afc..ec15fc3c 100644 --- a/common/src/profiles/compatibility-util.ts +++ b/common/src/profiles/compatibility-util.ts @@ -2,15 +2,15 @@ import { ProfileRow } from 'common/profiles/profile' import {MAX_INT, MIN_INT} from "common/constants"; const isPreferredGender = ( - preferredGenders: string[] | undefined, - gender: string | undefined + preferredGenders: string[] | undefined | null, + gender: string | undefined | null, ) => { // console.debug('isPreferredGender', preferredGenders, gender) - if (preferredGenders === undefined || preferredGenders.length === 0 || gender === undefined) return true + if (!preferredGenders?.length || !gender) return true // If simple gender preference, don't include non-binary. if ( - preferredGenders.length === 1 && + preferredGenders?.length === 1 && (preferredGenders[0] === 'male' || preferredGenders[0] === 'female') ) { return preferredGenders.includes(gender) @@ -43,13 +43,15 @@ export const areLocationCompatible = (profile1: ProfileRow, profile2: ProfileRow !profile2.city_latitude || !profile1.city_longitude || !profile2.city_longitude - ) + ) { + if (!profile1.city || !profile2.city) return true return profile1.city.trim().toLowerCase() === profile2.city.trim().toLowerCase() + } const latitudeDiff = Math.abs(profile1.city_latitude - profile2.city_latitude) - const longigudeDiff = Math.abs(profile1.city_longitude - profile2.city_longitude) + const longitudeDiff = Math.abs(profile1.city_longitude - profile2.city_longitude) - const root = (latitudeDiff ** 2 + longigudeDiff ** 2) ** 0.5 + const root = (latitudeDiff ** 2 + longitudeDiff ** 2) ** 0.5 return root < 2.5 } @@ -57,8 +59,9 @@ export const areRelationshipStyleCompatible = ( profile1: ProfileRow, profile2: ProfileRow ) => { + if (!profile1.pref_relation_styles?.length || !profile2.pref_relation_styles) return true return profile1.pref_relation_styles.some((style) => - profile2.pref_relation_styles.includes(style) + profile2.pref_relation_styles?.includes(style) ) } @@ -66,7 +69,7 @@ export const areWantKidsCompatible = (profile1: ProfileRow, profile2: ProfileRow const { wants_kids_strength: kids1 } = profile1 const { wants_kids_strength: kids2 } = profile2 - if (kids1 === undefined || kids2 === undefined) return true + if (kids1 == null || kids2 == null) return true const diff = Math.abs(kids1 - kids2) return diff <= 2 diff --git a/common/src/supabase/schema.ts b/common/src/supabase/schema.ts index 8c1c50c3..364e1752 100644 --- a/common/src/supabase/schema.ts +++ b/common/src/supabase/schema.ts @@ -533,7 +533,7 @@ export type Database = { bio_text: string | null bio_tsv: unknown born_in_location: string | null - city: string + city: string | null city_latitude: number | null city_longitude: number | null comments_enabled: boolean @@ -545,7 +545,7 @@ export type Database = { drinks_per_month: number | null education_level: string | null ethnicity: string[] | null - gender: string + gender: string | null geodb_city_id: string | null has_kids: number | null height_in_inches: number | null @@ -562,8 +562,8 @@ export type Database = { political_details: string | null pref_age_max: number | null pref_age_min: number | null - pref_gender: string[] - pref_relation_styles: string[] + pref_gender: string[] | null + pref_relation_styles: string[] | null pref_romantic_styles: string[] | null referred_by_username: string | null region_code: string | null @@ -574,7 +574,7 @@ export type Database = { university: string | null user_id: string visibility: Database['public']['Enums']['lover_visibility'] - wants_kids_strength: number + wants_kids_strength: number | null website: string | null } Insert: { @@ -584,7 +584,7 @@ export type Database = { bio_text?: string | null bio_tsv?: unknown born_in_location?: string | null - city: string + city?: string | null city_latitude?: number | null city_longitude?: number | null comments_enabled?: boolean @@ -596,7 +596,7 @@ export type Database = { drinks_per_month?: number | null education_level?: string | null ethnicity?: string[] | null - gender: string + gender?: string | null geodb_city_id?: string | null has_kids?: number | null height_in_inches?: number | null @@ -613,8 +613,8 @@ export type Database = { political_details?: string | null pref_age_max?: number | null pref_age_min?: number | null - pref_gender: string[] - pref_relation_styles: string[] + pref_gender?: string[] | null + pref_relation_styles?: string[] | null pref_romantic_styles?: string[] | null referred_by_username?: string | null region_code?: string | null @@ -625,7 +625,7 @@ export type Database = { university?: string | null user_id: string visibility?: Database['public']['Enums']['lover_visibility'] - wants_kids_strength?: number + wants_kids_strength?: number | null website?: string | null } Update: { @@ -635,7 +635,7 @@ export type Database = { bio_text?: string | null bio_tsv?: unknown born_in_location?: string | null - city?: string + city?: string | null city_latitude?: number | null city_longitude?: number | null comments_enabled?: boolean @@ -647,7 +647,7 @@ export type Database = { drinks_per_month?: number | null education_level?: string | null ethnicity?: string[] | null - gender?: string + gender?: string | null geodb_city_id?: string | null has_kids?: number | null height_in_inches?: number | null @@ -664,8 +664,8 @@ export type Database = { political_details?: string | null pref_age_max?: number | null pref_age_min?: number | null - pref_gender?: string[] - pref_relation_styles?: string[] + pref_gender?: string[] | null + pref_relation_styles?: string[] | null pref_romantic_styles?: string[] | null referred_by_username?: string | null region_code?: string | null @@ -676,7 +676,7 @@ export type Database = { university?: string | null user_id?: string visibility?: Database['public']['Enums']['lover_visibility'] - wants_kids_strength?: number + wants_kids_strength?: number | null website?: string | null } Relationships: [ diff --git a/web/components/optional-profile-form.tsx b/web/components/optional-profile-form.tsx index 425cca2d..b3e91dc2 100644 --- a/web/components/optional-profile-form.tsx +++ b/web/components/optional-profile-form.tsx @@ -17,7 +17,7 @@ import {Races} from './race' import {Carousel} from 'web/components/widgets/carousel' import {tryCatch} from 'common/util/try-catch' import {ProfileRow} from 'common/profiles/profile' -import {removeNullOrUndefinedProps} from 'common/util/object' +import {removeUndefinedProps} from 'common/util/object' import {isEqual, range} from 'lodash' import {PlatformSelect} from 'web/components/widgets/platform-select' import {PLATFORM_LABELS, type Site, SITE_ORDER} from 'common/socials' @@ -32,7 +32,8 @@ import { DIET_CHOICES, EDUCATION_CHOICES, POLITICAL_CHOICES, - RELATIONSHIP_CHOICES, RELIGION_CHOICES, + RELATIONSHIP_CHOICES, + RELIGION_CHOICES, ROMANTIC_CHOICES } from "web/components/filters/choices"; import toast from "react-hot-toast"; @@ -70,10 +71,10 @@ export const OptionalProfileUserForm = (props: { const handleSubmit = async () => { setIsSubmitting(true) - const {bio: _, ...otherProfileProps} = profile - console.debug('otherProfileProps', removeNullOrUndefinedProps(otherProfileProps)) + const {bio: _bio, bio_text: _bio_text, bio_tsv: _bio_tsv, bio_length: _bio_length, ...otherProfileProps} = profile + console.debug('otherProfileProps', removeUndefinedProps(otherProfileProps)) const {error} = await tryCatch( - updateProfile(removeNullOrUndefinedProps(otherProfileProps) as any) + updateProfile(removeUndefinedProps(otherProfileProps) as any) ) if (error) { console.error(error) diff --git a/web/components/profile/profile-header.tsx b/web/components/profile/profile-header.tsx index 72da7b10..7325212b 100644 --- a/web/components/profile/profile-header.tsx +++ b/web/components/profile/profile-header.tsx @@ -55,9 +55,9 @@ export default function ProfileHeader(props: { return ( - {currentUser && isCurrentUser && disabled &&
You disabled your profile, so no one else can access it.
} + {currentUser && isCurrentUser && disabled &&
You disabled your profile, so no one else can access it.
} {!isCurrentUser && }