Improve OG layout for scare profile

This commit is contained in:
MartinBraquet
2026-02-26 11:10:07 +01:00
parent 4015db7fda
commit 44d3e7577b
5 changed files with 133 additions and 55 deletions

View File

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

View File

@@ -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<string, any> | 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(','),
}

View File

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

View File

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

View File

@@ -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 (
<div
style={{
@@ -49,11 +54,11 @@ function OgProfile(props: ogProps) {
backgroundColor: '#f5f5f5',
}}
>
<div style={{display: 'flex', flex: 3}}>
<div style={{display: 'flex', flex: isLargerPicLayout ? 1 : 3}}>
{/* Left Column: Text */}
<div
style={{
flex: 3,
flex: isLargerPicLayout ? 1 : 3,
display: 'flex',
flexDirection: 'column',
gap: '10px',
@@ -65,28 +70,46 @@ function OgProfile(props: ogProps) {
{age && `, ${age}`}
</div>
{city && (
<div style={{display: 'flex', fontSize: '28px', marginBottom: '20px', opacity: 0.85}}>
{city}, {country}
<div
style={{
display: 'flex',
fontSize: '28px',
marginBottom: '20px',
marginTop: '20px',
opacity: 0.85,
}}
>
{city}
{country && `, ${country}`}
</div>
)}
{/*<div style={{display: 'flex', justifyContent: 'flex-end', alignItems: 'flex-start'}}>*/}
{/* <img src={'https://www.compassmeet.com/favicon.svg'} width={100} height={100} />*/}
{/*</div>*/}
<div style={{display: 'flex', gap: '10px', flexWrap: 'wrap'}}>
{allTags?.map(capitalize).map((tag, i) => (
<span
key={i}
style={{
padding: '8px 16px',
backgroundColor: '#ddd',
borderRadius: '20px',
fontSize: '24px',
}}
>
{tag.trim()}
</span>
))}
</div>
{allTags && (
<div style={{display: 'flex', gap: '10px', flexWrap: 'wrap'}}>
{allTags?.map(capitalize).map((tag, i) => (
<span
key={i}
style={{
padding: '8px 16px',
backgroundColor: '#ddd',
borderRadius: '20px',
fontSize: '24px',
}}
>
{tag.trim()}
</span>
))}
</div>
)}
{isLargerPicLayout && (
<div style={{display: 'flex'}}>
{headline && (
<div style={{display: 'flex', fontSize: '36px', marginTop: '40px'}}>{headline}</div>
)}
</div>
)}
</div>
{/* Right Column: Avatar */}
@@ -94,32 +117,49 @@ function OgProfile(props: ogProps) {
style={{
flex: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<img
src={avatarUrl || COMPASS_LOGO}
width={250}
height={250}
width={imgSize}
height={imgSize}
style={{borderRadius: 50, objectFit: 'cover'}}
alt="Avatar"
/>
{isLargerPicLayout && (
<div
style={{
display: 'flex',
fontSize: '48px',
fontWeight: 'semibold',
fontFamily: 'Georgia',
marginTop: '20px',
fontStyle: 'italic',
}}
>
compassmeet.com
</div>
)}
</div>
</div>
<div
style={{
flex: 2,
display: 'flex',
flexDirection: 'column',
marginBottom: '40px',
}}
>
{headline && (
<div style={{display: 'flex', fontSize: '36px', marginTop: '40px'}}>{headline}</div>
)}
</div>
{!isLargerPicLayout && (
<div
style={{
flex: 2,
display: 'flex',
flexDirection: 'column',
marginBottom: '40px',
}}
>
{headline && (
<div style={{display: 'flex', fontSize: '36px', marginTop: '40px'}}>{headline}</div>
)}
</div>
)}
</div>
)
}