105 lines
3.7 KiB
TypeScript
105 lines
3.7 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";
|
|
|
|
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 text-2xl sm:h-16 sm:w-16 sm:text-3xl">
|
|
🔍
|
|
</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>
|
|
);
|
|
}
|