Add profile card to profile

This commit is contained in:
MartinBraquet
2026-02-26 23:56:15 +01:00
parent 26bc68e4db
commit 0a2e4a7df1
9 changed files with 91 additions and 19 deletions

View File

@@ -8,7 +8,7 @@ android {
applicationId "com.compassconnections.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 42
versionCode 43
versionName "1.10.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {

View File

@@ -1248,5 +1248,7 @@
"profile.connect.interest_indicators_disabled": "{user} hat Interessenssignale deaktiviert",
"profile.connect.tips": "- Wählen Sie den Verbindungstyp, für den Sie offen sind.\n- Sie sehen dies nicht, es sei denn, sie wählen denselben Typ wie Sie.\n- Wenn Sie beide denselben Typ wählen, werden Sie beide benachrichtigt.",
"notifications.connection.mutual_title": "Es ist gegenseitig 🎉",
"notifications.connection.mutual_body": "Du und {name} sind beide an einem {type} interessiert. Beginnen Sie das Gespräch."
"notifications.connection.mutual_body": "Du und {name} sind beide an einem {type} interessiert. Beginnen Sie das Gespräch.",
"share_profile.on_x": "Auf X teilen",
"share_profile.on_linkedin": "Auf LinkedIn teilen"
}

View File

@@ -1247,5 +1247,7 @@
"profile.connect.interest_indicators_disabled": "{user} a désactivé les indicateurs d'intérêt",
"profile.connect.tips": "- Vous choisissez le type de relation auquel vous êtes ouvert.\n- Ils ne verront pas ceci à moins qu'ils ne choisissent le même type que vous.\n- Si vous choisissez tous les deux le même type de relation, vous serez tous les deux notifiés.",
"notifications.connection.mutual_title": "Cest mutuel 🎉",
"notifications.connection.mutual_body": "{name} et vous êtes tous deux intéressés par un(e) {type}. Commencez la conversation."
"notifications.connection.mutual_body": "{name} et vous êtes tous deux intéressés par un(e) {type}. Commencez la conversation.",
"share_profile.on_x": "Partager sur X",
"share_profile.on_linkedin": "Partager sur LinkedIn"
}

View File

