Files
2026-05-21 11:59:02 +07:00

111 lines
3.8 KiB
TypeScript

import type { Metadata } from "next";
import { Suspense } from "react";
import { profileService } from "@/server/services/profile.service";
import { UserCard } from "@/features/profile/components/user-card";
import { PeopleFilter } from "@/features/profile/components/people-filter";
import { isVibe, vibeLabel } from "@/lib/vibe";
import { siteConfig } from "@/lib/site";
import { Users } from "lucide-react";
interface PeoplePageProps {
searchParams: Promise<{
city?: string;
interest?: string;
vibe?: string;
}>;
}
export async function generateMetadata({
searchParams,
}: PeoplePageProps): Promise<Metadata> {
const { city, interest, vibe: vibeParam } = await searchParams;
const vibe = isVibe(vibeParam) ? vibeParam : undefined;
const parts: string[] = [];
if (vibe) parts.push(`Vibe ${vibeLabel(vibe).toLowerCase()}`);
if (city) parts.push(`di ${city}`);
if (interest) parts.push(`#${interest.toLowerCase()}`);
const title = parts.length
? `Cari Teman ${parts.join(" ")}`
: "Cari Teman Aktivitas — Profil Anggota";
const description = `Telusuri profil anggota ${siteConfig.name} berdasarkan minat, kota, dan vibe. Temukan calon teman trip dengan ritme yang cocok sebelum gabung bareng.`;
return {
title,
description,
alternates: { canonical: "/people" },
openGraph: { title, description, url: "/people" },
};
}
export default async function PeoplePage({ searchParams }: PeoplePageProps) {
const params = await searchParams;
const vibe = isVibe(params.vibe) ? params.vibe : undefined;
const filters = {
city: params.city?.trim() || undefined,
interest: params.interest?.trim().toLowerCase() || undefined,
vibe,
};
const hasFilters = Boolean(filters.city || filters.interest || filters.vibe);
const people = await profileService.findPeople(filters);
return (
<div className="mx-auto max-w-6xl px-4 py-6 sm:py-8">
<div className="mb-5 flex flex-col gap-2 sm:mb-6">
<h1 className="text-xl font-bold text-neutral-800 sm:text-2xl">
Cari Teman Aktivitas
</h1>
<p className="text-sm text-neutral-500">
{hasFilters
? `${people.length} orang ditemukan dengan filter di atas`
: `${people.length} anggota dengan profil sosial — kenali dulu sebelum gabung trip`}
</p>
</div>
<div className="mb-6">
<Suspense fallback={null}>
<PeopleFilter />
</Suspense>
</div>
{people.length === 0 ? (
<div className="rounded-2xl border-2 border-dashed border-neutral-200 bg-white p-8 text-center sm:p-14">
<div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-primary-50 sm:h-16 sm:w-16">
<Users
size={26}
strokeWidth={1.75}
aria-hidden
className="text-primary-600"
/>
</div>
<p className="mb-1 text-base font-bold text-neutral-800 sm:text-lg">
{hasFilters
? "Belum ada anggota yang cocok"
: "Belum ada anggota dengan profil terisi"}
</p>
<p className="text-sm text-neutral-500">
{hasFilters
? "Coba longgarkan filter — kota, minat, atau vibe."
: "Setelah anggota lain mengisi profil, mereka akan muncul di sini."}
</p>
</div>
) : (
<ul className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{people.map((u) => (
<li key={u.id}>
<UserCard
id={u.id}
name={u.name}
image={u.image}
isVerifiedOrganizer={
u.organizerVerification?.status === "APPROVED"
}
profile={u.profile}
/>
</li>
))}
</ul>
)}
</div>
);
}