add user profile, profile vibe and trip vibe and social signal
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { vibeMeta } from "@/lib/vibe";
|
||||
import type { Vibe } from "@/app/generated/prisma/enums";
|
||||
|
||||
interface UserCardProps {
|
||||
id: string;
|
||||
name: string;
|
||||
image: string | null;
|
||||
isVerifiedOrganizer: boolean;
|
||||
profile: {
|
||||
bio: string | null;
|
||||
city: string | null;
|
||||
interests: string[];
|
||||
vibe: Vibe | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export function UserCard({
|
||||
id,
|
||||
name,
|
||||
image,
|
||||
isVerifiedOrganizer,
|
||||
profile,
|
||||
}: UserCardProps) {
|
||||
const interests = profile?.interests ?? [];
|
||||
return (
|
||||
<Link
|
||||
href={`/u/${id}`}
|
||||
className="group flex h-full flex-col rounded-2xl border border-neutral-200 bg-white p-4 shadow-sm transition-all hover:-translate-y-0.5 hover:border-primary-300 hover:shadow-md"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
{image ? (
|
||||
<Image
|
||||
src={image}
|
||||
alt=""
|
||||
width={56}
|
||||
height={56}
|
||||
className="h-14 w-14 shrink-0 rounded-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-full bg-primary-600 text-lg font-bold text-white">
|
||||
{name.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-bold text-neutral-800 group-hover:text-primary-700">
|
||||
{name}
|
||||
</p>
|
||||
{profile?.city && (
|
||||
<p className="truncate text-[11px] text-neutral-500 sm:text-xs">
|
||||
📍 {profile.city}
|
||||
</p>
|
||||
)}
|
||||
<div className="mt-1 flex flex-wrap gap-1">
|
||||
{isVerifiedOrganizer && (
|
||||
<span
|
||||
className="inline-flex items-center gap-0.5 rounded-full bg-primary-100 px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-primary-800"
|
||||
title="Organizer terverifikasi"
|
||||
>
|
||||
✅ Organizer
|
||||
</span>
|
||||
)}
|
||||
{profile?.vibe && (
|
||||
<span
|
||||
className="inline-flex items-center gap-0.5 rounded-full bg-secondary-100 px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-secondary-800"
|
||||
title={vibeMeta(profile.vibe).description}
|
||||
>
|
||||
<span aria-hidden>{vibeMeta(profile.vibe).icon}</span>
|
||||
<span>{vibeMeta(profile.vibe).label}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{profile?.bio && (
|
||||
<p className="mt-3 line-clamp-2 text-xs leading-relaxed text-neutral-600">
|
||||
{profile.bio}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{interests.length > 0 && (
|
||||
<div className="mt-3 flex flex-wrap gap-1">
|
||||
{interests.slice(0, 5).map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="rounded-full bg-secondary-50 px-2 py-0.5 text-[10px] font-medium text-secondary-700"
|
||||
>
|
||||
#{tag}
|
||||
</span>
|
||||
))}
|
||||
{interests.length > 5 && (
|
||||
<span className="text-[10px] text-neutral-400">
|
||||
+{interests.length - 5}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user