import type { Metadata } from "next"; import Link from "next/link"; import Image from "next/image"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; import { tripService } from "@/server/services/trip.service"; import { profileRepo } from "@/server/repositories/profile.repo"; import { TripCard } from "@/features/trip/components/trip-card"; import { siteConfig, siteUrl, absoluteUrl } from "@/lib/site"; import { ACTIVITY_CATEGORIES, categoryMeta } from "@/lib/activity-category"; import { Compass, Flame, Mountain, Handshake, Tent, Plus, type LucideIcon, } from "lucide-react"; type OpenTrip = Awaited>[number]; function mapParticipants(trip: OpenTrip) { return trip.participants.map((p) => ({ id: p.id, name: p.user.name, image: p.user.image, interests: p.user.profile?.interests ?? [], })); } export const metadata: Metadata = { title: "Cari Teman Trip & Aktivitas — Pergi Bareng, Bukan Sendiri", description: `${siteConfig.slogan} ${siteConfig.description}`, alternates: { canonical: "/" }, openGraph: { title: `${siteConfig.name} — Cari Teman Trip & Aktivitas, Gabung Bareng`, description: siteConfig.slogan, url: "/", }, }; export default async function HomePage() { const session = await getServerSession(authOptions); const [trips, viewerProfile] = await Promise.all([ tripService.getOpenTrips(), session?.user?.id ? profileRepo.findByUserId(session.user.id) : Promise.resolve(null), ]); const viewerInterests = viewerProfile?.interests ?? []; const now = new Date(); const nextWeek = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); // Social proof: total orang yang sudah gabung di seluruh open trip. const joinerCount = trips.reduce((sum, t) => sum + t._count.participants, 0); const upcomingTrips = trips .filter((t) => new Date(t.date) <= nextWeek) .slice(0, 3); const upcomingIds = new Set(upcomingTrips.map((t) => t.id)); const latestTrips = trips .filter((t) => !upcomingIds.has(t.id)) .slice(0, 6); const shownIds = new Set([...upcomingIds, ...latestTrips.map((t) => t.id)]); // Section sosial: trip yang paling ramai joiner-nya (social proof, bukan price proof). const buzzingTrips = trips .filter((t) => !shownIds.has(t.id) && t._count.participants > 0) .sort((a, b) => b._count.participants - a._count.participants) .slice(0, 3); const orgJsonLd = { "@context": "https://schema.org", "@graph": [ { "@type": "Organization", "@id": `${siteUrl}/#organization`, name: siteConfig.name, url: siteUrl, logo: absoluteUrl("/images/SeTrip.png"), slogan: siteConfig.slogan, description: siteConfig.description, }, { "@type": "WebSite", "@id": `${siteUrl}/#website`, url: siteUrl, name: siteConfig.name, description: siteConfig.description, publisher: { "@id": `${siteUrl}/#organization` }, inLanguage: "id-ID", potentialAction: { "@type": "SearchAction", target: `${siteUrl}/trips?q={search_term_string}`, "query-input": "required name=search_term_string", }, }, ], }; return (