Rename lover -> profile

This commit is contained in:
MartinBraquet
2025-09-17 15:51:19 +02:00
parent 593617c0ff
commit ea18781cc6
86 changed files with 601 additions and 746 deletions

View File

@@ -12,11 +12,11 @@ import {blockUser, unblockUser} from './block-user'
import {getCompatibleProfilesHandler} from './compatible-profiles'
import {createComment} from './create-comment'
import {createCompatibilityQuestion} from './create-compatibility-question'
import {createProfile} from './create-lover'
import {createProfile} from './create-profile'
import {createUser} from './create-user'
import {getCompatibilityQuestions} from './get-compatibililty-questions'
import {getLikesAndShips} from './get-likes-and-ships'
import {getProfileAnswers} from './get-lover-answers'
import {getProfileAnswers} from './get-profile-answers'
import {getProfiles} from './get-profiles'
import {getSupabaseToken} from './get-supabase-token'
import {getDisplayUser, getUser} from './get-user'
@@ -25,15 +25,15 @@ import {hasFreeLike} from './has-free-like'
import {health} from './health'
import {type APIHandler, typedEndpoint} from './helpers/endpoint'
import {hideComment} from './hide-comment'
import {likeProfile} from './like-lover'
import {likeProfile} from './like-profile'
import {markAllNotifsRead} from './mark-all-notifications-read'
import {removePinnedPhoto} from './remove-pinned-photo'
import {report} from './report'
import {searchLocation} from './search-location'
import {searchNearCity} from './search-near-city'
import {shipProfiles} from './ship-profiles'
import {starProfile} from './star-lover'
import {updateProfile} from './update-lover'
import {starProfile} from './star-profile'
import {updateProfile} from './update-profile'
import {updateMe} from './update-me'
import {deleteMe} from './delete-me'
import {getCurrentPrivateUser} from './get-current-private-user'
@@ -134,20 +134,20 @@ const handlers: { [k in APIPath]: APIHandler<k> } = {
'ban-user': banUser,
report: report,
'create-user': createUser,
'create-lover': createProfile,
'create-profile': createProfile,
me: getMe,
'me/private': getCurrentPrivateUser,
'me/update': updateMe,
'update-notif-settings': updateNotifSettings,
'me/delete': deleteMe,
'update-lover': updateProfile,
'like-lover': likeProfile,
'update-profile': updateProfile,
'like-profile': likeProfile,
'ship-profiles': shipProfiles,
'get-likes-and-ships': getLikesAndShips,
'has-free-like': hasFreeLike,
'star-lover': starProfile,
'star-profile': starProfile,
'get-profiles': getProfiles,
'get-lover-answers': getProfileAnswers,
'get-profile-answers': getProfileAnswers,
'get-compatibility-questions': getCompatibilityQuestions,
'remove-pinned-photo': removePinnedPhoto,
'create-comment': createComment,

View File

@@ -15,32 +15,32 @@ export const getCompatibleProfilesHandler: APIHandler<
}
export const getCompatibleProfiles = async (userId: string) => {
const lover = await getProfile(userId)
const profile = await getProfile(userId)
log('got lover', {
id: lover?.id,
userId: lover?.user_id,
username: lover?.user?.username,
log('got profile', {
id: profile?.id,
userId: profile?.user_id,
username: profile?.user?.username,
})
if (!lover) throw new APIError(404, 'Profile not found')
if (!profile) throw new APIError(404, 'Profile not found')
const profiles = await getGenderCompatibleProfiles(lover)
const profiles = await getGenderCompatibleProfiles(profile)
const loverAnswers = await getCompatibilityAnswers([
const profileAnswers = await getCompatibilityAnswers([
userId,
...profiles.map((l) => l.user_id),
])
log('got lover answers ' + loverAnswers.length)
log('got profile answers ' + profileAnswers.length)
const answersByUserId = groupBy(loverAnswers, 'creator_id')
const loverCompatibilityScores = Object.fromEntries(
const answersByUserId = groupBy(profileAnswers, 'creator_id')
const profileCompatibilityScores = Object.fromEntries(
profiles.map(
(l) =>
[
l.user_id,
getCompatibilityScore(
answersByUserId[lover.user_id] ?? [],
answersByUserId[profile.user_id] ?? [],
answersByUserId[l.user_id] ?? []
),
] as const
@@ -49,13 +49,13 @@ export const getCompatibleProfiles = async (userId: string) => {
const sortedCompatibleProfiles = sortBy(
profiles,
(l) => loverCompatibilityScores[l.user_id].score
(l) => profileCompatibilityScores[l.user_id].score
).reverse()
return {
status: 'success',
lover,
profile,
compatibleProfiles: sortedCompatibleProfiles,
loverCompatibilityScores,
profileCompatibilityScores,
}
}

View File

@@ -32,8 +32,8 @@ export const createComment: APIHandler<'create-comment'> = async (
if (!onUser) throw new APIError(404, 'User not found')
const pg = createSupabaseDirectClient()
const comment = await pg.one<Row<'lover_comments'>>(
`insert into lover_comments (user_id, user_name, user_username, user_avatar_url, on_user_id, content, reply_to_comment_id)
const comment = await pg.one<Row<'profile_comments'>>(
`insert into profile_comments (user_id, user_name, user_username, user_avatar_url, on_user_id, content, reply_to_comment_id)
values ($1, $2, $3, $4, $5, $6, $7) returning *`,
[
creator.id,
@@ -104,7 +104,7 @@ const createNewCommentOnProfileNotification = async (
createdTime: Date.now(),
isSeen: false,
sourceId: commentId.toString(),
sourceType: 'comment_on_lover',
sourceType: 'comment_on_profile',
sourceUpdateType: 'created',
sourceUserName: creator.name,
sourceUserUsername: creator.username,

View File

@@ -8,7 +8,7 @@ import { updateUser } from 'shared/supabase/users'
import { tryCatch } from 'common/util/try-catch'
import { insert } from 'shared/supabase/utils'
export const createProfile: APIHandler<'create-lover'> = async (body, auth) => {
export const createProfile: APIHandler<'create-profile'> = async (body, auth) => {
const pg = createSupabaseDirectClient()
const { data: existingUser } = await tryCatch(
@@ -40,7 +40,7 @@ export const createProfile: APIHandler<'create-lover'> = async (body, auth) => {
}
log('Created user', data)
await track(user.id, 'create lover', { username: user.username })
await track(user.id, 'create profile', { username: user.username })
return data
}

View File

@@ -123,7 +123,7 @@ export const createUser: APIHandler<'create-user'> = async (
log('created user ', { username: user.username, firebaseId: auth.uid })
const continuation = async () => {
await track(auth.uid, 'create lover', { username: user.username })
await track(auth.uid, 'create profile', { username: user.username })
}
return {

View File

@@ -2,7 +2,7 @@ import { type APIHandler } from 'api/helpers/endpoint'
import { createSupabaseDirectClient } from 'shared/supabase/init'
import { Row } from 'common/supabase/utils'
export const getProfileAnswers: APIHandler<'get-lover-answers'> = async (
export const getProfileAnswers: APIHandler<'get-profile-answers'> = async (
props,
_auth
) => {

View File

@@ -10,8 +10,8 @@ export const hideComment: APIHandler<'hide-comment'> = async (
auth
) => {
const pg = createSupabaseDirectClient()
const comment = await pg.oneOrNone<Row<'lover_comments'>>(
`select * from lover_comments where id = $1`,
const comment = await pg.oneOrNone<Row<'profile_comments'>>(
`select * from profile_comments where id = $1`,
[commentId]
)
if (!comment) {
@@ -26,7 +26,7 @@ export const hideComment: APIHandler<'hide-comment'> = async (
throw new APIError(403, 'You are not allowed to hide this comment')
}
await pg.none(`update lover_comments set hidden = $2 where id = $1`, [
await pg.none(`update profile_comments set hidden = $2 where id = $1`, [
commentId,
hide,
])

View File

@@ -6,7 +6,7 @@ import { log } from 'shared/utils'
import { tryCatch } from 'common/util/try-catch'
import { Row } from 'common/supabase/utils'
export const likeProfile: APIHandler<'like-lover'> = async (props, auth) => {
export const likeProfile: APIHandler<'like-profile'> = async (props, auth) => {
const { targetUserId, remove } = props
const creatorId = auth.uid

View File

@@ -5,7 +5,7 @@ import { tryCatch } from 'common/util/try-catch'
import { Row } from 'common/supabase/utils'
import { insert } from 'shared/supabase/utils'
export const starProfile: APIHandler<'star-lover'> = async (props, auth) => {
export const starProfile: APIHandler<'star-profile'> = async (props, auth) => {
const { targetUserId, remove } = props
const creatorId = auth.uid

View File

@@ -7,7 +7,7 @@ import { tryCatch } from 'common/util/try-catch'
import { update } from 'shared/supabase/utils'
import { type Row } from 'common/supabase/utils'
export const updateProfile: APIHandler<'update-lover'> = async (
export const updateProfile: APIHandler<'update-profile'> = async (
parsedBody,
auth
) => {
@@ -25,7 +25,7 @@ export const updateProfile: APIHandler<'update-lover'> = async (
}
!parsedBody.last_online_time &&
log('Updating lover', { userId: auth.uid, parsedBody })
log('Updating profile', { userId: auth.uid, parsedBody })
await removePinnedUrlFromPhotoUrls(parsedBody)
if (parsedBody.avatar_url) {
@@ -37,8 +37,8 @@ export const updateProfile: APIHandler<'update-lover'> = async (
)
if (error) {
log('Error updating lover', error)
throw new APIError(500, 'Error updating lover')
log('Error updating profile', error)
throw new APIError(500, 'Error updating profile')
}
return data

View File

@@ -20,8 +20,8 @@ const from = 'Compass <no-reply@compassmeet.com>'
// 'new_match'
// )
// if (!privateUser.email || !sendToEmail) return
// const lover = await getProfile(privateUser.id)
// if (!lover) return
// const profile = await getProfile(privateUser.id)
// if (!profile) return
//
// return await sendEmail({
// from,
@@ -29,10 +29,10 @@ const from = 'Compass <no-reply@compassmeet.com>'
// to: privateUser.email,
// react: (
// <NewMatchEmail
// onUser={lover.user}
// onUser={profile.user}
// email={privateUser.email}
// matchedWithUser={matchedWithUser}
// matchedProfile={lover}
// matchedProfile={profile}
// unsubscribeUrl={unsubscribeUrl}
// />
// ),
@@ -51,9 +51,9 @@ export const sendNewMessageEmail = async (
)
if (!privateUser.email || !sendToEmail) return
const lover = await getProfile(fromUser.id)
const profile = await getProfile(fromUser.id)
if (!lover) {
if (!profile) {
console.error('Could not send email notification: User not found')
return
}
@@ -65,7 +65,7 @@ export const sendNewMessageEmail = async (
html: await render(
<NewMessageEmail
fromUser={fromUser}
fromUserProfile={lover}
fromUserProfile={profile}
toUser={toUser}
channelId={channelId}
unsubscribeUrl={unsubscribeUrl}

View File

@@ -1,4 +1,4 @@
import { ProfileRow } from 'common/love/lover'
import { ProfileRow } from 'common/love/profile'
import type { User } from 'common/user'
// for email template testing

View File

@@ -1,6 +1,6 @@
import {Body, Button, Container, Head, Html, Preview, Section, Text,} from '@react-email/components'
import {DOMAIN} from 'common/envs/constants'
import {type ProfileRow} from 'common/love/lover'
import {type ProfileRow} from 'common/love/profile'
import {type User} from 'common/user'
import {jamesProfile, jamesUser, sinclairUser} from './functions/mock'
import {Footer} from "email/utils";

View File

@@ -11,7 +11,7 @@ import {
Text,
} from '@react-email/components'
import { type User } from 'common/user'
import { type ProfileRow } from 'common/love/lover'
import { type ProfileRow } from 'common/love/profile'
import {
jamesProfile,
jamesUser,

View File

@@ -27,7 +27,7 @@ const getNodes = async (pg: SupabaseDirectClient, nodeName: string) => {
console.log(`\nSearching comments for ${nodeName}...`)
const commentQuery = renderSql(
select('id, user_id, on_user_id, content'),
from('lover_comments'),
from('profile_comments'),
where(`jsonb_path_exists(content, '$.**.type ? (@ == "${nodeName}")')`)
)
const comments = await pg.manyOrNone(commentQuery)

View File

@@ -33,7 +33,7 @@ runScript(async ({ pg }) => {
console.log('\nSearching comments for linkPreviews...')
const commentQuery = renderSql(
select('id, content'),
from('lover_comments'),
from('profile_comments'),
where(`jsonb_path_exists(content, '$.**.type ? (@ == "${nodeType}")')`)
)
const comments = await pg.manyOrNone(commentQuery)
@@ -45,7 +45,7 @@ runScript(async ({ pg }) => {
console.log('before', comment.content)
console.log('after', newContent)
await pg.none('update lover_comments set content = $1 where id = $2', [
await pg.none('update profile_comments set content = $1 where id = $2', [
newContent,
comment.id,
])

View File

@@ -10,9 +10,9 @@ export const createLoveLikeNotification = async (like: Row<'love_likes'>) => {
const { creator_id, target_id, like_id } = like
const targetPrivateUser = await getPrivateUser(target_id)
const lover = await getProfile(creator_id)
const profile = await getProfile(creator_id)
if (!targetPrivateUser || !lover) return
if (!targetPrivateUser || !profile) return
const { sendToBrowser } = getNotificationDestinationsForUser(
targetPrivateUser,
@@ -30,9 +30,9 @@ export const createLoveLikeNotification = async (like: Row<'love_likes'>) => {
sourceId: like_id,
sourceType: 'love_like',
sourceUpdateType: 'created',
sourceUserName: lover.user.name,
sourceUserUsername: lover.user.username,
sourceUserAvatarUrl: lover.pinned_url ?? lover.user.avatarUrl,
sourceUserName: profile.user.name,
sourceUserUsername: profile.user.username,
sourceUserAvatarUrl: profile.pinned_url ?? profile.user.avatarUrl,
sourceText: '',
}
const pg = createSupabaseDirectClient()
@@ -48,13 +48,13 @@ export const createLoveShipNotification = async (
const creator = await getUser(creator_id)
const targetPrivateUser = await getPrivateUser(recipientId)
const lover = await getProfile(otherTargetId)
const profile = await getProfile(otherTargetId)
if (!creator || !targetPrivateUser || !lover) {
if (!creator || !targetPrivateUser || !profile) {
console.error('Could not load user object', {
creator,
targetPrivateUser,
lover,
profile,
})
return
}
@@ -75,9 +75,9 @@ export const createLoveShipNotification = async (
sourceId: ship_id,
sourceType: 'love_ship',
sourceUpdateType: 'created',
sourceUserName: lover.user.name,
sourceUserUsername: lover.user.username,
sourceUserAvatarUrl: lover.pinned_url ?? lover.user.avatarUrl,
sourceUserName: profile.user.name,
sourceUserUsername: profile.user.username,
sourceUserAvatarUrl: profile.pinned_url ?? profile.user.avatarUrl,
sourceText: '',
data: {
creatorId: creator_id,

View File

@@ -1,5 +1,5 @@
import { areGenderCompatible } from 'common/love/compatibility-util'
import { type Profile, type ProfileRow } from 'common/love/lover'
import { type Profile, type ProfileRow } from 'common/love/profile'
import { type User } from 'common/user'
import { Row } from 'common/supabase/utils'
import { createSupabaseDirectClient } from 'shared/supabase/init'
@@ -58,7 +58,7 @@ export const getProfiles = async (userIds: string[]) => {
)
}
export const getGenderCompatibleProfiles = async (lover: ProfileRow) => {
export const getGenderCompatibleProfiles = async (profile: ProfileRow) => {
const pg = createSupabaseDirectClient()
const profiles = await pg.map(
`
@@ -74,14 +74,14 @@ export const getGenderCompatibleProfiles = async (lover: ProfileRow) => {
and (data->>'userDeleted' != 'true' or data->>'userDeleted' is null)
and profiles.pinned_url is not null
`,
{ ...lover },
{ ...profile },
convertRow
)
return profiles.filter((l: Profile) => areGenderCompatible(lover, l))
return profiles.filter((l: Profile) => areGenderCompatible(profile, l))
}
export const getCompatibleProfiles = async (
lover: ProfileRow,
profile: ProfileRow,
radiusKm: number | undefined
) => {
const pg = createSupabaseDirectClient()
@@ -111,7 +111,7 @@ export const getCompatibleProfiles = async (
-- Location
and calculate_earth_distance_km($(city_latitude), $(city_longitude), profiles.city_latitude, profiles.city_longitude) < $(radiusKm)
`,
{ ...lover, radiusKm: radiusKm ?? 40_000 },
{ ...profile, radiusKm: radiusKm ?? 40_000 },
convertRow
)
}

View File

@@ -9,7 +9,7 @@ BEGIN;
\i backend/supabase/private_user_messages.sql
\i backend/supabase/private_user_seen_message_channels.sql
\i backend/supabase/love_answers.sql
\i backend/supabase/lover_comments.sql
\i backend/supabase/profile_comments.sql
\i backend/supabase/love_compatibility_answers.sql
\i backend/supabase/love_likes.sql
\i backend/supabase/love_questions.sql

View File

@@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS lover_comments (
CREATE TABLE IF NOT EXISTS profile_comments (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
content JSONB NOT NULL,
created_time TIMESTAMPTZ DEFAULT now() NOT NULL,
@@ -12,12 +12,12 @@ CREATE TABLE IF NOT EXISTS lover_comments (
);
-- Row Level Security
ALTER TABLE lover_comments ENABLE ROW LEVEL SECURITY;
ALTER TABLE profile_comments ENABLE ROW LEVEL SECURITY;
-- Policies
DROP POLICY IF EXISTS "public read" ON lover_comments;
CREATE POLICY "public read" ON lover_comments FOR ALL USING (true);
DROP POLICY IF EXISTS "public read" ON profile_comments;
CREATE POLICY "public read" ON profile_comments FOR ALL USING (true);
-- Indexes
CREATE INDEX IF NOT EXISTS lover_comments_user_id_idx
ON public.lover_comments USING btree (on_user_id);
CREATE INDEX IF NOT EXISTS profile_comments_user_id_idx
ON public.profile_comments USING btree (on_user_id);

View File

@@ -1,8 +1,8 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'lover_visibility') THEN
CREATE TYPE lover_visibility AS ENUM ('public', 'member');
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'profile_visibility') THEN
CREATE TYPE profile_visibility AS ENUM ('public', 'member');
END IF;
END$$;
@@ -47,7 +47,7 @@ CREATE TABLE IF NOT EXISTS profiles (
twitter TEXT,
university TEXT,
user_id TEXT NOT NULL,
visibility lover_visibility DEFAULT 'member'::lover_visibility NOT NULL,
visibility profile_visibility DEFAULT 'member'::profile_visibility NOT NULL,
wants_kids_strength INTEGER DEFAULT 0 NOT NULL,
website TEXT,
CONSTRAINT profiles_pkey PRIMARY KEY (id)

View File

@@ -7,7 +7,7 @@ import {
import { PrivateChatMessage } from 'common/chat-message'
import { CompatibilityScore } from 'common/love/compatibility-score'
import { MAX_COMPATIBILITY_QUESTION_LENGTH } from 'common/love/constants'
import { Profile, ProfileRow } from 'common/love/lover'
import { Profile, ProfileRow } from 'common/love/profile'
import { Row } from 'common/supabase/utils'
import { PrivateUser, User } from 'common/user'
import { z } from 'zod'
@@ -88,7 +88,7 @@ export const API = (_apiTypeCheck = {
})
.strict(),
},
'create-lover': {
'create-profile': {
method: 'POST',
authed: true,
returns: {} as Row<'profiles'>,
@@ -143,7 +143,7 @@ export const API = (_apiTypeCheck = {
}),
returns: {} as FullUser,
},
'update-lover': {
'update-profile': {
method: 'POST',
authed: true,
props: combinedLoveUsersSchema.partial(),
@@ -217,9 +217,9 @@ export const API = (_apiTypeCheck = {
authed: false,
props: z.object({ userId: z.string() }),
returns: {} as {
lover: Profile
profile: Profile
compatibleProfiles: Profile[]
loverCompatibilityScores: {
profileCompatibilityScores: {
[userId: string]: CompatibilityScore
}
},
@@ -246,7 +246,7 @@ export const API = (_apiTypeCheck = {
})[]
},
},
'like-lover': {
'like-profile': {
method: 'POST',
authed: true,
props: z.object({
@@ -293,7 +293,7 @@ export const API = (_apiTypeCheck = {
hasFreeLike: boolean
},
},
'star-lover': {
'star-profile': {
method: 'POST',
authed: true,
props: z.object({
@@ -334,7 +334,7 @@ export const API = (_apiTypeCheck = {
profiles: Profile[]
},
},
'get-lover-answers': {
'get-profile-answers': {
method: 'GET',
authed: false,
props: z.object({ userId: z.string() }).strict(),

View File

@@ -11,8 +11,8 @@ export type Comment = {
replyToCommentId?: string
userId: string
// lover
commentType: 'lover'
// profile
commentType: 'profile'
onUserId: string
/** @deprecated - content now stored as JSON in content*/

View File

@@ -1,4 +1,4 @@
import {Profile, ProfileRow} from "common/love/lover";
import {Profile, ProfileRow} from "common/love/profile";
import {cloneDeep} from "lodash";
import {filterDefined} from "common/util/array";

View File

@@ -1,5 +1,5 @@
import { keyBy, sumBy } from 'lodash'
import { ProfileRow } from 'common/love/lover'
import { ProfileRow } from 'common/love/profile'
import { Row as rowFor } from 'common/supabase/utils'
import {
areAgeCompatible,
@@ -133,13 +133,13 @@ export function getScoredAnswerCompatibility(
}
export const getProfilesCompatibilityFactor = (
lover1: ProfileRow,
lover2: ProfileRow
profile1: ProfileRow,
profile2: ProfileRow
) => {
let multiplier = 1
multiplier *= areAgeCompatible(lover1, lover2) ? 1 : 0.5
multiplier *= areRelationshipStyleCompatible(lover1, lover2) ? 1 : 0.5
multiplier *= areWantKidsCompatible(lover1, lover2) ? 1 : 0.5
multiplier *= areLocationCompatible(lover1, lover2) ? 1 : 0.1
multiplier *= areAgeCompatible(profile1, profile2) ? 1 : 0.5
multiplier *= areRelationshipStyleCompatible(profile1, profile2) ? 1 : 0.5
multiplier *= areWantKidsCompatible(profile1, profile2) ? 1 : 0.5
multiplier *= areLocationCompatible(profile1, profile2) ? 1 : 0.1
return multiplier
}

View File

@@ -1,4 +1,4 @@
import { ProfileRow } from 'common/love/lover'
import { ProfileRow } from 'common/love/profile'
import {MAX_INT, MIN_INT} from "common/constants";
const isPreferredGender = (
@@ -18,53 +18,53 @@ const isPreferredGender = (
return preferredGenders.includes(gender) || gender === 'non-binary'
}
export const areGenderCompatible = (lover1: ProfileRow, lover2: ProfileRow) => {
// console.log('areGenderCompatible', isPreferredGender(lover1.pref_gender, lover2.gender), isPreferredGender(lover2.pref_gender, lover1.gender))
export const areGenderCompatible = (profile1: ProfileRow, profile2: ProfileRow) => {
// console.log('areGenderCompatible', isPreferredGender(profile1.pref_gender, profile2.gender), isPreferredGender(profile2.pref_gender, profile1.gender))
return (
isPreferredGender(lover1.pref_gender, lover2.gender) &&
isPreferredGender(lover2.pref_gender, lover1.gender)
isPreferredGender(profile1.pref_gender, profile2.gender) &&
isPreferredGender(profile2.pref_gender, profile1.gender)
)
}
const satisfiesAgeRange = (lover: ProfileRow, age: number | null | undefined) => {
return (age ?? MAX_INT) >= (lover.pref_age_min ?? MIN_INT) && (age ?? MIN_INT) <= (lover.pref_age_max ?? MAX_INT)
const satisfiesAgeRange = (profile: ProfileRow, age: number | null | undefined) => {
return (age ?? MAX_INT) >= (profile.pref_age_min ?? MIN_INT) && (age ?? MIN_INT) <= (profile.pref_age_max ?? MAX_INT)
}
export const areAgeCompatible = (lover1: ProfileRow, lover2: ProfileRow) => {
export const areAgeCompatible = (profile1: ProfileRow, profile2: ProfileRow) => {
return (
satisfiesAgeRange(lover1, lover2.age) &&
satisfiesAgeRange(lover2, lover1.age)
satisfiesAgeRange(profile1, profile2.age) &&
satisfiesAgeRange(profile2, profile1.age)
)
}
export const areLocationCompatible = (lover1: ProfileRow, lover2: ProfileRow) => {
export const areLocationCompatible = (profile1: ProfileRow, profile2: ProfileRow) => {
if (
!lover1.city_latitude ||
!lover2.city_latitude ||
!lover1.city_longitude ||
!lover2.city_longitude
!profile1.city_latitude ||
!profile2.city_latitude ||
!profile1.city_longitude ||
!profile2.city_longitude
)
return lover1.city.trim().toLowerCase() === lover2.city.trim().toLowerCase()
return profile1.city.trim().toLowerCase() === profile2.city.trim().toLowerCase()
const latitudeDiff = Math.abs(lover1.city_latitude - lover2.city_latitude)
const longigudeDiff = Math.abs(lover1.city_longitude - lover2.city_longitude)
const latitudeDiff = Math.abs(profile1.city_latitude - profile2.city_latitude)
const longigudeDiff = Math.abs(profile1.city_longitude - profile2.city_longitude)
const root = (latitudeDiff ** 2 + longigudeDiff ** 2) ** 0.5
return root < 2.5
}
export const areRelationshipStyleCompatible = (
lover1: ProfileRow,
lover2: ProfileRow
profile1: ProfileRow,
profile2: ProfileRow
) => {
return lover1.pref_relation_styles.some((style) =>
lover2.pref_relation_styles.includes(style)
return profile1.pref_relation_styles.some((style) =>
profile2.pref_relation_styles.includes(style)
)
}
export const areWantKidsCompatible = (lover1: ProfileRow, lover2: ProfileRow) => {
const { wants_kids_strength: kids1 } = lover1
const { wants_kids_strength: kids2 } = lover2
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

View File

@@ -1,5 +1,5 @@
import { User } from 'common/user'
import { ProfileRow } from 'common/love/lover'
import { ProfileRow } from 'common/love/profile'
import { buildOgUrl } from 'common/util/og'
// TODO: handle age, gender undefined better
@@ -8,21 +8,21 @@ export type LoveOgProps = {
avatarUrl: string
username: string
name: string
// lover props
// profile props
age: string
city: string
gender: string
}
export function getLoveOgImageUrl(user: User, lover?: ProfileRow | null) {
export function getLoveOgImageUrl(user: User, profile?: ProfileRow | null) {
const loveProps = {
avatarUrl: lover?.pinned_url,
avatarUrl: profile?.pinned_url,
username: user.username,
name: user.name,
age: lover?.age?.toString() ?? '25',
city: lover?.city ?? 'Internet',
gender: lover?.gender ?? '???',
age: profile?.age?.toString() ?? '25',
city: profile?.city ?? 'Internet',
gender: profile?.gender ?? '???',
} as LoveOgProps
return buildOgUrl(loveProps, 'lover')
return buildOgUrl(loveProps, 'profile')
}

View File

@@ -31,7 +31,7 @@ export type Notification = {
export const NOTIFICATION_TYPES_TO_SELECT = [
'new_match', // new match markets
'comment_on_lover', // endorsements
'comment_on_profile', // endorsements
'love_like',
'love_ship',
]

View File

@@ -2,10 +2,10 @@ import { type JSONContent } from '@tiptap/core'
import { type Row, tsToMillis } from './utils'
import { type Comment } from 'common/comment'
export const convertComment = (row: Row<'lover_comments'>): Comment => ({
export const convertComment = (row: Row<'profile_comments'>): Comment => ({
id: row.id + '',
userId: row.user_id,
commentType: 'lover',
commentType: 'profile',
onUserId: row.on_user_id,
createdTime: tsToMillis(row.created_time),
userName: row.user_name,

View File

@@ -221,7 +221,7 @@ export type Database = {
}
Relationships: []
}
lover_comments: {
profile_comments: {
Row: {
content: Json
created_time: string
@@ -260,147 +260,6 @@ export type Database = {
}
Relationships: []
}
lovers: {
Row: {
age: number | null
bio: Json | null
bio_text: unknown | null
born_in_location: string | null
city: string
city_latitude: number | null
city_longitude: number | null
comments_enabled: boolean
company: string | null
country: string | null
created_time: string
drinks_per_month: number | null
education_level: string | null
ethnicity: string[] | null
gender: string
geodb_city_id: string | null
has_kids: number | null
height_in_inches: number | null
id: number
is_smoker: boolean | null
is_vegetarian_or_vegan: boolean | null
last_modification_time: string
last_online_time: string
looking_for_matches: boolean
messaging_status: string
occupation: string | null
occupation_title: string | null
photo_urls: string[] | null
pinned_url: string | null
political_beliefs: string[] | null
pref_age_max: number | null
pref_age_min: number | null
pref_gender: string[]
pref_relation_styles: string[]
referred_by_username: string | null
region_code: string | null
religious_belief_strength: number | null
religious_beliefs: string | null
twitter: string | null
university: string | null
user_id: string
visibility: Database['public']['Enums']['lover_visibility']
wants_kids_strength: number
website: string | null
}
Insert: {
age?: number | null
bio?: Json | null
bio_text?: unknown | null
born_in_location?: string | null
city: string
city_latitude?: number | null
city_longitude?: number | null
comments_enabled?: boolean
company?: string | null
country?: string | null
created_time?: string
drinks_per_month?: number | null
education_level?: string | null
ethnicity?: string[] | null
gender: string
geodb_city_id?: string | null
has_kids?: number | null
height_in_inches?: number | null
id?: never
is_smoker?: boolean | null
is_vegetarian_or_vegan?: boolean | null
last_modification_time?: string
last_online_time?: string
looking_for_matches?: boolean
messaging_status?: string
occupation?: string | null
occupation_title?: string | null
photo_urls?: string[] | null
pinned_url?: string | null
political_beliefs?: string[] | null
pref_age_max?: number | null
pref_age_min?: number | null
pref_gender: string[]
pref_relation_styles: string[]
referred_by_username?: string | null
region_code?: string | null
religious_belief_strength?: number | null
religious_beliefs?: string | null
twitter?: string | null
university?: string | null
user_id: string
visibility?: Database['public']['Enums']['lover_visibility']
wants_kids_strength?: number
website?: string | null
}
Update: {
age?: number | null
bio?: Json | null
bio_text?: unknown | null
born_in_location?: string | null
city?: string
city_latitude?: number | null
city_longitude?: number | null
comments_enabled?: boolean
company?: string | null
country?: string | null
created_time?: string
drinks_per_month?: number | null
education_level?: string | null
ethnicity?: string[] | null
gender?: string
geodb_city_id?: string | null
has_kids?: number | null
height_in_inches?: number | null
id?: never
is_smoker?: boolean | null
is_vegetarian_or_vegan?: boolean | null
last_modification_time?: string
last_online_time?: string
looking_for_matches?: boolean
messaging_status?: string
occupation?: string | null
occupation_title?: string | null
photo_urls?: string[] | null
pinned_url?: string | null
political_beliefs?: string[] | null
pref_age_max?: number | null
pref_age_min?: number | null
pref_gender?: string[]
pref_relation_styles?: string[]
referred_by_username?: string | null
region_code?: string | null
religious_belief_strength?: number | null
religious_beliefs?: string | null
twitter?: string | null
university?: string | null
user_id?: string
visibility?: Database['public']['Enums']['lover_visibility']
wants_kids_strength?: number
website?: string | null
}
Relationships: []
}
private_user_message_channel_members: {
Row: {
channel_id: number
@@ -584,7 +443,7 @@ export type Database = {
twitter: string | null
university: string | null
user_id: string
visibility: Database['public']['Enums']['lover_visibility']
visibility: Database['public']['Enums']['profile_visibility']
wants_kids_strength: number
website: string | null
}
@@ -629,7 +488,7 @@ export type Database = {
twitter?: string | null
university?: string | null
user_id: string
visibility?: Database['public']['Enums']['lover_visibility']
visibility?: Database['public']['Enums']['profile_visibility']
wants_kids_strength?: number
website?: string | null
}
@@ -674,7 +533,7 @@ export type Database = {
twitter?: string | null
university?: string | null
user_id?: string
visibility?: Database['public']['Enums']['lover_visibility']
visibility?: Database['public']['Enums']['profile_visibility']
wants_kids_strength?: number
website?: string | null
}
@@ -834,10 +693,6 @@ export type Database = {
Args: Record<PropertyKey, never>
Returns: Record<string, unknown>[]
}
get_love_question_answers_and_lovers: {
Args: { p_question_id: number }
Returns: Record<string, unknown>[]
}
get_love_question_answers_and_profiles: {
Args: { p_question_id: number }
Returns: Record<string, unknown>[]
@@ -900,7 +755,7 @@ export type Database = {
}
}
Enums: {
lover_visibility: 'public' | 'member'
profile_visibility: 'public' | 'member'
}
CompositeTypes: {
[_ in never]: never
@@ -1028,7 +883,7 @@ export type CompositeTypes<
export const Constants = {
public: {
Enums: {
lover_visibility: ['public', 'member'],
profile_visibility: ['public', 'member'],
},
},
} as const

View File

@@ -400,7 +400,7 @@ const { data, error } = await tryCatch(
insert(pg, 'profiles', { user_id: auth.uid, ...body })
)
if (error) throw APIError(500, 'Error creating lover: ' + error.message)
if (error) throw APIError(500, 'Error creating profile: ' + error.message)
await update(pg, 'profiles', 'user_id', { user_id: auth.uid, age: 99 })

View File

@@ -3,11 +3,11 @@ import {
getAnswerCompatibility,
getScoredAnswerCompatibility,
} from 'common/love/compatibility-score'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { Row as rowFor } from 'common/supabase/utils'
import { User } from 'common/user'
import { partition, sortBy, keyBy } from 'lodash'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
import {
QuestionWithCountType,
useCompatibilityQuestionsWithAnswerCount,
@@ -25,7 +25,7 @@ import { Row } from 'web/components/layout/row'
import { Linkify } from 'web/components/widgets/linkify'
import { Pagination } from 'web/components/widgets/pagination'
import { db } from 'web/lib/supabase/db'
import { Subtitle } from '../widgets/lover-subtitle'
import { Subtitle } from '../widgets/profile-subtitle'
import { AddCompatibilityQuestionButton } from './add-compatibility-question-button'
import {
AnswerCompatibilityQuestionButton,
@@ -81,11 +81,11 @@ type CompatibilitySort =
export function CompatibilityQuestionsDisplay(props: {
isCurrentUser: boolean
user: User
lover: Profile
profile: Profile
fromSignup?: boolean
fromProfilePage?: Profile
}) {
const { isCurrentUser, user, fromSignup, fromProfilePage, lover } = props
const { isCurrentUser, user, fromSignup, fromProfilePage, profile } = props
const { refreshCompatibilityQuestions, compatibilityQuestions } =
useCompatibilityQuestionsWithAnswerCount()
@@ -223,7 +223,7 @@ export function CompatibilityQuestionsDisplay(props: {
user={user}
isCurrentUser={isCurrentUser}
refreshCompatibilityAll={refreshCompatibilityAll}
lover={lover}
profile={profile}
fromProfilePage={fromProfilePage}
/>
)
@@ -314,7 +314,7 @@ function CompatibilityAnswerBlock(props: {
yourQuestions: QuestionWithCountType[]
user: User
isCurrentUser: boolean
lover: Profile
profile: Profile
refreshCompatibilityAll: () => void
fromProfilePage?: Profile
}) {
@@ -322,7 +322,7 @@ function CompatibilityAnswerBlock(props: {
answer,
yourQuestions,
user,
lover,
profile,
isCurrentUser,
refreshCompatibilityAll,
fromProfilePage,
@@ -374,9 +374,9 @@ function CompatibilityAnswerBlock(props: {
<div className="hidden sm:block">
<CompatibilityDisplay
question={question}
lover1={lover}
profile1={profile}
answer1={answer}
lover2={comparedProfile as Profile}
profile2={comparedProfile as Profile}
currentUserIsComparedProfile={!fromProfilePage}
currentUser={currentUser}
/>
@@ -437,9 +437,9 @@ function CompatibilityAnswerBlock(props: {
<Row className="w-full justify-end sm:hidden">
<CompatibilityDisplay
question={question}
lover1={lover}
profile1={profile}
answer1={answer}
lover2={comparedProfile as Profile}
profile2={comparedProfile as Profile}
currentUserIsComparedProfile={!fromProfilePage}
currentUser={currentUser}
/>
@@ -476,8 +476,8 @@ function CompatibilityAnswerBlock(props: {
function CompatibilityDisplay(props: {
question: QuestionWithCountType
lover1: Profile
lover2: Profile
profile1: Profile
profile2: Profile
answer1: rowFor<'love_compatibility_answers'>
currentUserIsComparedProfile: boolean
currentUser: User | null | undefined
@@ -485,8 +485,8 @@ function CompatibilityDisplay(props: {
}) {
const {
question,
lover1,
lover2,
profile1,
profile2,
answer1,
currentUserIsComparedProfile,
currentUser,
@@ -499,7 +499,7 @@ function CompatibilityDisplay(props: {
async function getComparedProfileAnswer() {
db.from('love_compatibility_answers')
.select()
.eq('creator_id', lover2.user_id)
.eq('creator_id', profile2.user_id)
.eq('question_id', question.id)
.then((res) => {
if (res.error) {
@@ -515,21 +515,21 @@ function CompatibilityDisplay(props: {
const [open, setOpen] = useState(false)
if (lover1.id === lover2.id) return null
if (profile1.id === profile2.id) return null
const showCreateAnswer =
(!answer2 || answer2.importance == -1) &&
currentUserIsComparedProfile &&
!!currentUser
const isCurrentUser = currentUser?.id === lover2.user_id
const isCurrentUser = currentUser?.id === profile2.user_id
const answerCompatibility = answer2
? getAnswerCompatibility(answer1, answer2)
: //getScoredAnswerCompatibility(answer1, answer2)
undefined
const user1 = lover1.user
const user2 = lover2.user
const user1 = profile1.user
const user2 = profile2.user
const importanceScore = answer1.importance

View File

@@ -12,7 +12,7 @@ import {
import { Row } from 'web/components/layout/row'
import { IndividualQuestionRow } from '../questions-form'
import { TbMessage } from 'react-icons/tb'
import { OtherProfileAnswers } from './other-lover-answers'
import { OtherProfileAnswers } from './other-profile-answers'
import { ArrowLeftIcon } from '@heroicons/react/outline'
import { usePersistentInMemoryState } from 'web/hooks/use-persistent-in-memory-state'

View File

@@ -10,14 +10,14 @@ import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Linkify } from 'web/components/widgets/linkify'
import { IndividualQuestionRow } from '../questions-form'
import { Subtitle } from '../widgets/lover-subtitle'
import { Subtitle } from '../widgets/profile-subtitle'
import {
QuestionWithCountType,
useFRQuestionsWithAnswerCount,
useUserAnswers,
} from 'web/hooks/use-questions'
import { TbMessage } from 'react-icons/tb'
import { OtherProfileAnswers } from './other-lover-answers'
import { OtherProfileAnswers } from './other-profile-answers'
import {
MODAL_CLASS,
Modal,
@@ -26,7 +26,7 @@ import {
import { partition } from 'lodash'
import { shortenName } from 'web/components/widgets/user-link'
import { AddQuestionButton } from './free-response-add-question'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
export function FreeResponseDisplay(props: {
isCurrentUser: boolean

View File

@@ -8,7 +8,7 @@ import { capitalize, orderBy } from 'lodash'
import { Button } from 'web/components/buttons/button'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Subtitle } from '../widgets/lover-subtitle'
import { Subtitle } from '../widgets/profile-subtitle'
import { BiTachometer } from 'react-icons/bi'
export function OpinionScale(props: {

View File

@@ -2,23 +2,23 @@ import { User } from 'common/user'
import { Col } from 'web/components/layout/col'
import { CompatibilityQuestionsDisplay } from './compatibility-questions-display'
import { FreeResponseDisplay } from './free-response-display'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
export function ProfileAnswers(props: {
isCurrentUser: boolean
user: User
lover: Profile
profile: Profile
fromSignup?: boolean
fromProfilePage?: Profile
}) {
const { isCurrentUser, user, fromSignup, fromProfilePage, lover } = props
const { isCurrentUser, user, fromSignup, fromProfilePage, profile } = props
return (
<Col className={'mt-2 gap-5'}>
<CompatibilityQuestionsDisplay
isCurrentUser={isCurrentUser}
user={user}
lover={lover}
profile={profile}
fromSignup={fromSignup}
fromProfilePage={fromProfilePage}
/>

View File

@@ -1,6 +1,6 @@
import { JSONContent } from '@tiptap/core'
import { MAX_DESCRIPTION_LENGTH } from 'common/envs/constants'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { tryCatch } from 'common/util/try-catch'
import { Button } from 'web/components/buttons/button'
import { Col } from 'web/components/layout/col'
@@ -10,18 +10,18 @@ import { updateProfile } from 'web/lib/api'
import { track } from 'web/lib/service/analytics'
export function EditableBio(props: {
lover: Profile
profile: Profile
onSave: () => void
onCancel?: () => void
}) {
const { lover, onCancel, onSave } = props
const { profile, onCancel, onSave } = props
const editor = useTextEditor({
max: MAX_DESCRIPTION_LENGTH,
defaultValue: (lover.bio as JSONContent) ?? '',
defaultValue: (profile.bio as JSONContent) ?? '',
placeholder: "Tell us about yourself — and what you're looking for!",
})
const hideButtons = editor?.getText().length === 0 && !lover.bio
const hideButtons = editor?.getText().length === 0 && !profile.bio
const saveBio = async () => {
if (!editor) return
@@ -32,7 +32,7 @@ export function EditableBio(props: {
return
}
track('edited lover bio')
track('edited profile bio')
}
return (

View File

@@ -2,7 +2,7 @@ import { PencilIcon, XIcon } from '@heroicons/react/outline'
import { JSONContent } from '@tiptap/core'
import clsx from 'clsx'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import DropdownMenu from 'web/components/comments/dropdown-menu'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
@@ -13,12 +13,12 @@ import { tryCatch } from 'common/util/try-catch'
export function BioBlock(props: {
isCurrentUser: boolean
lover: Profile
profile: Profile
refreshProfile: () => void
edit: boolean
setEdit: (edit: boolean) => void
}) {
const { isCurrentUser, refreshProfile, lover, edit, setEdit } = props
const { isCurrentUser, refreshProfile, profile, edit, setEdit } = props
return (
<Col
@@ -28,15 +28,15 @@ export function BioBlock(props: {
)}
>
<Row className="w-full">
{!edit && lover.bio && (
{!edit && profile.bio && (
<Col className="flex w-full flex-grow">
<Content className="w-full" content={lover.bio as JSONContent} />
<Content className="w-full" content={profile.bio as JSONContent} />
</Col>
)}
{edit && (
<EditableBio
lover={lover}
onCancel={lover.bio ? () => setEdit(false) : undefined}
profile={profile}
onCancel={profile.bio ? () => setEdit(false) : undefined}
onSave={() => {
refreshProfile()
setEdit(false)

View File

@@ -1,29 +1,29 @@
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { useState } from 'react'
import { Col } from 'web/components/layout/col'
import { Subtitle } from '../widgets/lover-subtitle'
import { BioBlock } from './lover-bio-block'
import { Subtitle } from '../widgets/profile-subtitle'
import { BioBlock } from './profile-bio-block'
export function ProfileBio(props: {
isCurrentUser: boolean
lover: Profile
profile: Profile
refreshProfile: () => void
fromProfilePage?: Profile
}) {
const { isCurrentUser, lover, refreshProfile, fromProfilePage } = props
const { isCurrentUser, profile, refreshProfile, fromProfilePage } = props
const [edit, setEdit] = useState(false)
if (!isCurrentUser && !lover.bio) return null
if (fromProfilePage && !lover.bio) return null
if (!isCurrentUser && !profile.bio) return null
if (fromProfilePage && !profile.bio) return null
return (
<Col>
<Subtitle className="mb-4">About Me</Subtitle>
<BioBlock
isCurrentUser={isCurrentUser}
lover={lover}
profile={profile}
refreshProfile={refreshProfile}
edit={edit || (isCurrentUser && !lover.bio)}
edit={edit || (isCurrentUser && !profile.bio)}
setEdit={setEdit}
/>
</Col>

View File

@@ -4,7 +4,7 @@ import { useState } from 'react'
import Link from 'next/link'
import { MAX_COMMENT_LENGTH } from 'common/comment'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { Button } from 'web/components/buttons/button'
import { Col } from 'web/components/layout/col'
import { Modal, SCROLLABLE_MODAL_CLASS } from 'web/components/layout/modal'
@@ -13,21 +13,21 @@ import { useTextEditor } from 'web/components/widgets/editor'
import { useUser } from 'web/hooks/use-user'
import { CompatibilityScore } from 'common/love/compatibility-score'
import { CompatibleBadge } from './widgets/compatible-badge'
import { ProfileProfile } from './profile/lover-profile'
import { ProfileProfile } from './profile/profile-profile'
import { Pagination } from 'web/components/widgets/pagination'
import { Title } from 'web/components/widgets/title'
import { Input } from 'web/components/widgets/input'
export const BrowseMatchesButton = (props: {
lover: Profile
profile: Profile
potentialProfiles: Profile[]
compatibilityScores: Record<string, CompatibilityScore>
className?: string
}) => {
const { lover, potentialProfiles, compatibilityScores, className } = props
const { profile, potentialProfiles, compatibilityScores, className } = props
const currentUser = useUser()
const isCurrentUser = currentUser?.id === lover.user_id
const isCurrentUser = currentUser?.id === profile.user_id
const [dialogOpen, setDialogOpen] = useState(false)
const key = `comment ${potentialProfiles.map((l) => l.id).join(',')}`
@@ -46,7 +46,7 @@ export const BrowseMatchesButton = (props: {
// setIsSubmitting(true)
// const result = await createMatch({
// userId1: lover.user_id,
// userId1: profile.user_id,
// userId2: selectedMatchId,
// betAmount,
// introduction,
@@ -61,7 +61,7 @@ export const BrowseMatchesButton = (props: {
// window.location.reload()
// }
}
if (!lover.looking_for_matches)
if (!profile.looking_for_matches)
return (
<div className="text-ink-500 text-sm">
Not looking for more matches right now
@@ -77,11 +77,11 @@ export const BrowseMatchesButton = (props: {
disabled={isSubmitting}
loading={isSubmitting}
>
Browse {isCurrentUser ? 'your compatible' : `for ${lover.user.name}`}
Browse {isCurrentUser ? 'your compatible' : `for ${profile.user.name}`}
</Button>
{dialogOpen && (
<BrowseMatchesDialog
lover={lover}
profile={profile}
potentialProfiles={potentialProfiles}
compatibilityScores={compatibilityScores}
isSubmitting={isSubmitting}
@@ -95,7 +95,7 @@ export const BrowseMatchesButton = (props: {
}
const BrowseMatchesDialog = (props: {
lover: Profile
profile: Profile
potentialProfiles: Profile[]
compatibilityScores: Record<string, CompatibilityScore>
isSubmitting: boolean
@@ -104,7 +104,7 @@ const BrowseMatchesDialog = (props: {
editor: Editor | null
}) => {
const {
lover,
profile,
potentialProfiles,
compatibilityScores,
isSubmitting,
@@ -117,10 +117,10 @@ const BrowseMatchesDialog = (props: {
const [error, setError] = useState<string | undefined>(undefined)
const currentUser = useUser()
const isCurrentUser = currentUser?.id === lover.user_id
const isCurrentUser = currentUser?.id === profile.user_id
const filteredProfiles = potentialProfiles.filter((lover) =>
lover.user.name.toLowerCase().includes(query.toLowerCase())
const filteredProfiles = potentialProfiles.filter((profile) =>
profile.user.name.toLowerCase().includes(query.toLowerCase())
)
const [potentialIndex, setPotentialIndex] = useState(0)
const index = Math.min(potentialIndex, filteredProfiles.length - 1)
@@ -140,7 +140,7 @@ const BrowseMatchesDialog = (props: {
<Col className="bg-canvas-0 min-h-full gap-2 rounded p-4 pb-8">
<Row className="justify-between">
<Title className="!mb-0">
Browse {!isCurrentUser && `for ${lover.user.name}`}
Browse {!isCurrentUser && `for ${profile.user.name}`}
</Title>
<Input
className={'!h-10 max-w-[200px] self-end text-sm'}
@@ -172,13 +172,13 @@ const BrowseMatchesDialog = (props: {
<>
<CompatibilityScoreDisplay compatibility={compatibility} />
<ProfileProfile
lover={potentialProfile}
profile={potentialProfile}
user={potentialProfile.user}
refreshProfile={() => window.location.reload()}
fromProfilePage={lover}
fromProfilePage={profile}
/>
{/* <Col key={lover.id} className={clsx('gap-4 px-3 py-2')}>
{/* <Col key={profile.id} className={clsx('gap-4 px-3 py-2')}>
<CommentInputTextArea
isSubmitting={isSubmitting}
editor={editor}

View File

@@ -640,7 +640,7 @@
"fountain": "26F2",
"fountain_pen": "1F58B",
"four": "0034 20E3",
"four_leaf_clover": "1F340",
"four_leaf_cprofile": "1F340",
"fox_face": "1F98A",
"fr": "1F1EB 1F1F7",
"framed_picture": "1F5BC",

View File

@@ -22,7 +22,7 @@ import {
import { KidsLabel, wantsKidsLabelsWithIcon } from './wants-kids-filter'
import { HasKidsLabel } from './has-kids-filter'
import { MyMatchesToggle } from './my-matches-toggle'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import {FilterFields} from "common/filters";
import {hasKidsLabels} from "common/has-kids";

View File

@@ -3,8 +3,8 @@ import {Col} from 'web/components/layout/col'
import {Slider} from 'web/components/widgets/slider'
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
import {Row} from 'web/components/layout/row'
import {City, CityRow, loverToCity, originToCity, useCitySearch,} from '../search-location'
import {Profile} from 'common/love/lover'
import {City, CityRow, profileToCity, originToCity, useCitySearch,} from '../search-location'
import {Profile} from 'common/love/profile'
import {useEffect, useState} from 'react'
import {Input} from 'web/components/widgets/input'
import {XIcon} from '@heroicons/react/solid'
@@ -64,7 +64,7 @@ export function LocationFilter(props: {
const { location, setLocation, radius, setRadius } = props.locationFilterProps
const youCity = youProfile && loverToCity(youProfile)
const youCity = youProfile && profileToCity(youProfile)
const [lastCity, setLastCity] = usePersistentInMemoryState<City>(
location ? originToCity(location) : youCity || DEFAULT_LAST_CITY,

View File

@@ -24,7 +24,7 @@ import {
} from './wants-kids-filter'
import { FaChild } from 'react-icons/fa6'
import { MyMatchesToggle } from './my-matches-toggle'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { Gender } from 'common/gender'
import { RelationshipType } from 'web/lib/util/convert-relationship-type'
import {FilterFields} from "common/filters";

View File

@@ -1,6 +1,6 @@
import { Row } from 'web/components/layout/row'
import clsx from 'clsx'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
export function MyMatchesToggle(props: {
setYourFilters: (checked: boolean) => void

View File

@@ -1,4 +1,4 @@
import {Profile} from 'common/love/lover'
import {Profile} from 'common/love/profile'
import React, {useEffect, useState} from 'react'
import {IoFilterSharp} from 'react-icons/io5'
import {Button} from 'web/components/buttons/button'

View File

@@ -1,4 +1,4 @@
import {Profile} from "common/love/lover";
import {Profile} from "common/love/profile";
import {useIsLooking} from "web/hooks/use-is-looking";
import {usePersistentLocalState} from "web/hooks/use-persistent-local-state";
import {useCallback} from "react";

View File

@@ -18,8 +18,8 @@ import {useTracking} from 'web/hooks/use-tracking'
import {useUser} from 'web/hooks/use-user'
import {GoogleOneTapLogin} from 'web/lib/firebase/google-onetap-login'
import Sidebar from './nav/love-sidebar'
import {useProfile} from 'web/hooks/use-lover'
import {Profile} from 'common/love/lover'
import {useProfile} from 'web/hooks/use-profile'
import {Profile} from 'common/love/profile'
import {NotificationsIcon, SolidNotificationsIcon} from './notifications-icon'
export function LovePage(props: {
@@ -40,9 +40,9 @@ export function LovePage(props: {
} = props
const user = useUser()
const isMobile = useIsMobile()
const lover = useProfile()
const profile = useProfile()
const bottomNavOptions = user
? getBottomNavigation(user, lover)
? getBottomNavigation(user, profile)
: signedOutNavigation()
// const [isModalOpen, setIsModalOpen] = useState(false)
const desktopSidebarOptions = getDesktopNav(user)
@@ -106,13 +106,13 @@ const Notifs = {name: 'Notifs', href: `/notifications`, icon: NotificationsIcon}
const NotifsSolid = {name: 'Notifs', href: `/notifications`, icon: SolidNotificationsIcon};
const Messages = {name: 'Messages', href: '/messages', icon: PrivateMessagesIcon};
function getBottomNavigation(user: User, lover: Profile | null | undefined) {
function getBottomNavigation(user: User, profile: Profile | null | undefined) {
return buildArray(
Profiles,
NotifsSolid,
{
name: 'Profile',
href: lover === null ? '/signup' : `/${user.username}`,
href: profile === null ? '/signup' : `/${user.username}`,
icon: SolidHomeIcon,
},
{

View File

@@ -1,6 +1,6 @@
import { Row } from 'web/components/layout/row'
import { HeartIcon } from '@heroicons/react/solid'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import Image from 'next/image'
import { Col } from 'web/components/layout/col'
import { UserIcon } from '@heroicons/react/solid'

View File

@@ -12,7 +12,7 @@ import { useIsIframe } from 'web/hooks/use-is-iframe'
import { trackCallback } from 'web/lib/service/analytics'
import { User } from 'common/user'
import { Col } from 'web/components/layout/col'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
const itemClass =
'sm:hover:bg-ink-200 block w-full py-1 px-3 text-center sm:hover:text-primary-700 transition-colors'
@@ -80,7 +80,7 @@ function ProfileItem(props: {
track: () => void
}) {
const { user, item, touched, setTouched, currentPage, track } = props
const lover = useProfile()
const profile = useProfile()
return (
<Link
href={item.href ?? '#'}
@@ -98,7 +98,7 @@ function ProfileItem(props: {
<Avatar
size={'md'}
username={user.username}
avatarUrl={lover?.pinned_url ?? user.avatarUrl}
avatarUrl={profile?.pinned_url ?? user.avatarUrl}
noLink
/>
</div>

View File

@@ -1,5 +1,5 @@
import clsx from 'clsx'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
import Link from 'next/link'
import { Avatar } from 'web/components/widgets/avatar'
import { User } from 'web/lib/firebase/users'
@@ -8,11 +8,11 @@ import { trackCallback } from 'web/lib/service/analytics'
export function ProfileSummary(props: { user: User; className?: string }) {
const { user, className } = props
const lover = useProfile()
const profile = useProfile()
return (
<Link
href={lover === null ? '/signup' : `/${user.username}`}
href={profile === null ? '/signup' : `/${user.username}`}
onClick={trackCallback('sidebar: profile')}
className={clsx(
'hover:bg-ink-100 text-ink-700 group flex w-full shrink-0 flex-row items-center truncate rounded-md py-3',
@@ -21,7 +21,7 @@ export function ProfileSummary(props: { user: User; className?: string }) {
>
<div className="w-2 shrink" />
<Avatar
avatarUrl={lover?.pinned_url ?? ''}
avatarUrl={profile?.pinned_url ?? ''}
username={user.username}
noLink
/>

View File

@@ -15,7 +15,7 @@ import { Item, SidebarItem } from './love-sidebar-item'
import SiteLogo from '../site-logo'
import { Button, ColorType, SizeType } from 'web/components/buttons/button'
import {signupRedirect} from 'web/lib/util/signup'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
import { useTheme } from 'web/hooks/use-theme'
export default function Sidebar(props: {
@@ -28,7 +28,7 @@ export default function Sidebar(props: {
const currentPage = router.pathname
const user = useUser()
const lover = useProfile()
const profile = useProfile()
const { theme, setTheme } = useTheme()
@@ -58,7 +58,7 @@ export default function Sidebar(props: {
{user === null && <SignUpButton className="mt-4" text="Sign up" />}
{/*{user === null && <SignUpAsMatchmaker className="mt-2" />}*/}
{user && lover === null && (
{user && profile === null && (
<Button className="mt-2" onClick={() => router.push('signup')}>
Create a profile
</Button>

View File

@@ -26,7 +26,7 @@ export function NotificationItem(props: { notification: Notification }) {
setHighlighted,
}
if (sourceType === 'comment_on_lover') {
if (sourceType === 'comment_on_profile') {
return <CommentOnProfileNotification {...params} />
} else if (sourceType === 'new_match') {
return <NewMatchNotification {...params} />

View File

@@ -16,7 +16,7 @@ import {track} from 'web/lib/service/analytics'
import {Races} from './race'
import {Carousel} from 'web/components/widgets/carousel'
import {tryCatch} from 'common/util/try-catch'
import {ProfileRow} from 'common/love/lover'
import {ProfileRow} from 'common/love/profile'
import {removeNullOrUndefinedProps} from 'common/util/object'
import {isEqual, range} from 'lodash'
import {PlatformSelect} from 'web/components/widgets/platform-select'
@@ -24,7 +24,7 @@ import {PLATFORM_LABELS, type Site, SITE_ORDER} from 'common/socials'
import {PlusIcon, XIcon} from '@heroicons/react/solid'
import {SocialIcon} from './user/social'
import {Select} from 'web/components/widgets/select'
import {City, CityRow, loverToCity, useCitySearch} from "web/components/search-location";
import {City, CityRow, profileToCity, useCitySearch} from "web/components/search-location";
import {AddPhotosWidget} from './widgets/add-photos'
import {RadioToggleGroup} from "web/components/widgets/radio-toggle-group";
import {MultipleChoiceOptions} from "common/love/multiple-choice";
@@ -32,26 +32,26 @@ import {RELATIONSHIP_CHOICES} from "web/components/filters/choices";
import toast from "react-hot-toast";
export const OptionalLoveUserForm = (props: {
lover: ProfileRow
profile: ProfileRow
setProfile: <K extends Column<'profiles'>>(key: K, value: ProfileRow[K]) => void
user: User
buttonLabel?: string
fromSignup?: boolean
onSubmit?: () => Promise<void>
}) => {
const {lover, user, buttonLabel, setProfile, fromSignup, onSubmit} = props
const {profile, user, buttonLabel, setProfile, fromSignup, onSubmit} = props
const [isSubmitting, setIsSubmitting] = useState(false)
const [lookingRelationship, setLookingRelationship] = useState(false)
const router = useRouter()
const [heightFeet, setHeightFeet] = useState<number | undefined>(
lover.height_in_inches
? Math.floor((lover['height_in_inches'] ?? 0) / 12)
profile.height_in_inches
? Math.floor((profile['height_in_inches'] ?? 0) / 12)
: undefined
)
const [heightInches, setHeightInches] = useState<number | undefined>(
lover.height_in_inches
? Math.floor((lover['height_in_inches'] ?? 0) % 12)
profile.height_in_inches
? Math.floor((profile['height_in_inches'] ?? 0) % 12)
: undefined
)
@@ -64,7 +64,7 @@ export const OptionalLoveUserForm = (props: {
const handleSubmit = async () => {
setIsSubmitting(true)
const {bio: _, ...otherProfileProps} = lover
const {bio: _, ...otherProfileProps} = profile
const {error} = await tryCatch(
updateProfile(removeNullOrUndefinedProps(otherProfileProps) as any)
)
@@ -105,7 +105,7 @@ export const OptionalLoveUserForm = (props: {
}
const [trans, setTrans] = useState<boolean | undefined>(
lover['gender'].includes('trans')
profile['gender'].includes('trans')
)
function setProfileCity(inputCity: City | undefined) {
@@ -135,7 +135,7 @@ export const OptionalLoveUserForm = (props: {
}
useEffect(() => {
const currentState = lover['gender']
const currentState = profile['gender']
if (currentState === 'non-binary') {
setTrans(undefined)
} else if (trans && !currentState.includes('trans-')) {
@@ -143,7 +143,7 @@ export const OptionalLoveUserForm = (props: {
} else if (!trans && currentState.includes('trans-')) {
setProfile('gender', currentState.replace('trans-', ''))
}
}, [trans, lover['gender']])
}, [trans, profile['gender']])
return (
<>
@@ -164,10 +164,10 @@ export const OptionalLoveUserForm = (props: {
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>Location</label>
{lover.city ? (
{profile.city ? (
<Row className="border-primary-500 w-full justify-between rounded border px-4 py-2">
<CityRow
city={loverToCity(lover)}
city={profileToCity(profile)}
onSelect={() => {
}}
className="pointer-events-none"
@@ -195,7 +195,7 @@ export const OptionalLoveUserForm = (props: {
<Input
type="number"
placeholder="Age"
value={lover['age'] ?? undefined}
value={profile['age'] ?? undefined}
min={18}
max={100}
onChange={(e) => setProfile('age', Number(e.target.value))}
@@ -206,7 +206,7 @@ export const OptionalLoveUserForm = (props: {
<Col className={'gap-1'}>
<label className={clsx(labelClassName)}>Gender</label>
<ChoicesToggleGroup
currentChoice={lover['gender'].replace('trans-', '')}
currentChoice={profile['gender'].replace('trans-', '')}
choicesMap={{
Woman: 'female',
Man: 'male',
@@ -225,7 +225,7 @@ export const OptionalLoveUserForm = (props: {
Men: 'male',
Other: 'other',
}}
selected={lover['pref_gender']}
selected={profile['pref_gender']}
onChange={(selected) => setProfile('pref_gender', selected)}
/>
</Col>
@@ -236,7 +236,7 @@ export const OptionalLoveUserForm = (props: {
<Col>
<span>Min</span>
<Select
value={lover['pref_age_min'] ?? ''}
value={profile['pref_age_min'] ?? ''}
onChange={(e) =>
setProfile('pref_age_min', Number(e.target.value))
}
@@ -253,7 +253,7 @@ export const OptionalLoveUserForm = (props: {
<Col>
<span>Max</span>
<Select
value={lover['pref_age_max'] ?? ''}
value={profile['pref_age_max'] ?? ''}
onChange={(e) =>
setProfile('pref_age_max', Number(e.target.value))
}
@@ -274,7 +274,7 @@ export const OptionalLoveUserForm = (props: {
<label className={clsx(labelClassName)}>Connection type</label>
<MultiCheckbox
choices={RELATIONSHIP_CHOICES}
selected={lover['pref_relation_styles']}
selected={profile['pref_relation_styles']}
onChange={(selected) =>
setProfile('pref_relation_styles', selected)
}
@@ -359,7 +359,7 @@ export const OptionalLoveUserForm = (props: {
'Pause AI': 'pause ai',
Other: 'other',
}}
selected={lover['political_beliefs'] ?? []}
selected={profile['political_beliefs'] ?? []}
onChange={(selected) => setProfile('political_beliefs', selected)}
/>
</Col>
@@ -370,14 +370,14 @@ export const OptionalLoveUserForm = (props: {
type="text"
onChange={(e) => setProfile('religious_beliefs', e.target.value)}
className={'w-full sm:w-96'}
value={lover['religious_beliefs'] ?? undefined}
value={profile['religious_beliefs'] ?? undefined}
/>
</Col>
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>Do you smoke?</label>
<ChoicesToggleGroup
currentChoice={lover['is_smoker'] ?? undefined}
currentChoice={profile['is_smoker'] ?? undefined}
choicesMap={{
Yes: true,
No: false,
@@ -399,7 +399,7 @@ export const OptionalLoveUserForm = (props: {
}}
className={'w-20'}
min={0}
value={lover['drinks_per_month'] ?? undefined}
value={profile['drinks_per_month'] ?? undefined}
/>
</Col>
@@ -451,7 +451,7 @@ export const OptionalLoveUserForm = (props: {
type="text"
onChange={(e) => setProfileState('born_in_location', e.target.value)}
className={'w-52'}
value={lover['born_in_location'] ?? undefined}
value={profile['born_in_location'] ?? undefined}
/>
</Col> */}
@@ -459,7 +459,7 @@ export const OptionalLoveUserForm = (props: {
<label className={clsx(labelClassName)}>Ethnicity/origin</label>
<MultiCheckbox
choices={Races}
selected={lover['ethnicity'] ?? []}
selected={profile['ethnicity'] ?? []}
onChange={(selected) => setProfile('ethnicity', selected)}
/>
</Col>
@@ -470,7 +470,7 @@ export const OptionalLoveUserForm = (props: {
</label>
<Carousel className="max-w-full">
<ChoicesToggleGroup
currentChoice={lover['education_level'] ?? ''}
currentChoice={profile['education_level'] ?? ''}
choicesMap={{
None: 'none',
'High school': 'high-school',
@@ -489,7 +489,7 @@ export const OptionalLoveUserForm = (props: {
type="text"
onChange={(e) => setProfile('university', e.target.value)}
className={'w-52'}
value={lover['university'] ?? undefined}
value={profile['university'] ?? undefined}
/>
</Col>
<Col className={clsx(colClassName)}>
@@ -498,19 +498,19 @@ export const OptionalLoveUserForm = (props: {
type="text"
onChange={(e) => setProfile('company', e.target.value)}
className={'w-52'}
value={lover['company'] ?? undefined}
value={profile['company'] ?? undefined}
/>
</Col>
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>
Job title {lover['company'] ? 'at ' + lover['company'] : ''}
Job title {profile['company'] ? 'at ' + profile['company'] : ''}
</label>
<Input
type="text"
onChange={(e) => setProfile('occupation_title', e.target.value)}
className={'w-52'}
value={lover['occupation_title'] ?? undefined}
value={profile['occupation_title'] ?? undefined}
/>
</Col>
@@ -525,7 +525,7 @@ export const OptionalLoveUserForm = (props: {
}}
className={'w-20'}
min={0}
value={lover['has_kids'] ?? undefined}
value={profile['has_kids'] ?? undefined}
/>
</Col>
@@ -549,7 +549,7 @@ export const OptionalLoveUserForm = (props: {
setChoice={(choice) => {
setProfile('wants_kids_strength', choice)
}}
currentChoice={lover.wants_kids_strength ?? -1}
currentChoice={profile.wants_kids_strength ?? -1}
/>
</Col>
</>}
@@ -563,8 +563,8 @@ export const OptionalLoveUserForm = (props: {
<AddPhotosWidget
user={user}
photo_urls={lover.photo_urls}
pinned_url={lover.pinned_url}
photo_urls={profile.photo_urls}
pinned_url={profile.pinned_url}
setPhotoUrls={(urls) => setProfile('photo_urls', urls)}
setPinnedUrl={(url) => setProfile('pinned_url', url)}
/>

View File

@@ -28,7 +28,7 @@ import { Gender, convertGenderPlural } from 'common/gender'
import { HiOutlineGlobe } from 'react-icons/hi'
import { UserHandles } from 'web/components/user/user-handles'
import { convertRace } from './race'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
export function AboutRow(props: {
icon: ReactNode
@@ -54,48 +54,48 @@ export function AboutRow(props: {
)
}
export default function ProfileAbout(props: { lover: Profile }) {
const { lover } = props
export default function ProfileAbout(props: { profile: Profile }) {
const { profile } = props
return (
<Col
className={clsx('bg-canvas-0 relative gap-3 overflow-hidden rounded p-4')}
>
<Seeking lover={lover} />
<RelationshipType lover={lover} />
<HasKids lover={lover} />
<Seeking profile={profile} />
<RelationshipType profile={profile} />
<HasKids profile={profile} />
<AboutRow
icon={<RiScales3Line className="h-5 w-5" />}
text={lover.political_beliefs}
text={profile.political_beliefs}
/>
<Education lover={lover} />
<Occupation lover={lover} />
<Education profile={profile} />
<Occupation profile={profile} />
<AboutRow
icon={<PiHandsPrayingBold className="h-5 w-5" />}
text={lover.religious_beliefs}
text={profile.religious_beliefs}
/>
<AboutRow
icon={<HiOutlineGlobe className="h-5 w-5" />}
text={lover.ethnicity
text={profile.ethnicity
?.filter((r) => r !== 'other')
?.map((r: any) => convertRace(r))}
/>
<Smoker lover={lover} />
<Drinks lover={lover} />
<Smoker profile={profile} />
<Drinks profile={profile} />
<AboutRow
icon={<PiPlantBold className="h-5 w-5" />}
text={lover.is_vegetarian_or_vegan ? 'Vegetarian/Vegan' : null}
text={profile.is_vegetarian_or_vegan ? 'Vegetarian/Vegan' : null}
/>
<WantsKids lover={lover} />
<UserHandles links={lover.user.link} />
<WantsKids profile={profile} />
<UserHandles links={profile.user.link} />
</Col>
)
}
function Seeking(props: { lover: Profile }) {
const { lover } = props
const prefGender = lover.pref_gender
const min = lover.pref_age_min
const max = lover.pref_age_max
function Seeking(props: { profile: Profile }) {
const { profile } = props
const prefGender = profile.pref_gender
const min = profile.pref_age_min
const max = profile.pref_age_max
const seekingGenderText = stringOrStringArrayToText({
text:
prefGender.length == 5
@@ -126,9 +126,9 @@ function Seeking(props: { lover: Profile }) {
)
}
function RelationshipType(props: { lover: Profile }) {
const { lover } = props
const relationshipTypes = lover.pref_relation_styles
function RelationshipType(props: { profile: Profile }) {
const { profile } = props
const relationshipTypes = profile.pref_relation_styles
const seekingGenderText = stringOrStringArrayToText({
text: relationshipTypes.map((rel) =>
convertRelationshipType(rel as RelationshipType).toLowerCase()
@@ -149,10 +149,10 @@ function RelationshipType(props: { lover: Profile }) {
)
}
function Education(props: { lover: Profile }) {
const { lover } = props
const educationLevel = lover.education_level
const university = lover.university
function Education(props: { profile: Profile }) {
const { profile } = props
const educationLevel = profile.education_level
const university = profile.university
const noUniversity =
!educationLevel ||
@@ -173,10 +173,10 @@ function Education(props: { lover: Profile }) {
)
}
function Occupation(props: { lover: Profile }) {
const { lover } = props
const occupation_title = lover.occupation_title
const company = lover.company
function Occupation(props: { profile: Profile }) {
const { profile } = props
const occupation_title = profile.occupation_title
const company = profile.company
if (!company && !occupation_title) {
return <></>
@@ -194,9 +194,9 @@ function Occupation(props: { lover: Profile }) {
)
}
function Smoker(props: { lover: Profile }) {
const { lover } = props
const isSmoker = lover.is_smoker
function Smoker(props: { profile: Profile }) {
const { profile } = props
const isSmoker = profile.is_smoker
if (isSmoker == null) return null
if (isSmoker) {
return (
@@ -211,9 +211,9 @@ function Smoker(props: { lover: Profile }) {
)
}
function Drinks(props: { lover: Profile }) {
const { lover } = props
const drinksPerMonth = lover.drinks_per_month
function Drinks(props: { profile: Profile }) {
const { profile } = props
const drinksPerMonth = profile.drinks_per_month
if (drinksPerMonth == null) return null
if (drinksPerMonth === 0) {
return (
@@ -233,9 +233,9 @@ function Drinks(props: { lover: Profile }) {
)
}
function WantsKids(props: { lover: Profile }) {
const { lover } = props
const wantsKidsStrength = lover.wants_kids_strength
function WantsKids(props: { profile: Profile }) {
const { profile } = props
const wantsKidsStrength = profile.wants_kids_strength
if (wantsKidsStrength == null || wantsKidsStrength < 0) return null
const wantsKidsText =
wantsKidsStrength == 0
@@ -256,11 +256,11 @@ function WantsKids(props: { lover: Profile }) {
)
}
function HasKids(props: { lover: Profile }) {
const { lover } = props
function HasKids(props: { profile: Profile }) {
const { profile } = props
const hasKidsText =
lover.has_kids && lover.has_kids > 0
? `Has ${lover.has_kids} ${lover.has_kids > 1 ? 'kids' : 'kid'}`
profile.has_kids && profile.has_kids > 0
? `Has ${profile.has_kids} ${profile.has_kids > 1 ? 'kids' : 'kid'}`
: null
return <AboutRow icon={<FaChild className="h-5 w-5" />} text={hasKidsText} />
}

View File

@@ -7,7 +7,7 @@ import { Carousel } from 'web/components/widgets/carousel'
import { MODAL_CLASS, Modal } from 'web/components/layout/modal'
import { Col } from 'web/components/layout/col'
import { SignUpButton } from './nav/love-sidebar'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { useAdmin } from 'web/hooks/use-admin'
import { Button } from 'web/components/buttons/button'
import { updateProfile } from 'web/lib/api'
@@ -18,21 +18,21 @@ import { api } from 'web/lib/api'
import { EditablePhotoGrid } from './widgets/editable-photo-grid'
import { AddPhotosWidget } from './widgets/add-photos'
export default function ProfileCarousel(props: { lover: Profile }) {
const { lover } = props
const photoNums = lover.photo_urls ? lover.photo_urls.length : 0
export default function ProfileCarousel(props: { profile: Profile }) {
const { profile } = props
const photoNums = profile.photo_urls ? profile.photo_urls.length : 0
const [lightboxUrl, setLightboxUrl] = useState('')
const [lightboxOpen, setLightboxOpen] = useState(false)
const [isEditMode, setIsEditMode] = useState(false)
const [addPhotosOpen, setAddPhotosOpen] = useState(false)
const [pinnedUrl, setPinnedUrl] = useState<string | null>(lover.pinned_url)
const [photoUrls, setPhotoUrls] = useState<string[]>(lover.photo_urls ?? [])
const [pinnedUrl, setPinnedUrl] = useState<string | null>(profile.pinned_url)
const [photoUrls, setPhotoUrls] = useState<string[]>(profile.photo_urls ?? [])
const isAdmin = useAdmin()
const currentUser = useUser()
const isCurrentUser = currentUser?.id === lover.user_id
const isCurrentUser = currentUser?.id === profile.user_id
const handleSaveChanges = async () => {
await updateProfile({
@@ -42,14 +42,14 @@ export default function ProfileCarousel(props: { lover: Profile }) {
setIsEditMode(false)
}
if (!currentUser && lover.visibility !== 'public') {
if (!currentUser && profile.visibility !== 'public') {
return (
<Carousel>
{lover.pinned_url && (
{profile.pinned_url && (
<div className="h-80 w-[250px] flex-none snap-start">
<Image
priority={true}
src={lover.pinned_url}
src={profile.pinned_url}
height={360}
width={240}
sizes="(max-width: 640px) 100vw, 240px"
@@ -83,7 +83,7 @@ export default function ProfileCarousel(props: { lover: Profile }) {
size="sm"
color="red"
onClick={() => {
api('remove-pinned-photo', { userId: lover.user_id }).then(() =>
api('remove-pinned-photo', { userId: profile.user_id }).then(() =>
Router.back()
)
}}
@@ -105,8 +105,8 @@ export default function ProfileCarousel(props: { lover: Profile }) {
<Button
onClick={() => {
// TODO this is stale if you've saved
setPhotoUrls(lover.photo_urls ?? [])
setPinnedUrl(lover.pinned_url)
setPhotoUrls(profile.photo_urls ?? [])
setPinnedUrl(profile.pinned_url)
setIsEditMode(false)
}}
color="gray-outline"
@@ -164,7 +164,7 @@ export default function ProfileCarousel(props: { lover: Profile }) {
</Col>
) : (
<Carousel>
{buildArray(lover.pinned_url, lover.photo_urls).map((url, i) => (
{buildArray(profile.pinned_url, profile.photo_urls).map((url, i) => (
<div key={url} className="h-80 w-[250px] flex-none snap-start">
<Image
priority={i < 3}
@@ -181,7 +181,7 @@ export default function ProfileCarousel(props: { lover: Profile }) {
/>
</div>
))}
{isCurrentUser && (lover.photo_urls?.length ?? 0) > 1 && (
{isCurrentUser && (profile.photo_urls?.length ?? 0) > 1 && (
<button
className="bg-ink-200 text-ink-0 group flex h-80 w-[250px] flex-none cursor-pointer snap-start items-center justify-center rounded ease-in-out"
onClick={() => setAddPhotosOpen(true)}

View File

@@ -1,10 +1,10 @@
import { Col } from 'web/components/layout/col'
import { groupBy, orderBy } from 'lodash'
import { useLiveCommentsOnProfile } from 'web/hooks/use-comments-on-lover'
import { useLiveCommentsOnProfile } from 'web/hooks/use-comments-on-profile'
import {
ProfileCommentInput,
ProfileProfileCommentThread,
} from 'web/components/lover-comments'
} from 'web/components/profile-comments'
import { User } from 'common/user'
import { Row } from 'web/components/layout/row'
import ShortToggle from 'web/components/widgets/short-toggle'
@@ -12,12 +12,12 @@ import { useState } from 'react'
import { updateProfile } from 'web/lib/api'
import { Tooltip } from 'web/components/widgets/tooltip'
import { toast } from 'react-hot-toast'
import { Subtitle } from './widgets/lover-subtitle'
import { Profile } from 'common/love/lover'
import { Subtitle } from './widgets/profile-subtitle'
import { Profile } from 'common/love/profile'
export const ProfileCommentSection = (props: {
onUser: User
lover: Profile
profile: Profile
currentUser: User | null | undefined
simpleView?: boolean
}) => {
@@ -25,10 +25,10 @@ export const ProfileCommentSection = (props: {
const comments = useLiveCommentsOnProfile(onUser.id).filter((c) => !c.hidden)
const parentComments = comments.filter((c) => !c.replyToCommentId)
const commentsByParent = groupBy(comments, (c) => c.replyToCommentId ?? '_')
const [lover, setProfile] = useState<Profile>(props.lover)
const [profile, setProfile] = useState<Profile>(props.profile)
const isCurrentUser = currentUser?.id === onUser.id
if (simpleView && (!lover.comments_enabled || parentComments.length == 0))
if (simpleView && (!profile.comments_enabled || parentComments.length == 0))
return null
return (
@@ -38,12 +38,12 @@ export const ProfileCommentSection = (props: {
{isCurrentUser && !simpleView && (
<Tooltip
text={
(lover.comments_enabled ? 'Disable' : 'Enable') +
(profile.comments_enabled ? 'Disable' : 'Enable') +
' endorsements from others'
}
>
<ShortToggle
on={lover.comments_enabled}
on={profile.comments_enabled}
setOn={(on) => {
const update = { comments_enabled: on }
setProfile((l) => ({ ...l, ...update }))
@@ -63,7 +63,7 @@ export const ProfileCommentSection = (props: {
</Row>
{!simpleView && (
<>
{lover.comments_enabled && (
{profile.comments_enabled && (
<>
<div className="mb-4">
{isCurrentUser ? (
@@ -84,7 +84,7 @@ export const ProfileCommentSection = (props: {
)}
</>
)}
{!lover.comments_enabled &&
{!profile.comments_enabled &&
(isCurrentUser ? (
<span className={'text-ink-500 text-sm'}>
This feature is disabled
@@ -96,7 +96,7 @@ export const ProfileCommentSection = (props: {
))}
</>
)}
{lover.comments_enabled &&
{profile.comments_enabled &&
orderBy(parentComments, 'createdTime', 'desc').map((c) => (
<ProfileProfileCommentThread
key={c.id + 'thread'}

View File

@@ -29,7 +29,7 @@ import { api } from 'web/lib/api'
import { RelativeTimestamp } from 'web/components/relative-timestamp'
import { useAdmin } from 'web/hooks/use-admin'
import { EyeOffIcon } from '@heroicons/react/outline'
import { useProfileByUserId } from 'web/hooks/use-lover'
import { useProfileByUserId } from 'web/hooks/use-profile'
import { MAX_COMMENT_LENGTH, ReplyToUserInfo } from 'common/comment'
import { safeLocalStorage } from 'web/lib/util/local'
@@ -158,7 +158,7 @@ const ProfileComment = memo(function FeedComment(props: {
const [comment, setComment] = useState(props.comment)
const { userUsername, userAvatarUrl, userId, hidden } = comment
const isOwner = onUser.id === userId
const lover = useProfileByUserId(userId)
const profile = useProfileByUserId(userId)
useEffect(() => {
if (highlighted && ref.current) {
@@ -176,7 +176,7 @@ const ProfileComment = memo(function FeedComment(props: {
<Avatar
username={userUsername}
size={isParent ? 'sm' : '2xs'}
avatarUrl={lover?.pinned_url ?? userAvatarUrl}
avatarUrl={profile?.pinned_url ?? userAvatarUrl}
className={clsx(isOwner && 'shadow shadow-amber-300', 'z-10')}
/>
<div

View File

@@ -1,4 +1,4 @@
import {Profile} from 'common/love/lover'
import {Profile} from 'common/love/profile'
import {CompatibilityScore} from 'common/love/compatibility-score'
import {LoadingIndicator} from 'web/components/widgets/loading-indicator'
import {LoadMoreUntilNotVisible} from 'web/components/widgets/visibility-observer'
@@ -34,7 +34,7 @@ export const ProfileGrid = (props: {
const user = useUser()
const other_profiles = profiles.filter((lover) => lover.user_id !== user?.id);
const other_profiles = profiles.filter((profile) => profile.user_id !== user?.id);
return (
<div className="relative">
@@ -45,12 +45,12 @@ export const ProfileGrid = (props: {
)}
>
{other_profiles
.map((lover) => (
.map((profile) => (
<ProfilePreview
key={lover.id}
lover={lover}
compatibilityScore={compatibilityScores?.[lover.user_id]}
hasStar={starredUserIds?.includes(lover.user_id) ?? false}
key={profile.id}
profile={profile}
compatibilityScore={compatibilityScores?.[profile.user_id]}
hasStar={starredUserIds?.includes(profile.user_id) ?? false}
refreshStars={refreshStars}
/>
))}
@@ -75,13 +75,13 @@ export const ProfileGrid = (props: {
}
function ProfilePreview(props: {
lover: Profile
profile: Profile
compatibilityScore: CompatibilityScore | undefined
hasStar: boolean
refreshStars: () => Promise<void>
}) {
const {lover, compatibilityScore} = props
const {user} = lover
const {profile, compatibilityScore} = props
const {user} = profile
// const currentUser = useUser()
return (
@@ -115,7 +115,7 @@ function ProfilePreview(props: {
{/* className="!pt-0"*/}
{/* isStarred={hasStar}*/}
{/* refresh={refreshStars}*/}
{/* targetProfile={lover}*/}
{/* targetProfile={profile}*/}
{/* hideTooltip*/}
{/* />*/}
{/* ) : (*/}
@@ -135,7 +135,7 @@ function ProfilePreview(props: {
</h3>
<div className="text-sm text-gray-500 dark:text-gray-400">
{/*TODO: fix nested <a> links warning (one from Link above, one from link in bio below)*/}
<Content className="w-full line-clamp-4" content={lover.bio as JSONContent}/>
<Content className="w-full line-clamp-4" content={profile.bio as JSONContent}/>
</div>
{/*{age}*/}
</div>

View File

@@ -6,30 +6,30 @@ import { MdHeight } from 'react-icons/md'
import { Row } from 'web/components/layout/row'
import GenderIcon from '../gender-icon'
import { Gender, convertGender } from 'common/gender'
import { formatProfileValue } from '../lover-about'
import { Profile } from 'common/love/lover'
import { formatProfileValue } from '../profile-about'
import { Profile } from 'common/love/profile'
export default function ProfilePrimaryInfo(props: { lover: Profile }) {
const { lover } = props
export default function ProfilePrimaryInfo(props: { profile: Profile }) {
const { profile } = props
const stateOrCountry =
lover.country === 'United States of America'
? lover.region_code
: lover.country
profile.country === 'United States of America'
? profile.region_code
: profile.country
return (
<Row className="text-ink-700 gap-4 text-sm">
<IconWithInfo
text={`${lover.city ?? ''}, ${stateOrCountry ?? ''}`}
text={`${profile.city ?? ''}, ${stateOrCountry ?? ''}`}
icon={<IoLocationOutline className="h-4 w-4" />}
/>
<IconWithInfo
text={capitalize(convertGender(lover.gender as Gender))}
text={capitalize(convertGender(profile.gender as Gender))}
icon={
<GenderIcon gender={lover.gender as Gender} className="h-4 w-4 " />
<GenderIcon gender={profile.gender as Gender} className="h-4 w-4 " />
}
/>
{lover.height_in_inches != null && (
{profile.height_in_inches != null && (
<IconWithInfo
text={formatProfileValue('height_in_inches', lover.height_in_inches)}
text={formatProfileValue('height_in_inches', profile.height_in_inches)}
icon={<MdHeight className="h-4 w-4 " />}
/>
)}

View File

@@ -8,12 +8,12 @@ import {MoreOptionsUserButton} from 'web/components/buttons/more-options-user-bu
import {Col} from 'web/components/layout/col'
import {Row} from 'web/components/layout/row'
import {SendMessageButton} from 'web/components/messaging/send-message-button'
import ProfilePrimaryInfo from './lover-primary-info'
import ProfilePrimaryInfo from './profile-primary-info'
import {OnlineIcon} from '../online-icon'
import {track} from 'web/lib/service/analytics'
import DropdownMenu from 'web/components/comments/dropdown-menu'
import {ShareProfileButton} from '../widgets/share-profile-button'
import {Profile} from 'common/love/lover'
import {Profile} from 'common/love/profile'
import {useUser} from 'web/hooks/use-user'
import {linkClass} from 'web/components/widgets/site-link'
import {StarButton} from '../widgets/star-button'
@@ -23,7 +23,7 @@ import {VisibilityConfirmationModal} from './visibility-confirmation-modal'
export default function ProfileProfileHeader(props: {
user: User
lover: Profile
profile: Profile
simpleView?: boolean
starredUserIds: string[]
refreshStars: () => Promise<void>
@@ -32,7 +32,7 @@ export default function ProfileProfileHeader(props: {
}) {
const {
user,
lover,
profile,
simpleView,
starredUserIds,
refreshStars,
@@ -43,7 +43,7 @@ export default function ProfileProfileHeader(props: {
const isCurrentUser = currentUser?.id === user.id
const [showVisibilityModal, setShowVisibilityModal] = useState(false)
console.log('ProfileProfileHeader', {user, lover, currentUser})
console.log('ProfileProfileHeader', {user, profile, currentUser})
return (
<Col className="w-full">
@@ -51,7 +51,7 @@ export default function ProfileProfileHeader(props: {
<Row className="items-center gap-1">
<Col className="gap-1">
<Row className="items-center gap-1 text-xl">
<OnlineIcon last_online_time={lover.last_online_time}/>
<OnlineIcon last_online_time={profile.last_online_time}/>
<span>
{simpleView ? (
<Link className={linkClass} href={`/${user.username}`}>
@@ -60,10 +60,10 @@ export default function ProfileProfileHeader(props: {
) : (
<span className="font-semibold">{user.name}</span>
)}
, {lover.age}
, {profile.age}
</span>
</Row>
<ProfilePrimaryInfo lover={lover}/>
<ProfilePrimaryInfo profile={profile}/>
</Col>
</Row>
{currentUser && isCurrentUser ? (
@@ -91,11 +91,11 @@ export default function ProfileProfileHeader(props: {
items={[
{
name:
lover.visibility === 'member'
profile.visibility === 'member'
? 'List Profile Publicly'
: 'Limit to Members Only',
icon:
lover.visibility === 'member' ? (
profile.visibility === 'member' ? (
<EyeIcon className="h-4 w-4"/>
) : (
<LockClosedIcon className="h-4 w-4"/>
@@ -129,7 +129,7 @@ export default function ProfileProfileHeader(props: {
/>
{currentUser && (
<StarButton
targetProfile={lover}
targetProfile={profile}
isStarred={starredUserIds.includes(user.id)}
refresh={refreshStars}
/>
@@ -149,10 +149,10 @@ export default function ProfileProfileHeader(props: {
<VisibilityConfirmationModal
open={showVisibilityModal}
setOpen={setShowVisibilityModal}
currentVisibility={lover.visibility}
currentVisibility={profile.visibility}
onConfirm={async () => {
const newVisibility =
lover.visibility === 'member' ? 'public' : 'member'
profile.visibility === 'member' ? 'public' : 'member'
await updateProfile({visibility: newVisibility})
refreshProfile()
}}

View File

@@ -1,17 +1,17 @@
import {ProfileCommentSection} from 'web/components/lover-comment-section'
import ProfileProfileHeader from 'web/components/profile/lover-profile-header'
import {ProfileCommentSection} from 'web/components/profile-comment-section'
import ProfileProfileHeader from 'web/components/profile/profile-profile-header'
import ProfileCarousel from 'web/components/profile-carousel'
import {Col} from 'web/components/layout/col'
import {Row} from 'web/components/layout/row'
import {useUser} from 'web/hooks/use-user'
import {User} from 'web/lib/firebase/users'
import ProfileAbout from 'web/components/lover-about'
import {ProfileAnswers} from 'web/components/answers/lover-answers'
import ProfileAbout from 'web/components/profile-about'
import {ProfileAnswers} from 'web/components/answers/profile-answers'
import {SignUpButton} from 'web/components/nav/love-sidebar'
import {Profile} from 'common/love/lover'
import {ProfileBio} from 'web/components/bio/lover-bio'
import {Profile} from 'common/love/profile'
import {ProfileBio} from 'web/components/bio/profile-bio'
import {areGenderCompatible} from 'common/love/compatibility-util'
import {useProfile} from 'web/hooks/use-lover'
import {useProfile} from 'web/hooks/use-profile'
import {useGetter} from 'web/hooks/use-getter'
import {getStars} from 'web/lib/supabase/stars'
import {Content} from "web/components/widgets/editor";
@@ -19,14 +19,14 @@ import {JSONContent} from "@tiptap/core";
import React from "react";
export function ProfileProfile(props: {
lover: Profile
profile: Profile
user: User
refreshProfile: () => void
fromProfilePage?: Profile
fromSignup?: boolean
}) {
console.log('Rendering ProfileProfile for ', props)
const {lover, user, refreshProfile, fromProfilePage, fromSignup} = props
const {profile, user, refreshProfile, fromProfilePage, fromSignup} = props
const currentUser = useUser()
const currentProfile = useProfile()
@@ -56,18 +56,18 @@ export function ProfileProfile(props: {
// !!ships && hasShipped(currentUser, fromProfilePage?.user_id, user.id, ships)
const areCompatible =
!!currentProfile && areGenderCompatible(currentProfile, lover)
!!currentProfile && areGenderCompatible(currentProfile, profile)
// Allow everyone to message everyone for now
const showMessageButton = true // liked || likedBack || !areCompatible
const isProfileVisible = currentUser || lover.visibility === 'public'
const isProfileVisible = currentUser || profile.visibility === 'public'
return (
<>
<ProfileProfileHeader
user={user}
lover={lover}
profile={profile}
simpleView={!!fromProfilePage}
starredUserIds={starredUserIds ?? []}
refreshStars={refreshStars}
@@ -77,7 +77,7 @@ export function ProfileProfile(props: {
{isProfileVisible ? (
<ProfileContent
user={user}
lover={lover}
profile={profile}
refreshProfile={refreshProfile}
fromProfilePage={fromProfilePage}
fromSignup={fromSignup}
@@ -89,7 +89,7 @@ export function ProfileProfile(props: {
) : (
<Col className="bg-canvas-0 w-full gap-4 rounded p-4">
<div className="text-sm text-gray-500 dark:text-gray-400">
<Content className="w-full line-clamp-6" content={lover.bio as JSONContent}/>
<Content className="w-full line-clamp-6" content={profile.bio as JSONContent}/>
</div>
<Col className="relative gap-4">
<div className="bg-ink-200 dark:bg-ink-400 h-4 w-2/5"/>
@@ -106,7 +106,7 @@ export function ProfileProfile(props: {
{/* ((!fromProfilePage && !isCurrentUser) ||*/}
{/* (fromProfilePage && fromProfilePage.user_id === currentUser?.id)) && (*/}
{/* <Row className="right-0 mr-1 self-end lg:bottom-6">*/}
{/* <LikeButton targetProfile={lover} liked={liked} refresh={refresh} />*/}
{/* <LikeButton targetProfile={profile} liked={liked} refresh={refresh} />*/}
{/* </Row>*/}
{/* )}*/}
{/*{fromProfilePage &&*/}
@@ -121,14 +121,14 @@ export function ProfileProfile(props: {
{/* />*/}
{/* </Row>*/}
{/* )}*/}
{isProfileVisible && lover.photo_urls && <ProfileCarousel lover={lover}/>}
{isProfileVisible && profile.photo_urls && <ProfileCarousel profile={profile}/>}
</>
)
}
function ProfileContent(props: {
user: User
lover: Profile
profile: Profile
refreshProfile: () => void
fromProfilePage?: Profile
fromSignup?: boolean
@@ -139,7 +139,7 @@ function ProfileContent(props: {
}) {
const {
user,
lover,
profile,
refreshProfile,
fromProfilePage,
fromSignup,
@@ -154,10 +154,10 @@ function ProfileContent(props: {
return (
<>
<ProfileAbout lover={lover}/>
<ProfileAbout profile={profile}/>
<ProfileBio
isCurrentUser={isCurrentUser}
lover={lover}
profile={profile}
refreshProfile={refreshProfile}
fromProfilePage={fromProfilePage}
/>
@@ -166,11 +166,11 @@ function ProfileContent(props: {
user={user}
fromSignup={fromSignup}
fromProfilePage={fromProfilePage}
lover={lover}
profile={profile}
/>
<ProfileCommentSection
onUser={user}
lover={lover}
profile={profile}
currentUser={currentUser}
simpleView={!!fromProfilePage}
/>
@@ -179,7 +179,7 @@ function ProfileContent(props: {
{/* likesReceived={likesReceived}*/}
{/* ships={ships}*/}
{/* refreshShips={refreshShips}*/}
{/* profileProfile={lover}*/}
{/* profileProfile={profile}*/}
{/*/>*/}
</>
)

View File

@@ -1,7 +1,7 @@
import {Profile} from 'common/love/lover'
import {Profile} from 'common/love/profile'
import {removeNullOrUndefinedProps} from 'common/util/object'
import {Search} from 'web/components/filters/search'
import {useProfile} from 'web/hooks/use-lover'
import {useProfile} from 'web/hooks/use-profile'
import {useCompatibleProfiles} from 'web/hooks/use-profiles'
import {getStars} from 'web/lib/supabase/stars'
import Router from 'next/router'
@@ -20,8 +20,8 @@ import {useFilters} from "web/components/filters/use-filters";
export function ProfilesHome() {
const user = useUser();
const lover = useProfile();
const you = lover;
const profile = useProfile();
const you = profile;
const {
filters,
@@ -95,7 +95,7 @@ export function ProfilesHome() {
return (
<>
{!lover && <Button className="mb-4 lg:hidden" onClick={() => Router.push('signup')}>Create a profile</Button>}
{!profile && <Button className="mb-4 lg:hidden" onClick={() => Router.push('signup')}>Create a profile</Button>}
<Title className="!mb-2 text-3xl">Profiles</Title>
<Search
youProfile={you}
@@ -117,7 +117,7 @@ export function ProfilesHome() {
loadMore={loadMore}
isLoadingMore={isLoadingMore}
isReloading={isReloading}
compatibilityScores={compatibleProfiles?.loverCompatibilityScores}
compatibilityScores={compatibleProfiles?.profileCompatibilityScores}
starredUserIds={starredUserIds}
refreshStars={refreshStars}
/>

View File

@@ -10,7 +10,7 @@ import {User} from 'common/user'
import {useEditableUserInfo} from 'web/hooks/use-editable-user-info'
import {LoadingIndicator} from 'web/components/widgets/loading-indicator'
import {Column} from 'common/supabase/utils'
import {ProfileRow} from 'common/love/lover'
import {ProfileRow} from 'common/love/profile'
import {SignupBio} from "web/components/bio/editable-bio";
import {JSONContent} from "@tiptap/core";
@@ -40,13 +40,13 @@ export const RequiredLoveUserForm = (props: {
// TODO thread this properly instead of this jank
setEditUsername?: (name: string) => unknown
setEditDisplayName?: (name: string) => unknown
lover: ProfileRow
profile: ProfileRow
setProfile: <K extends Column<'profiles'>>(key: K, value: ProfileRow[K] | undefined) => void
isSubmitting: boolean
onSubmit?: () => void
loverCreatedAlready?: boolean
profileCreatedAlready?: boolean
}) => {
const {user, onSubmit, loverCreatedAlready, setProfile, lover, isSubmitting} = props
const {user, onSubmit, profileCreatedAlready, setProfile, profile, isSubmitting} = props
const {updateUsername, updateDisplayName, userInfo, updateUserState} = useEditableUserInfo(user)
const {
@@ -67,9 +67,9 @@ export const RequiredLoveUserForm = (props: {
const canContinue = true
// const canContinue =
// (!lover.looking_for_matches ||
// (!profile.looking_for_matches ||
// requiredKeys
// .map((k) => lover[k])
// .map((k) => profile[k])
// .every((v) =>
// typeof v == 'string'
// ? v !== ''
@@ -83,7 +83,7 @@ export const RequiredLoveUserForm = (props: {
return (
<>
<Title>The Basics</Title>
{!loverCreatedAlready && <div className="text-ink-500 mb-6 text-lg">No endless formswrite your own bio, your own way.</div>}
{!profileCreatedAlready && <div className="text-ink-500 mb-6 text-lg">No endless formswrite your own bio, your own way.</div>}
<Col className={'gap-8'}>
<Col>
<label className={clsx(labelClassName)}>Display name</label>
@@ -103,7 +103,7 @@ export const RequiredLoveUserForm = (props: {
{errorName && <span className="text-error text-sm">{errorName}</span>}
</Col>
{!loverCreatedAlready && <>
{!profileCreatedAlready && <>
<Col>
<label className={clsx(labelClassName)}>Username</label>
<Row className={'items-center gap-2'}>
@@ -128,7 +128,7 @@ export const RequiredLoveUserForm = (props: {
<label className={clsx(labelClassName)}>Bio</label>
<SignupBio
onChange={(e: JSONContent) => {
console.log('bio changed', e, lover.bio)
console.log('bio changed', e, profile.bio)
setProfile('bio', e)
}}
/>

View File

@@ -2,7 +2,7 @@ import clsx from 'clsx'
import { useEffect, useRef, useState } from 'react'
import { api } from 'web/lib/api'
import { countryCodeToFlag } from 'web/lib/util/location'
import { ProfileRow } from 'common/love/lover'
import { ProfileRow } from 'common/love/profile'
import {OriginLocation} from "common/filters";
export type City = {
@@ -15,15 +15,15 @@ export type City = {
longitude: number
}
export function loverToCity(lover: ProfileRow): City {
export function profileToCity(profile: ProfileRow): City {
return {
geodb_city_id: lover.geodb_city_id!,
city: lover.city,
region_code: lover.region_code!,
country: lover.country!,
geodb_city_id: profile.geodb_city_id!,
city: profile.city,
region_code: profile.region_code!,
country: profile.country!,
country_code: '',
latitude: lover.city_latitude!,
longitude: lover.city_longitude!,
latitude: profile.city_latitude!,
longitude: profile.city_longitude!,
}
}

View File

@@ -9,10 +9,10 @@ import { Tooltip } from 'web/components/widgets/tooltip'
import { Col } from 'web/components/layout/col'
import { MODAL_CLASS, Modal } from 'web/components/layout/modal'
import { Row } from 'web/components/layout/row'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
import { useUserById } from 'web/hooks/use-user-supabase'
import { MatchAvatars } from '../matches/match-avatars'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
import { useAPIGetter } from 'web/hooks/use-api-getter'
export const LikeButton = (props: {
@@ -36,8 +36,8 @@ export const LikeButton = (props: {
const like = async () => {
setShowConfirmation(false)
setIsLoading(true)
await api('like-lover', { targetUserId: targetId, remove: liked })
track('like lover', {
await api('like-profile', { targetUserId: targetId, remove: liked })
track('like profile', {
targetId,
remove: liked,
})

View File

@@ -3,8 +3,8 @@ import Image from 'next/image'
import Link from 'next/link'
import { UserIcon } from '@heroicons/react/solid'
import { Profile } from 'common/love/lover'
import { useProfileByUserId } from 'web/hooks/use-lover'
import { Profile } from 'common/love/profile'
import { useProfileByUserId } from 'web/hooks/use-profile'
import { Col } from 'web/components/layout/col'
import { Avatar, EmptyAvatar } from 'web/components/widgets/avatar'
import { Carousel } from 'web/components/widgets/carousel'
@@ -13,7 +13,7 @@ import { useUser } from 'web/hooks/use-user'
import { useUserById } from 'web/hooks/use-user-supabase'
import { SendMessageButton } from 'web/components/messaging/send-message-button'
import { ShipsList } from './ships-display'
import { Subtitle } from './lover-subtitle'
import { Subtitle } from './profile-subtitle'
import { LikeData, ShipData } from 'common/api/love-types'
export const LikesDisplay = (props: {
@@ -122,17 +122,17 @@ const LikesList = (props: { label: string; likes: LikeData[] }) => {
const UserAvatar = (props: { userId: string; className?: string }) => {
const { userId, className } = props
const lover = useProfileByUserId(userId)
const profile = useProfileByUserId(userId)
const user = useUserById(userId)
// console.log('UserAvatar', user?.username, lover?.pinned_url)
// console.log('UserAvatar', user?.username, profile?.pinned_url)
if (!lover)
if (!profile)
return <EmptyAvatar className={className} size={10} />
return (
<Avatar
className={className}
avatarUrl={lover.pinned_url}
avatarUrl={profile.pinned_url}
username={user?.username}
/>
)
@@ -143,14 +143,14 @@ export const MatchTile = (props: {
matchUserId: string
}) => {
const { matchUserId, profileProfile } = props
const lover = useProfileByUserId(matchUserId)
const profile = useProfileByUserId(matchUserId)
const user = useUserById(matchUserId)
const currentUser = useUser()
const isYourMatch = currentUser?.id === profileProfile.user_id
if (!lover || !user)
if (!profile || !user)
return <Col className="mb-2 h-[184px] w-[200px] shrink-0"></Col>
const { pinned_url } = lover
const { pinned_url } = profile
return (
<Col className="mb-2 w-[200px] shrink-0 overflow-hidden rounded">

View File

@@ -5,14 +5,14 @@ import clsx from 'clsx'
import { MODAL_CLASS, Modal } from 'web/components/layout/modal'
import { MatchAvatars } from '../matches/match-avatars'
import { Row } from 'web/components/layout/row'
import { Profile } from 'common/love/lover'
import { useProfileByUserId } from 'web/hooks/use-lover'
import { Profile } from 'common/love/profile'
import { useProfileByUserId } from 'web/hooks/use-profile'
import { Col } from 'web/components/layout/col'
import { EmptyAvatar, Avatar } from 'web/components/widgets/avatar'
import { Carousel } from 'web/components/widgets/carousel'
import { UserLink } from 'web/components/widgets/user-link'
import { useUser } from 'web/hooks/use-user'
import { Subtitle } from './lover-subtitle'
import { Subtitle } from './profile-subtitle'
import { ShipButton } from './ship-button'
import { hasShipped } from 'web/lib/util/ship-util'
import { ShipData } from 'common/api/love-types'
@@ -144,15 +144,15 @@ const ShipsTargetDisplay = (props: {
const UserAvatar = (props: { userId: string; className?: string }) => {
const { userId, className } = props
const lover = useProfileByUserId(userId)
const profile = useProfileByUserId(userId)
const user = useUserById(userId)
if (!lover || !lover.pinned_url)
if (!profile || !profile.pinned_url)
return <EmptyAvatar className={className} size={10} />
return (
<Avatar
className={className}
avatarUrl={lover.pinned_url}
avatarUrl={profile.pinned_url}
username={user?.username}
noLink
/>
@@ -162,14 +162,14 @@ const UserAvatar = (props: { userId: string; className?: string }) => {
const UserInfoRow = (props: { userId: string; className?: string }) => {
const { userId, className } = props
const user = useUserById(userId)
const lover = useProfileByUserId(userId)
const profile = useProfileByUserId(userId)
return (
<Row className={clsx(className, 'items-center gap-2')}>
{!lover || !lover.pinned_url ? (
{!profile || !profile.pinned_url ? (
<EmptyAvatar size={10} />
) : (
<Avatar avatarUrl={lover.pinned_url} username={user?.username} />
<Avatar avatarUrl={profile.pinned_url} username={user?.username} />
)}
{user && <UserLink user={user} hideBadge />}
</Row>

View File

@@ -6,7 +6,7 @@ import { api } from 'web/lib/api'
import { buttonClass } from 'web/components/buttons/button'
import { track } from 'web/lib/service/analytics'
import { Tooltip } from 'web/components/widgets/tooltip'
import { Profile } from 'common/love/lover'
import { Profile } from 'common/love/profile'
export const StarButton = (props: {
targetProfile: Profile
@@ -25,13 +25,13 @@ export const StarButton = (props: {
const star = async () => {
setIsStarred(!isStarred)
await api('star-lover', {
await api('star-profile', {
targetUserId: targetId,
remove: isStarred,
}).catch(() => {
setIsStarred(isStarred)
})
track('star lover', {
track('star profile', {
targetId,
remove: isStarred,
})

View File

@@ -36,7 +36,7 @@ export function useLiveCommentsOnProfile(userId: string) {
const getComments = async (userId: string) => {
const { data, error } = await db
.from('lover_comments')
.from('profile_comments')
.select('*')
.eq('on_user_id', userId)
if (error) {

View File

@@ -1,6 +1,6 @@
import { useProfile } from './use-lover'
import { useProfile } from './use-profile'
export const useIsLooking = () => {
const lover = useProfile()
return !!(lover && lover.looking_for_matches)
const profile = useProfile()
return !!(profile && profile.looking_for_matches)
}

View File

@@ -1,78 +0,0 @@
import {useUser} from 'web/hooks/use-user'
import {useEffect} from 'react'
import {Row} from 'common/supabase/utils'
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
import {User} from 'common/user'
import {getProfileRow, Profile, ProfileRow} from 'common/love/lover'
import {db} from 'web/lib/supabase/db'
import {usePersistentLocalState} from 'web/hooks/use-persistent-local-state'
export const useProfile = () => {
const user = useUser()
const [lover, setProfile] = usePersistentLocalState<
Row<'profiles'> | undefined | null
>(undefined, `lover-${user?.id}`)
const refreshProfile = () => {
if (user) {
console.log('Refreshing lover in useProfile for', user?.username, lover);
getProfileRow(user.id, db).then((lover) => {
if (!lover) setProfile(null)
else setProfile(lover)
})
}
}
useEffect(() => {
refreshProfile()
}, [user?.id])
return user && lover ? {...lover, user} : lover === null ? null : undefined
}
export const useProfileByUser = (user: User | undefined) => {
const userId = user?.id
const [lover, setProfile] = usePersistentInMemoryState<
Profile | undefined | null
>(undefined, `lover-user-${userId}`)
function refreshProfile() {
if (userId) {
console.log('Refreshing lover in useProfileByUser for', user?.username, lover);
getProfileRow(userId, db)
.then((lover) => {
if (!lover) setProfile(null)
else setProfile({...lover, user})
})
.catch(error => {
console.log('Warning: lover not found', user?.username, error);
setProfile(null)
return
});
console.log('End Refreshing lover for', user?.username, lover);
}
}
useEffect(() => {
refreshProfile()
}, [userId])
return {lover, refreshProfile}
}
export const useProfileByUserId = (userId: string | undefined) => {
const [lover, setProfile] = usePersistentInMemoryState<
ProfileRow | undefined | null
>(undefined, `lover-${userId}`)
useEffect(() => {
console.log('Refreshing lover in useProfileByUserId for', userId, lover);
if (userId)
getProfileRow(userId, db).then((lover) => {
if (!lover) setProfile(null)
else setProfile(lover)
})
}, [userId])
return lover
}

View File

@@ -1,18 +1,18 @@
import { useEffect } from 'react'
import { useProfile } from 'web/hooks/use-lover'
import { useProfile } from 'web/hooks/use-profile'
import { useIsAuthorized } from 'web/hooks/use-user'
import { run } from 'common/supabase/utils'
import { db } from 'web/lib/supabase/db'
export const useOnline = () => {
const lover = useProfile()
const profile = useProfile()
const isAuthed = useIsAuthorized()
useEffect(() => {
if (!lover || !isAuthed) return
if (!profile || !isAuthed) return
run(
db
.from('profiles')
.update({ last_online_time: new Date().toISOString() })
.eq('id', lover.id)
.eq('id', profile.id)
)
}, [])
}

78
web/hooks/use-profile.ts Normal file
View File

@@ -0,0 +1,78 @@
import {useUser} from 'web/hooks/use-user'
import {useEffect} from 'react'
import {Row} from 'common/supabase/utils'
import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state'
import {User} from 'common/user'
import {getProfileRow, Profile, ProfileRow} from 'common/love/profile'
import {db} from 'web/lib/supabase/db'
import {usePersistentLocalState} from 'web/hooks/use-persistent-local-state'
export const useProfile = () => {
const user = useUser()
const [profile, setProfile] = usePersistentLocalState<
Row<'profiles'> | undefined | null
>(undefined, `profile-${user?.id}`)
const refreshProfile = () => {
if (user) {
console.log('Refreshing profile in useProfile for', user?.username, profile);
getProfileRow(user.id, db).then((profile) => {
if (!profile) setProfile(null)
else setProfile(profile)
})
}
}
useEffect(() => {
refreshProfile()
}, [user?.id])
return user && profile ? {...profile, user} : profile === null ? null : undefined
}
export const useProfileByUser = (user: User | undefined) => {
const userId = user?.id
const [profile, setProfile] = usePersistentInMemoryState<
Profile | undefined | null
>(undefined, `profile-user-${userId}`)
function refreshProfile() {
if (userId) {
console.log('Refreshing profile in useProfileByUser for', user?.username, profile);
getProfileRow(userId, db)
.then((profile) => {
if (!profile) setProfile(null)
else setProfile({...profile, user})
})
.catch(error => {
console.log('Warning: profile not found', user?.username, error);
setProfile(null)
return
});
console.log('End Refreshing profile for', user?.username, profile);
}
}
useEffect(() => {
refreshProfile()
}, [userId])
return {profile, refreshProfile}
}
export const useProfileByUserId = (userId: string | undefined) => {
const [profile, setProfile] = usePersistentInMemoryState<
ProfileRow | undefined | null
>(undefined, `profile-${userId}`)
useEffect(() => {
console.log('Refreshing profile in useProfileByUserId for', userId, profile);
if (userId)
getProfileRow(userId, db).then((profile) => {
if (!profile) setProfile(null)
else setProfile(profile)
})
}, [userId])
return profile
}

View File

@@ -3,7 +3,7 @@ import { useEffect } from 'react'
import { usePersistentInMemoryState } from 'web/hooks/use-persistent-in-memory-state'
import { api } from 'web/lib/api'
import { APIResponse } from 'common/api/schema'
import { useProfileByUserId } from './use-lover'
import { useProfileByUserId } from './use-profile'
import { getProfilesCompatibilityFactor } from 'common/love/compatibility-score'
export const useCompatibleProfiles = (
@@ -14,7 +14,7 @@ export const useCompatibleProfiles = (
APIResponse<'compatible-profiles'> | undefined | null
>(undefined, `compatible-profiles-${userId}`)
const lover = useProfileByUserId(userId ?? undefined)
const profile = useProfileByUserId(userId ?? undefined)
useEffect(() => {
if (userId) {
@@ -30,10 +30,10 @@ export const useCompatibleProfiles = (
} else if (userId === null) setData(null)
}, [userId])
if (data && lover && options?.sortWithModifiers) {
if (data && profile && options?.sortWithModifiers) {
data.compatibleProfiles = sortBy(data.compatibleProfiles, (l) => {
const modifier = !lover ? 1 : getProfilesCompatibilityFactor(lover, l)
return -1 * modifier * data.loverCompatibilityScores[l.user.id].score
const modifier = !profile ? 1 : getProfilesCompatibilityFactor(profile, l)
return -1 * modifier * data.profileCompatibilityScores[l.user.id].score
})
}

View File

@@ -28,6 +28,6 @@ function curriedAPI<P extends APIPath>(path: P) {
return (params: APIParams<P>) => api(path, params)
}
export const updateProfile = curriedAPI('update-lover')
export const updateProfile = curriedAPI('update-profile')
export const updateUser = curriedAPI('me/update')
export const report = curriedAPI('report')

View File

@@ -1,15 +1,15 @@
import Router from 'next/router'
import { firebaseLogin } from 'web/lib/firebase/users'
import { db } from 'web/lib/supabase/db'
import { getProfileRow } from 'common/love/lover'
import { getProfileRow } from 'common/love/profile'
export const signupThenMaybeRedirectToSignup = async () => {
const creds = await firebaseLogin()
await Router.push('/')
const userId = creds?.user.uid
if (userId) {
const lover = await getProfileRow(userId, db)
if (!lover) {
const profile = await getProfileRow(userId, db)
if (!profile) {
await Router.push('/signup')
}
}

View File

@@ -3,7 +3,7 @@ import Router from 'next/router'
import Head from 'next/head'
import {useRouter} from 'next/router'
import {LovePage} from 'web/components/love-page'
import {useProfileByUser} from 'web/hooks/use-lover'
import {useProfileByUser} from 'web/hooks/use-profile'
import {Button} from 'web/components/buttons/button'
import {Col} from 'web/components/layout/col'
import {Row} from 'web/components/layout/row'
@@ -13,9 +13,9 @@ import {useTracking} from 'web/hooks/use-tracking'
import {BackButton} from 'web/components/back-button'
import {useSaveReferral} from 'web/hooks/use-save-referral'
import {getLoveOgImageUrl} from 'common/love/og-image'
import {getProfileRow, ProfileRow} from 'common/love/lover'
import {getProfileRow, ProfileRow} from 'common/love/profile'
import {db} from 'web/lib/supabase/db'
import {ProfileProfile} from 'web/components/profile/lover-profile'
import {ProfileProfile} from 'web/components/profile/profile-profile'
import {User} from 'common/user'
import {getUserForStaticProps} from 'common/supabase/users'
import {type GetStaticProps} from 'next'
@@ -58,12 +58,12 @@ export const getStaticProps: GetStaticProps<
}
}
const lover = await getProfileRow(user.id, db)
const profile = await getProfileRow(user.id, db)
return {
props: {
user,
username,
lover,
profile,
},
revalidate: 15,
}
@@ -82,7 +82,7 @@ type DeletedUserPageProps = {
type ActiveUserPageProps = {
user: User
username: string
lover: ProfileRow
profile: ProfileRow
}
export default function UserPage(props: UserPageProps) {
@@ -112,12 +112,12 @@ function UserPageInner(props: ActiveUserPageProps) {
useTracking('view love profile', {username: user?.username})
const [staticProfile] = useState(
props.lover && user ? {...props.lover, user: user} : null
props.profile && user ? {...props.profile, user: user} : null
)
const {lover: clientProfile, refreshProfile} = useProfileByUser(user)
const {profile: clientProfile, refreshProfile} = useProfileByUser(user)
// Show previous profile while loading another one
const lover = clientProfile ?? staticProfile
// console.log('lover:', user?.username, lover, clientProfile, staticProfile)
const profile = clientProfile ?? staticProfile
// console.log('profile:', user?.username, profile, clientProfile, staticProfile)
return (
<LovePage
@@ -129,7 +129,7 @@ function UserPageInner(props: ActiveUserPageProps) {
title={`${user.name} (@${user.username})`}
description={user.bio ?? ''}
url={`/${user.username}`}
image={getLoveOgImageUrl(user, lover)}
image={getLoveOgImageUrl(user, profile)}
/>
{(user.isBannedFromPosting || user.userDeleted) && (
<Head>
@@ -140,10 +140,10 @@ function UserPageInner(props: ActiveUserPageProps) {
{currentUser !== undefined && (
<Col className={'gap-4'}>
{lover ? (
{profile ? (
<ProfileProfile
key={lover.user_id}
lover={lover}
key={profile.user_id}
profile={profile}
user={user}
refreshProfile={refreshProfile}
fromSignup={fromSignup}

View File

@@ -1,9 +1,9 @@
import {Profile, ProfileRow} from 'common/love/lover'
import {Profile, ProfileRow} from 'common/love/profile'
import {Column} from 'common/supabase/utils'
import {User} from 'common/user'
import {OptionalLoveUserForm} from 'web/components/optional-lover-form'
import {RequiredLoveUserForm} from 'web/components/required-lover-form'
import {useProfileByUser} from 'web/hooks/use-lover'
import {OptionalLoveUserForm} from 'web/components/optional-profile-form'
import {RequiredLoveUserForm} from 'web/components/required-profile-form'
import {useProfileByUser} from 'web/hooks/use-profile'
import Router from 'next/router'
import {useEffect, useState} from 'react'
import {Col} from 'web/components/layout/col'
@@ -13,22 +13,22 @@ import {LovePage} from "web/components/love-page";
export default function ProfilePage() {
const user = useUser()
const {lover} = useProfileByUser(user ?? undefined)
const {profile} = useProfileByUser(user ?? undefined)
useEffect(() => {
if (user === null || lover === null) {
if (user === null || profile === null) {
Router.replace('/')
}
}, [user])
return user && lover && <ProfilePageInner user={user} lover={lover}/>
return user && profile && <ProfilePageInner user={user} profile={profile}/>
}
function ProfilePageInner(props: { user: User; lover: Profile }) {
function ProfilePageInner(props: { user: User; profile: Profile }) {
const {user} = props
const [lover, setProfile] = useState<Profile>({
...props.lover,
const [profile, setProfile] = useState<Profile>({
...props.profile,
user,
})
@@ -46,15 +46,15 @@ function ProfilePageInner(props: { user: User; lover: Profile }) {
<RequiredLoveUserForm
user={user}
setProfile={setProfileState}
lover={lover}
loverCreatedAlready={true}
profile={profile}
profileCreatedAlready={true}
isSubmitting={false}
setEditUsername={setUsername}
setEditDisplayName={setDisplayName}
/>
<div className={'h-4'}/>
<OptionalLoveUserForm
lover={lover}
profile={profile}
user={user}
setProfile={setProfileState}
buttonLabel={'Save'}

View File

@@ -9,7 +9,7 @@ import {createUserWithEmailAndPassword} from "firebase/auth";
import {auth} from "web/lib/firebase/users";
import FavIcon from "web/public/FavIcon";
import {LovePage} from "web/components/love-page";
import {getProfileRow} from "common/love/lover";
import {getProfileRow} from "common/love/profile";
import {db} from "web/lib/supabase/db";
import Router from "next/router";
import {useUser} from "web/hooks/use-user";
@@ -42,8 +42,8 @@ function RegisterComponent() {
useEffect(() => {
const checkProfileAndRedirect = async () => {
if (user) {
const lover = await getProfileRow(user.id, db)
if (lover) {
const profile = await getProfileRow(user.id, db)
if (profile) {
await Router.push('/')
} else {
await Router.push('/signup')

View File

@@ -7,7 +7,7 @@ import {auth, firebaseLogin} from "web/lib/firebase/users";
import FavIcon from "web/public/FavIcon";
import {signInWithEmailAndPassword} from "firebase/auth";
import {getProfileRow} from "common/love/lover";
import {getProfileRow} from "common/love/profile";
import {db} from "web/lib/supabase/db";
import Router from "next/router";
import {LovePage} from "web/components/love-page";
@@ -43,14 +43,14 @@ function RegisterComponent() {
if (user) {
console.log("User signed in:", user);
try {
const lover = await getProfileRow(user.id, db)
if (lover) {
const profile = await getProfileRow(user.id, db)
if (profile) {
await Router.push('/')
} else {
await Router.push('/signup')
}
} catch (error) {
console.error("Error fetching lover profile:", error);
console.error("Error fetching profile profile:", error);
}
setIsLoading(false);
setIsLoadingGoogle(false);

View File

@@ -1,7 +1,7 @@
import {useEffect, useState} from 'react'
import {Col} from 'web/components/layout/col'
import {initialRequiredState, RequiredLoveUserForm,} from 'web/components/required-lover-form'
import {OptionalLoveUserForm} from 'web/components/optional-lover-form'
import {initialRequiredState, RequiredLoveUserForm,} from 'web/components/required-profile-form'
import {OptionalLoveUserForm} from 'web/components/optional-profile-form'
import {useUser} from 'web/hooks/use-user'
import {LoadingIndicator} from 'web/components/widgets/loading-indicator'
import {CACHED_REFERRAL_USERNAME_KEY,} from 'web/lib/firebase/users'
@@ -12,8 +12,8 @@ import {useTracking} from 'web/hooks/use-tracking'
import {track} from 'web/lib/service/analytics'
import {safeLocalStorage} from 'web/lib/util/local'
import {removeNullOrUndefinedProps} from 'common/util/object'
import {useProfileByUserId} from 'web/hooks/use-lover'
import {ProfileRow} from 'common/love/lover'
import {useProfileByUserId} from 'web/hooks/use-profile'
import {ProfileRow} from 'common/love/profile'
import {LovePage} from "web/components/love-page";
import {Button} from "web/components/buttons/button";
@@ -25,7 +25,7 @@ export default function SignupPage() {
useTracking('view love signup page')
// Omit the id, created_time?
const [loverForm, setProfileForm] = useState<ProfileRow>({
const [profileForm, setProfileForm] = useState<ProfileRow>({
...initialRequiredState,
} as any)
const setProfileState = (key: keyof ProfileRow, value: any) => {
@@ -47,7 +47,7 @@ export default function SignupPage() {
<Col className={'w-full px-6 py-4'}>
<OptionalLoveUserForm
setProfile={setProfileState}
lover={loverForm}
profile={profileForm}
user={user}
fromSignup
/>
@@ -78,10 +78,10 @@ export default function SignupPage() {
<RequiredLoveUserForm
user={user}
setProfile={setProfileState}
lover={loverForm}
profile={profileForm}
isSubmitting={isSubmitting}
onSubmit={async () => {
if (!loverForm.looking_for_matches) {
if (!profileForm.looking_for_matches) {
router.push('/')
return
}
@@ -91,11 +91,11 @@ export default function SignupPage() {
: undefined
setIsSubmitting(true)
console.log('loverForm', loverForm)
const lover = await api(
'create-lover',
console.log('profileForm', profileForm)
const profile = await api(
'create-profile',
removeNullOrUndefinedProps({
...loverForm,
...profileForm,
referred_by_username: referredByUsername,
}) as any
).catch((e: unknown) => {
@@ -103,8 +103,8 @@ export default function SignupPage() {
return null
})
setIsSubmitting(false)
if (lover) {
setProfileForm(lover)
if (profile) {
setProfileForm(profile)
setStep(1)
scrollTo(0, 0)
track('submit love required profile')