Add profile fields: work areas, moral causes, and interests

This commit is contained in:
MartinBraquet
2025-12-03 16:56:02 +01:00
parent 43238ecc44
commit 3b0465c65c
31 changed files with 1134 additions and 109 deletions

View File

@@ -1,7 +1,7 @@
import {arraybeSchema, baseProfilesSchema, combinedProfileSchema, contentSchema, zBoolean,} from 'common/api/zod-types'
import {PrivateChatMessage} from 'common/chat-message'
import {CompatibilityScore} from 'common/profiles/compatibility-score'
import {MAX_COMPATIBILITY_QUESTION_LENGTH} from 'common/profiles/constants'
import {MAX_COMPATIBILITY_QUESTION_LENGTH, OPTION_TABLES} from 'common/profiles/constants'
import {Profile, ProfileRow} from 'common/profiles/profile'
import {Row} from 'common/supabase/utils'
import {PrivateUser, User} from 'common/user'
@@ -460,6 +460,9 @@ export const API = (_apiTypeCheck = {
diet: arraybeSchema.optional(),
political_beliefs: arraybeSchema.optional(),
mbti: arraybeSchema.optional(),
interests: arraybeSchema.optional(),
causes: arraybeSchema.optional(),
work: arraybeSchema.optional(),
relationship_status: arraybeSchema.optional(),
languages: arraybeSchema.optional(),
wants_kids_strength: z.coerce.number().optional(),
@@ -486,6 +489,33 @@ export const API = (_apiTypeCheck = {
summary: 'List profiles with filters, pagination and ordering',
tag: 'Profiles',
},
'get-options': {
method: 'GET',
authed: true,
rateLimited: true,
returns: {},
props: z
.object({
table: z.enum(OPTION_TABLES),
})
.strict(),
summary: 'Get profile options like interests',
tag: 'Profiles',
},
'update-options': {
method: 'POST',
authed: true,
rateLimited: true,
returns: {},
props: z
.object({
table: z.enum(OPTION_TABLES),
names: arraybeSchema.optional(),
})
.strict(),
summary: 'Update profile options like interests',
tag: 'Profiles',
},
'create-comment': {
method: 'POST',
authed: true,

View File

@@ -91,6 +91,9 @@ const optionalProfilesSchema = z.object({
occupation: z.string().optional().nullable(),
occupation_title: z.string().optional().nullable(),
political_beliefs: z.array(z.string()).optional().nullable(),
interests: z.array(z.string()).optional().nullable(),
work: z.array(z.string()).optional().nullable(),
causes: z.array(z.string()).optional().nullable(),
relationship_status: z.array(z.string()).optional().nullable(),
political_details: z.string().optional().nullable(),
pref_romantic_styles: z.array(z.string()).nullable(),

View File

@@ -1,6 +1,7 @@
import {Profile, ProfileRow} from "common/profiles/profile";
import {cloneDeep} from "lodash";
import {filterDefined} from "common/util/array";
import {OptionTableKey} from "common/profiles/constants";
// export type TargetArea = {
// lat: number
@@ -21,7 +22,10 @@ export type FilterFields = {
shortBio: boolean | undefined
drinks_min: number | undefined
drinks_max: number | undefined
} & Pick<
} & {
[K in OptionTableKey]: string[]
}
& Pick<
ProfileRow,
| 'wants_kids_strength'
| 'pref_relation_styles'
@@ -74,6 +78,9 @@ export const initialFilters: Partial<FilterFields> = {
pref_romantic_styles: undefined,
diet: undefined,
political_beliefs: undefined,
interests: undefined,
causes: undefined,
work: undefined,
relationship_status: undefined,
languages: undefined,
religion: undefined,

View File

@@ -1,7 +1,10 @@
import { isProd } from 'common/envs/is-prod'
import {isProd} from 'common/envs/is-prod'
export const compassUserId = isProd()
? 'tRZZ6ihugZQLXPf6aPRneGpWLmz1'
: 'RlXR2xa4EFfAzdCbSe45wkcdarh1'
export const MAX_COMPATIBILITY_QUESTION_LENGTH = 240
export const OPTION_TABLES = ['interests', 'causes', 'work'] as const
export type OptionTableKey = typeof OPTION_TABLES[number]

View File

@@ -1,10 +1,55 @@
import { Row, run, SupabaseClient } from 'common/supabase/utils'
import { User } from 'common/user'
import {Row, run, SupabaseClient} from 'common/supabase/utils'
import {User} from 'common/user'
import {OptionTableKey} from "common/profiles/constants";
export type ProfileRow = Row<'profiles'>
export type Profile = ProfileRow & { user: User }
export const getProfileRow = async (userId: string, db: SupabaseClient) => {
// console.debug('getProfileRow', userId)
const res = await run(db.from('profiles').select('*').eq('user_id', userId))
return res.data[0]
export type ProfileWithoutUser = ProfileRow & {[K in OptionTableKey]?: string[]}
export type Profile = ProfileWithoutUser & { user: User }
export const getProfileRow = async (userId: string, db: SupabaseClient): Promise<ProfileWithoutUser | null> => {
// Fetch profile
const profileRes = await run(
db
.from('profiles')
.select('*')
.eq('user_id', userId)
)
const profile = profileRes.data?.[0]
if (!profile) return null
// Fetch interests
const interestsRes = await run(
db
.from('profile_interests')
.select('interests(name)')
.eq('profile_id', profile.id)
)
const interests = interestsRes.data?.map((row: any) => row.interests.name) || []
// Fetch causes
const causesRes = await run(
db
.from('profile_causes')
.select('causes(name)')
.eq('profile_id', profile.id)
)
const causes = causesRes.data?.map((row: any) => row.causes.name) || []
// Fetch causes
const workRes = await run(
db
.from('profile_work')
.select('work(name)')
.eq('profile_id', profile.id)
)
const work = workRes.data?.map((row: any) => row.work.name) || []
// console.debug('work', work)
return {
...profile,
interests,
causes,
work,
}
}

View File

@@ -52,6 +52,32 @@ export type Database = {
},
]
}
causes: {
Row: {
creator_id: string | null
id: number
name: string
}
Insert: {
creator_id?: string | null
id?: never
name: string
}
Update: {
creator_id?: string | null
id?: never
name?: string
}
Relationships: [
{
foreignKeyName: 'causes_creator_id_fkey'
columns: ['creator_id']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
]
}
compatibility_answers: {
Row: {
created_time: string
@@ -243,6 +269,32 @@ export type Database = {
},
]
}
interests: {
Row: {
creator_id: string | null
id: number
name: string
}
Insert: {
creator_id?: string | null
id?: never
name: string
}
Update: {
creator_id?: string | null
id?: never
name?: string
}
Relationships: [
{
foreignKeyName: 'interests_creator_id_fkey'
columns: ['creator_id']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
]
}
private_user_message_channel_members: {
Row: {
channel_id: number
@@ -431,6 +483,39 @@ export type Database = {
},
]
}
profile_causes: {
Row: {
id: number
option_id: number
profile_id: number
}
Insert: {
id?: never
option_id: number
profile_id: number
}
Update: {
id?: never
option_id?: number
profile_id?: number
}
Relationships: [
{
foreignKeyName: 'profile_causes_option_id_fkey'
columns: ['option_id']
isOneToOne: false
referencedRelation: 'causes'
referencedColumns: ['id']
},
{
foreignKeyName: 'profile_causes_profile_id_fkey'
columns: ['profile_id']
isOneToOne: false
referencedRelation: 'profiles'
referencedColumns: ['id']
},
]
}
profile_comments: {
Row: {
content: Json
@@ -485,6 +570,39 @@ export type Database = {
},
]
}
profile_interests: {
Row: {
id: number
option_id: number
profile_id: number
}
Insert: {
id?: never
option_id: number
profile_id: number
}
Update: {
id?: never
option_id?: number
profile_id?: number
}
Relationships: [
{
foreignKeyName: 'profile_interests_option_id_fkey'
columns: ['option_id']
isOneToOne: false
referencedRelation: 'interests'
referencedColumns: ['id']
},
{
foreignKeyName: 'profile_interests_profile_id_fkey'
columns: ['profile_id']
isOneToOne: false
referencedRelation: 'profiles'
referencedColumns: ['id']
},
]
}
profile_likes: {
Row: {
created_time: string
@@ -582,6 +700,39 @@ export type Database = {
},
]
}
profile_work: {
Row: {
id: number
option_id: number
profile_id: number
}
Insert: {
id?: never
option_id: number
profile_id: number
}
Update: {
id?: never
option_id?: number
profile_id?: number
}
Relationships: [
{
foreignKeyName: 'profile_work_option_id_fkey'
columns: ['option_id']
isOneToOne: false
referencedRelation: 'work'
referencedColumns: ['id']
},
{
foreignKeyName: 'profile_work_profile_id_fkey'
columns: ['profile_id']
isOneToOne: false
referencedRelation: 'profiles'
referencedColumns: ['id']
},
]
}
profiles: {
Row: {
age: number | null
@@ -1077,6 +1228,32 @@ export type Database = {
},
]
}
work: {
Row: {
creator_id: string | null
id: number
name: string
}
Insert: {
creator_id?: string | null
id?: never
name: string
}
Update: {
creator_id?: string | null
id?: never
name?: string
}
Relationships: [
{
foreignKeyName: 'work_creator_id_fkey'
columns: ['creator_id']
isOneToOne: false
referencedRelation: 'users'
referencedColumns: ['id']
},
]
}
}
Views: {
[_ in never]: never