2026-09-15 23:26:24 +03:30
|
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
|
|
import { useEffect, useState, useCallback } from "react";
|
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
|
import { ChevronLeft, UserCheck } from "lucide-react";
|
|
|
|
|
|
import { Card } from "@/components/ui/Card";
|
|
|
|
|
|
import { Avatar } from "@/components/ui/Avatar";
|
|
|
|
|
|
import { Badge } from "@/components/ui/Badge";
|
|
|
|
|
|
import { EmptyState } from "@/components/ui/EmptyState";
|
|
|
|
|
|
import { FullScreenLoader } from "@/components/ui/FullScreenLoader";
|
|
|
|
|
|
import { ErrorBanner } from "@/components/ui/ErrorBanner";
|
|
|
|
|
|
import { formatApiError } from "@/lib/hooks";
|
|
|
|
|
|
import { calcAge } from "@/lib/utils";
|
2026-09-26 18:10:31 +03:30
|
|
|
|
import { PendingUserView, listPendingUsers, photoUrl } from "@/lib/api";
|
2026-09-15 23:26:24 +03:30
|
|
|
|
|
|
|
|
|
|
export default function PendingUsersPage() {
|
2026-09-26 18:10:31 +03:30
|
|
|
|
const [users, setUsers] = useState<PendingUserView[] | null>(null);
|
2026-09-15 23:26:24 +03:30
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
const load = useCallback(async () => {
|
|
|
|
|
|
setError(null);
|
|
|
|
|
|
try {
|
|
|
|
|
|
setUsers(await listPendingUsers());
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
setError(formatApiError(err));
|
|
|
|
|
|
}
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
|
|
|
|
load();
|
|
|
|
|
|
}, [load]);
|
|
|
|
|
|
|
|
|
|
|
|
if (error && !users) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="max-w-2xl">
|
|
|
|
|
|
<ErrorBanner message={error} />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!users) return <FullScreenLoader />;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="flex flex-col gap-6 max-w-3xl">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h1 className="font-[var(--font-display)] font-extrabold text-[24px]">
|
|
|
|
|
|
کاربران در انتظار تایید ✅
|
|
|
|
|
|
</h1>
|
|
|
|
|
|
<p className="text-[14px] text-(--color-content-secondary) mt-1">
|
|
|
|
|
|
این کاربرها آنبوردینگ رو کامل کردن و منتظرن پروفایلشون بررسی بشه. قدیمیترین
|
|
|
|
|
|
درخواست بالاتره.
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{users.length === 0 ? (
|
|
|
|
|
|
<Card>
|
|
|
|
|
|
<EmptyState
|
|
|
|
|
|
icon={<UserCheck size={32} />}
|
|
|
|
|
|
title="کسی منتظر بررسی نیست"
|
|
|
|
|
|
description="هر وقت کاربر جدیدی آنبوردینگ رو تموم کنه، اینجا برای بررسی نشون داده میشه."
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<Card padded={false} className="overflow-hidden">
|
|
|
|
|
|
{users.map((u, i) => (
|
|
|
|
|
|
<Link
|
|
|
|
|
|
key={u.id}
|
|
|
|
|
|
href={`/users/${u.id}`}
|
|
|
|
|
|
className={`flex items-center gap-3 px-4 py-3.5 hover:bg-(--color-bg-secondary) transition-colors ${
|
|
|
|
|
|
i !== users.length - 1 ? "border-b border-(--color-border-subtle)" : ""
|
|
|
|
|
|
}`}
|
|
|
|
|
|
>
|
2026-09-26 18:10:31 +03:30
|
|
|
|
{u.photos.length > 0 ? (
|
|
|
|
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={photoUrl(u.photos[0])}
|
|
|
|
|
|
alt=""
|
|
|
|
|
|
className="w-11 h-11 rounded-(--radius-md) object-cover shrink-0"
|
|
|
|
|
|
/>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<Avatar name={u.first_name || u.phone} />
|
|
|
|
|
|
)}
|
2026-09-15 23:26:24 +03:30
|
|
|
|
<div className="flex-1 min-w-0">
|
|
|
|
|
|
<p className="font-bold text-[14px] text-(--color-content-primary) truncate">
|
|
|
|
|
|
{u.first_name || "بدون نام"}
|
|
|
|
|
|
{calcAge(u.birth_date) ? `، ${calcAge(u.birth_date)} سال` : ""}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p dir="ltr" className="text-[12px] text-(--color-content-tertiary) text-right">
|
|
|
|
|
|
{u.phone}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
2026-09-26 18:10:31 +03:30
|
|
|
|
{u.photos.length === 0 && (
|
|
|
|
|
|
<Badge tone="warning" className="shrink-0">
|
|
|
|
|
|
بدون عکس
|
|
|
|
|
|
</Badge>
|
|
|
|
|
|
)}
|
2026-09-15 23:26:24 +03:30
|
|
|
|
{u.gender && (
|
|
|
|
|
|
<Badge tone="neutral" className="shrink-0">
|
|
|
|
|
|
{u.gender === "male" ? "مرد" : "زن"}
|
|
|
|
|
|
</Badge>
|
|
|
|
|
|
)}
|
|
|
|
|
|
<ChevronLeft size={16} className="text-(--color-content-tertiary) shrink-0" />
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|