@@ -194,6 +194,7 @@ export const shareOnLinkedIn = (profileUrl: string) => {
}
export const ShareProfileOnXButton = (props: {username: string; className?: string}) => {
const {username, className} = props
const t = useT()
return (
<Button
@@ -202,19 +203,21 @@ export const ShareProfileOnXButton = (props: {username: string; className?: stri
shareOnX(`https://compassmeet.com/${username}`, `Thoughtful connections > swiping.`)
}
>
Share on X
{t('share_profile.on_x', 'Share on X')}
</Button>
)
}
export const ShareProfileOnLinkedinButton = (props: {username: string; className?: string}) => {
const {username, className} = props
const t = useT()
return (
<Button
className={className}
onClick={() => shareOnLinkedIn(`https://compassmeet.com/${username}`)}
>
Share on LinkedIn
{t('share_profile.on_linkedin', 'Share on LinkedIn')}
</Button>
)
}

View File

@@ -4,6 +4,7 @@ import {Button} from 'web/components/buttons/button'
import {Col} from 'web/components/layout/col'
import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
import {Row} from 'web/components/layout/row'
import {ShareProfileButtons} from 'web/components/widgets/share-profile-button'
export const PhotosModal = (props: {
open: boolean
@@ -37,3 +38,48 @@ export const PhotosModal = (props: {
</Modal>
)
}
export const ExpandablePhoto = (props: {src: string; width?: number; height?: number}) => {
const {src, width = 1000, height = 1000} = props
const [open, setOpen] = useState<boolean>(false)
return (
<div className="">
<Image
src={src}
width={width}
height={height}
alt=""
className="cursor-pointer object-cover rounded-2xl"
onClick={() => setOpen(true)}
/>
<Modal open={open} setOpen={setOpen} size={'xl'}>
<Image src={src} width={1000} height={1000} alt="" className={'rounded-2xl'} />
</Modal>
</div>
)
}
export const PhotoButton = (props: {
src: string
username: string
width?: number
height?: number
}) => {
const {src, username, width = 1000, height = 1000} = props
const [open, setOpen] = useState<boolean>(false)
return (
<>
<Button onClick={() => setOpen(true)}>View Profile Card</Button>
<Modal open={open} setOpen={setOpen} size={'lg'} className={''}>
<Col className="gap-4 bg-canvas-100/75 rounded-2xl">
<Image src={src} width={width} height={height} alt="" className={'rounded-2xl'} />
<ShareProfileButtons
username={username}
className={'justify-center gap-4 text-3xl pb-4'}
buttonClassName={'hover:bg-canvas-200'}
/>
</Col>
</Modal>
</>
)
}

View File

@@ -118,7 +118,7 @@ export default function ProfileHeader(props: {
</Col>
</Row>
{currentUser && isCurrentUser ? (
<Row className={'items-center gap-1 sm:gap-2'}>
<Row className={'items-center gap-4'}>
<ShareProfileButton className="sm:flex" username={user.username} />
<Tooltip text={t('more_options_user.edit_profile', 'Edit profile')} noTap>
<Button

View File

@@ -1,4 +1,5 @@
import {JSONContent} from '@tiptap/core'
import {getProfileOgImageUrl} from 'common/profiles/og-image'
import {Profile} from 'common/profiles/profile'
import {UserActivity} from 'common/user'
import {ProfileAnswers} from 'web/components/answers/profile-answers'
@@ -6,6 +7,7 @@ import {ProfileBio} from 'web/components/bio/profile-bio'
import {Col} from 'web/components/layout/col'
import {Row} from 'web/components/layout/row'
import {SignUpButton} from 'web/components/nav/sidebar'
import {PhotoButton} from 'web/components/photos-modal'
import {ConnectActions} from 'web/components/profile/connect-actions'
import ProfileHeader from 'web/components/profile/profile-header'
import ProfileAbout from 'web/components/profile-about'
@@ -166,6 +168,9 @@ function ProfileContent(props: {
return (
<>
<div className={'w-fit mx-4 mb-2'}>
<PhotoButton src={getProfileOgImageUrl(user, profile)} username={user.username} />
</div>
<ProfileAbout profile={profile} userActivity={userActivity} isCurrentUser={isCurrentUser} />
<ProfileBio
isCurrentUser={isCurrentUser}

View File

@@ -1,6 +1,12 @@
import clsx from 'clsx'
import {ENV_CONFIG} from 'common/envs/constants'
import {ColorType} from 'web/components/buttons/button'
import {CopyLinkOrShareButton} from 'web/components/buttons/copy-link-button'
import {
CopyLinkOrShareButton,
ShareProfileOnLinkedinButton,
ShareProfileOnXButton,
} from 'web/components/buttons/copy-link-button'
import {Row} from 'web/components/layout/row'
import {useUser} from 'web/hooks/use-user'
import {useT} from 'web/lib/locale'
@@ -24,7 +30,24 @@ export const ShareProfileButton = (props: {
eventTrackingName="shareprofile"
color={color}
>
<div className="ml-2 text-sm">{t('button.share.label', 'Copy sharing link')}</div>
<div className="ml-2 text-sm">{t('button.share.label', 'Copy profile link')}</div>
</CopyLinkOrShareButton>
)
}
export const ShareProfileButtons = (props: {
username: string | undefined
className?: string
buttonClassName?: string
}) => {
const {username, className, buttonClassName} = props
if (!username) return
return (
<Row className={clsx('gap-4', className)}>
<ShareProfileOnXButton username={username} className={buttonClassName} />
<ShareProfileOnLinkedinButton username={username} className={buttonClassName} />
<ShareProfileButton username={username} color={'gray-outline'} className={buttonClassName} />
</Row>
)
}

View File

@@ -2,15 +2,10 @@ import {getProfileOgImageUrl} from 'common/profiles/og-image'
import Image from 'next/image'
import Router from 'next/router'
import {Button} from 'web/components/buttons/button'
import {
ShareProfileOnLinkedinButton,
ShareProfileOnXButton,
} from 'web/components/buttons/copy-link-button'
import {Col} from 'web/components/layout/col'
import {Row} from 'web/components/layout/row'
import {PageBase} from 'web/components/page-base'
import {SEO} from 'web/components/SEO'
import {ShareProfileButton} from 'web/components/widgets/share-profile-button'
import {ShareProfileButtons} from 'web/components/widgets/share-profile-button'
import {useProfile} from 'web/hooks/use-profile'
import {useUser} from 'web/hooks/use-user'
import {useT} from 'web/lib/locale'
@@ -58,11 +53,7 @@ export default function SoftGatePage() {
'You created a public profile card and values-based profile. Share them to attract people who think like you. Shared profiles are discovered much more often.',
)}
</p>
<Row className={'gap-4'}>
<ShareProfileOnXButton username={user?.username} />
<ShareProfileOnLinkedinButton username={user?.username} />
<ShareProfileButton username={user?.username} color={'gray-outline'} />
</Row>
<ShareProfileButtons username={user?.username} />
</Col>
)}