import type { Metadata } from "next"; import Link from "next/link"; import Image from "next/image"; import { notFound } from "next/navigation"; import { profileService } from "@/server/services/profile.service"; import { trustService } from "@/server/services/trust.service"; import { reviewService } from "@/server/services/review.service"; import { TripCard } from "@/features/trip/components/trip-card"; import { ProfileTripRow } from "@/features/profile/components/profile-trip-row"; import { OrganizerStatsPanel } from "@/features/profile/components/organizer-stats-panel"; import { OrganizerReviewsList } from "@/features/review/components/organizer-reviews-list"; import { siteConfig } from "@/lib/site"; import { vibeMeta } from "@/lib/vibe"; interface PageProps { params: Promise<{ id: string }>; } export async function generateMetadata({ params, }: PageProps): Promise { const { id } = await params; const data = await profileService.getPublicProfile(id); if (!data) { return { title: "Profil tidak ditemukan", robots: { index: false } }; } const { user } = data; const title = `${user.name} — Profil`; const desc = user.profile?.bio?.slice(0, 160) || `Lihat profil ${user.name} di ${siteConfig.name}: trip yang dibuat, trip yang diikuti, dan minat aktivitas.`; return { title, description: desc, alternates: { canonical: `/u/${id}` }, openGraph: { title, description: desc, url: `/u/${id}` }, }; } export default async function PublicProfilePage({ params }: PageProps) { const { id } = await params; const data = await profileService.getPublicProfile(id); if (!data) notFound(); const { user, isVerifiedOrganizer, organizedTrips, joinedTrips } = data; const profile = user.profile; const memberSince = new Date(user.createdAt).toLocaleDateString("id-ID", { month: "long", year: "numeric", }); // Trust panel hanya relevan untuk user yang berperan organizer. // Hindari query Prisma yang nggak perlu untuk user yang murni peserta. const isOrganizerProfile = organizedTrips.length > 0 || isVerifiedOrganizer; const [organizerTrust, organizerReviews] = isOrganizerProfile ? await Promise.all([ trustService.getOrganizerTrust(user.id), reviewService.getReviewsByOrganizer(user.id), ]) : [null, []]; return (
{/* Header */}
{user.image ? ( {user.name} ) : (
{user.name.charAt(0).toUpperCase()}
)}

{user.name}

{isVerifiedOrganizer && ( ✅ Verified Organizer )}
{profile?.city && ( 📍 {profile.city} )} Bergabung sejak {memberSince}
{profile?.bio && (

{profile.bio}

)} {profile?.vibe && (
{vibeMeta(profile.vibe).icon} Vibe: {vibeMeta(profile.vibe).label}
)} {profile?.interests && profile.interests.length > 0 && (
{profile.interests.map((tag) => ( #{tag} ))}
)} {profile?.instagram && ( 📸 @{profile.instagram} )}

{organizedTrips.length}

Trip dibuat

{joinedTrips.length}

Trip diikuti

{organizedTrips.length + joinedTrips.length}

Total perjalanan

{organizerTrust && } {organizerTrust && organizerReviews.length > 0 && ( )} {/* Empty profile hint */} {!profile && (

{user.name} belum melengkapi profil sosial — bio, kota, & minat akan muncul di sini setelah diisi.

)} {/* Trip dibuat */} {organizedTrips.length > 0 && (

Trip yang dibuat ({organizedTrips.length})

{organizedTrips.map((trip) => ( ))}
)} {/* Trip diikuti */} {joinedTrips.length > 0 && (

Trip yang diikuti ({joinedTrips.length})

    {joinedTrips.map((trip) => (
  • bareng{" "} {trip.organizer.name} } />
  • ))}
)} {/* Empty state */} {organizedTrips.length === 0 && joinedTrips.length === 0 && (

Belum ada trip yang dibuat atau diikuti.

)}
); }