From 44d3e7577b402c7caf8f9df6b768286d834bd881 Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Thu, 26 Feb 2026 11:10:07 +0100 Subject: [PATCH] Improve OG layout for scare profile --- common/src/geodb.ts | 21 ++++ common/src/profiles/og-image.ts | 42 ++++++-- web/components/profile-about.tsx | 2 +- web/components/profile/profile-location.tsx | 17 +--- web/pages/api/og/profile.tsx | 106 ++++++++++++++------ 5 files changed, 133 insertions(+), 55 deletions(-) diff --git a/common/src/geodb.ts b/common/src/geodb.ts index 911705b4..f81943ad 100644 --- a/common/src/geodb.ts +++ b/common/src/geodb.ts @@ -1,3 +1,5 @@ +import {ProfileRow} from 'common/profiles/profile' + export const geodbHost = 'wft-geo-db.p.rapidapi.com' export const geodbFetch = async (endpoint: string) => { @@ -29,3 +31,22 @@ export const geodbFetch = async (endpoint: string) => { return {status: 'failure', data: error} } } +export function getLocationText( + profile: ProfileRow | undefined | null, + prefix?: string | undefined | null, +) { + if (!profile) return + prefix = prefix ?? '' + const city = profile[`${prefix}city` as keyof ProfileRow] + const country = profile[`${prefix}country` as keyof ProfileRow] + const regionCode = profile[`${prefix}region_code` as keyof ProfileRow] + console.log({city, country, regionCode}) + + const stateOrCountry = country === 'United States of America' ? regionCode : country + + if (!city) { + return null + } + + return `${city}${stateOrCountry && ', '}${stateOrCountry}` +} diff --git a/common/src/profiles/og-image.ts b/common/src/profiles/og-image.ts index 0fa79ee0..5bc88b9b 100644 --- a/common/src/profiles/og-image.ts +++ b/common/src/profiles/og-image.ts @@ -1,5 +1,6 @@ import {JSONContent} from '@tiptap/core' -import {ProfileRow} from 'common/profiles/profile' +import {getLocationText} from 'common/geodb' +import {Profile} from 'common/profiles/profile' import {User} from 'common/user' import {buildOgUrl} from 'common/util/og' import {parseJsonContentToText} from 'common/util/parse' @@ -20,17 +21,46 @@ export type ogProps = { keywords: string | string[] } -export function getProfileOgImageUrl(user: User, profile?: ProfileRow | null) { +type NestedStringArray = (string | NestedStringArray | undefined | null)[] + +export const flatten = (arr: NestedStringArray, separator: string = ', '): string => + arr + .flatMap((item) => (Array.isArray(item) ? [flatten(item, separator)] : [item])) + .filter((item): item is string => item != null && item !== '') + .join(separator) + +export function getProfileOgImageUrl( + user: User, + profile?: Profile | null, + // choicesIdsToLabels?: Record | null, +) { + console.log({profile}) + const headline = + profile?.headline || + parseJsonContentToText(profile?.bio as JSONContent) || + flatten( + [ + // profile?.interests?.map((id: string) => choicesIdsToLabels?.['interests']?.[id]), + // profile?.causes?.map((id: string) => choicesIdsToLabels?.['causes']?.[id]), + // profile?.work?.map((id: string) => choicesIdsToLabels?.['work']?.[id]), + profile?.occupation_title, + profile?.education_level, + profile?.university, + profile?.mbti, + profile?.religion, + profile?.political_beliefs, + profile?.languages, + ], + ' • ', + ) const props = { avatarUrl: profile?.pinned_url, username: user.username, name: user.name, age: profile?.age?.toString() ?? '', - city: profile?.city ?? '', - country: profile?.country ?? '', + city: getLocationText(profile) ?? '', gender: profile?.gender ?? '', - headline: - profile?.headline || parseJsonContentToText(profile?.bio as JSONContent)?.slice(0, 500) || '', + headline: headline.slice(0, 500), interests: '', keywords: (profile?.keywords ?? []).join(','), } diff --git a/web/components/profile-about.tsx b/web/components/profile-about.tsx index 4c789f3d..27644328 100644 --- a/web/components/profile-about.tsx +++ b/web/components/profile-about.tsx @@ -11,6 +11,7 @@ import { } from 'common/choices' import {MAX_INT, MIN_INT} from 'common/constants' import {convertGenderPlural, Gender} from 'common/gender' +import {getLocationText} from 'common/geodb' import {formatHeight, MeasurementSystem} from 'common/measurement-utils' import {Profile} from 'common/profiles/profile' import {UserActivity} from 'common/user' @@ -30,7 +31,6 @@ import {RiScales3Line} from 'react-icons/ri' import {TbBulb, TbCheck, TbMoodSad, TbUsers} from 'react-icons/tb' import {Col} from 'web/components/layout/col' import {Row} from 'web/components/layout/row' -import {getLocationText} from 'web/components/profile/profile-location' import {UserHandles} from 'web/components/user/user-handles' import {useChoices} from 'web/hooks/use-choices' import {useLocale, useT} from 'web/lib/locale' diff --git a/web/components/profile/profile-location.tsx b/web/components/profile/profile-location.tsx index 2a73ffb9..4559df1d 100644 --- a/web/components/profile/profile-location.tsx +++ b/web/components/profile/profile-location.tsx @@ -1,23 +1,10 @@ +import {getLocationText} from 'common/geodb' import {Profile} from 'common/profiles/profile' import {IoLocationOutline} from 'react-icons/io5' import {IconWithInfo} from 'web/components/icons' -export function getLocationText(profile: Profile, prefix?: string) { - const city = profile[`${prefix}city` as keyof Profile] - const country = profile[`${prefix}country` as keyof Profile] - const regionCode = profile[`${prefix}region_code` as keyof Profile] - - const stateOrCountry = country === 'United States of America' ? regionCode : country - - if (!city) { - return null - } - - return `${city}${stateOrCountry && ', '}${stateOrCountry}` -} - export function ProfileLocation(props: {profile: Profile; prefix?: string}) { - const {profile, prefix = ''} = props + const {profile, prefix} = props const text = getLocationText(profile, prefix) diff --git a/web/pages/api/og/profile.tsx b/web/pages/api/og/profile.tsx index 7b84cffc..083660a5 100644 --- a/web/pages/api/og/profile.tsx +++ b/web/pages/api/og/profile.tsx @@ -35,8 +35,13 @@ function OgProfile(props: ogProps) { headline = headline.slice(0, maxChars) + '...' } + const totalChars = (headline?.length || 0) + (allTags?.join(' ')?.length || 0) + name.length * 3 + + const isLargerPicLayout = totalChars < 220 + console.log(props) + const imgSize = isLargerPicLayout ? 400 : 250 return (
-
+
{/* Left Column: Text */}
{city && ( -
- {city}, {country} +
+ {city} + {country && `, ${country}`}
)} {/*
*/} {/* */} {/*
*/} -
- {allTags?.map(capitalize).map((tag, i) => ( - - {tag.trim()} - - ))} -
+ {allTags && ( +
+ {allTags?.map(capitalize).map((tag, i) => ( + + {tag.trim()} + + ))} +
+ )} + {isLargerPicLayout && ( +
+ {headline && ( +
{headline}
+ )} +
+ )}
{/* Right Column: Avatar */} @@ -94,32 +117,49 @@ function OgProfile(props: ogProps) { style={{ flex: 1, display: 'flex', + flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }} > Avatar + {isLargerPicLayout && ( +
+ compassmeet.com +
+ )}
-
- {headline && ( -
{headline}
- )} -
+ {!isLargerPicLayout && ( +
+ {headline && ( +
{headline}
+ )} +
+ )}
) }