165 lines
5.1 KiB
TypeScript
165 lines
5.1 KiB
TypeScript
"use client";
|
|
|
|
import Image from "next/image";
|
|
import { Camera, ImageIcon, LockKeyhole, MessageCircle, Sparkles } from "lucide-react";
|
|
|
|
import { MobileShell } from "@/app/_components/core";
|
|
import { useAppNavigator } from "@/router/use-app-navigator";
|
|
|
|
import styles from "./profile-screen.module.css";
|
|
|
|
const PROFILE = {
|
|
name: "Elio Silvestri",
|
|
handle: "@elio.private",
|
|
avatar: "/images/chat/pic-chat-elio.png",
|
|
postsCount: 10,
|
|
cta: "Join Me, unlock my private zoom",
|
|
bio: "Soft moments, private photos, and a little sweetness just for you.",
|
|
} as const;
|
|
|
|
const POSTS = [
|
|
{
|
|
id: "private-zoom-1",
|
|
timeAgo: "1 day ago",
|
|
price: "XXX coins",
|
|
photoCount: "7 photos",
|
|
},
|
|
{
|
|
id: "private-zoom-2",
|
|
timeAgo: "30 days ago",
|
|
price: "XXX coins",
|
|
photoCount: "7 photos",
|
|
},
|
|
] as const;
|
|
|
|
export function ProfileScreen() {
|
|
const navigator = useAppNavigator();
|
|
|
|
const openVipSubscription = () => {
|
|
navigator.openSubscription({ type: "vip" });
|
|
};
|
|
|
|
return (
|
|
<MobileShell background="#fff7ed">
|
|
<main className={styles.shell}>
|
|
<div className={styles.backgroundGlowOne} />
|
|
<div className={styles.backgroundGlowTwo} />
|
|
|
|
<section className={styles.hero} aria-labelledby="profile-title">
|
|
<div className={styles.heroTopline}>
|
|
<span className={styles.liveDot} aria-hidden="true" />
|
|
<span>Private zoom is open</span>
|
|
</div>
|
|
|
|
<div className={styles.identity}>
|
|
<div className={styles.avatarFrame}>
|
|
<Image
|
|
src={PROFILE.avatar}
|
|
alt={PROFILE.name}
|
|
width={72}
|
|
height={72}
|
|
priority
|
|
/>
|
|
</div>
|
|
|
|
<div className={styles.identityText}>
|
|
<h1 id="profile-title" className={styles.title}>
|
|
{PROFILE.name}
|
|
</h1>
|
|
<p className={styles.handle}>{PROFILE.handle}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<p className={styles.bio}>{PROFILE.bio}</p>
|
|
|
|
<button
|
|
type="button"
|
|
className={styles.primaryCta}
|
|
onClick={openVipSubscription}
|
|
>
|
|
<Sparkles size={16} aria-hidden="true" />
|
|
<span>{PROFILE.cta}</span>
|
|
</button>
|
|
</section>
|
|
|
|
<section className={styles.postsSection} aria-labelledby="posts-title">
|
|
<div className={styles.sectionHeader}>
|
|
<div>
|
|
<p className={styles.kicker}>Posts</p>
|
|
<h2 id="posts-title" className={styles.sectionTitle}>
|
|
Private moments
|
|
</h2>
|
|
</div>
|
|
<span className={styles.postCount}>{PROFILE.postsCount}</span>
|
|
</div>
|
|
|
|
<div className={styles.timeline}>
|
|
{POSTS.map((post, index) => (
|
|
<article
|
|
key={post.id}
|
|
className={styles.postCard}
|
|
style={{ "--reveal-index": index } as React.CSSProperties}
|
|
>
|
|
<header className={styles.postHeader}>
|
|
<div className={styles.postAuthor}>
|
|
<Image
|
|
src={PROFILE.avatar}
|
|
alt=""
|
|
width={38}
|
|
height={38}
|
|
className={styles.postAvatar}
|
|
/>
|
|
<div>
|
|
<p className={styles.authorName}>{PROFILE.name}</p>
|
|
<p className={styles.authorSubline}>Private zoom drop</p>
|
|
</div>
|
|
</div>
|
|
<time className={styles.postTime}>{post.timeAgo}</time>
|
|
</header>
|
|
|
|
<button
|
|
type="button"
|
|
className={styles.lockedPreview}
|
|
onClick={openVipSubscription}
|
|
aria-label={`Unlock ${post.photoCount} from ${PROFILE.name}`}
|
|
>
|
|
<div className={styles.previewIcon}>
|
|
<LockKeyhole size={18} aria-hidden="true" />
|
|
</div>
|
|
<div className={styles.previewText}>
|
|
<strong>{post.price}</strong>
|
|
<span>Unlock to view</span>
|
|
<small>
|
|
<ImageIcon size={13} aria-hidden="true" />
|
|
{post.photoCount}
|
|
</small>
|
|
</div>
|
|
</button>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<nav className={styles.bottomNav} aria-label="Profile navigation">
|
|
<button
|
|
type="button"
|
|
className={styles.navButton}
|
|
onClick={() => navigator.openChat({ replace: false })}
|
|
>
|
|
<MessageCircle size={20} aria-hidden="true" />
|
|
<span>Chat</span>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className={`${styles.navButton} ${styles.navButtonActive}`}
|
|
aria-current="page"
|
|
>
|
|
<Camera size={20} aria-hidden="true" />
|
|
<span>Elio Private zoom</span>
|
|
</button>
|
|
</nav>
|
|
</main>
|
|
</MobileShell>
|
|
);
|
|
}
|