add user profile, profile vibe and trip vibe and social signal
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user