gh_UserManager/apps/web/app/admin/members/page.tsx
bermooda-company 54d5891edf user
2026-08-23 23:59:14 +03:30

111 lines
3.9 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { RefreshCw, Users } from "lucide-react";
import { AdminLayout } from "@/components/admin/admin-layout";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { useLanguage } from "@/components/language-provider";
interface Membership {
id: string;
user_name: string;
user_email: string;
organization_name: string;
role: string;
status: string;
created_at: string;
}
export default function AdminMembersPage() {
const { lang } = useLanguage();
const [memberships, setMemberships] = useState<Membership[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem("access_token");
if (!token) {
window.location.href = "/login?redirect=/admin/members";
return;
}
const fetchData = async () => {
const baseURL = process.env.NEXT_PUBLIC_API_URL;
try {
const res = await fetch(`${baseURL}/membership/memberships/`, {
headers: { Authorization: `Bearer ${token}` },
});
const data = await res.json();
setMemberships(data.results || []);
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
const t = (fa: string, en: string) => (lang === "fa" ? fa : en);
if (loading) {
return (
<AdminLayout>
<div className="flex items-center justify-center h-64">
<RefreshCw className="h-8 w-8 animate-spin text-brand-400" />
</div>
</AdminLayout>
);
}
return (
<AdminLayout>
<div className="space-y-6">
<h2 className="text-xl font-bold text-white">{t("اعضا", "Members")}</h2>
<div className="overflow-x-auto rounded-xl border border-white/10">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/10 bg-white/[0.02]">
<th className="px-4 py-3 text-start text-xs font-medium text-slate-400">{t("کاربر", "User")}</th>
<th className="px-4 py-3 text-start text-xs font-medium text-slate-400">{t("سازمان", "Organization")}</th>
<th className="px-4 py-3 text-start text-xs font-medium text-slate-400">{t("نقش", "Role")}</th>
<th className="px-4 py-3 text-start text-xs font-medium text-slate-400">{t("وضعیت", "Status")}</th>
</tr>
</thead>
<tbody>
{memberships.map((m) => (
<tr key={m.id} className="border-b border-white/5">
<td className="px-4 py-3">
<div className="flex items-center gap-3">
<span className="flex h-7 w-7 items-center justify-center rounded-full bg-brand-gradient text-[10px] font-bold text-white">
{m.user_name?.charAt(0) || m.user_email?.charAt(0) || "?"}
</span>
<span className="text-white">{m.user_name || m.user_email}</span>
</div>
</td>
<td className="px-4 py-3 text-slate-300">{m.organization_name}</td>
<td className="px-4 py-3">
<Badge variant="secondary" className="text-xs capitalize">{m.role}</Badge>
</td>
<td className="px-4 py-3">
<Badge variant={m.status === "active" ? "default" : "secondary"} className="text-xs">
{m.status}
</Badge>
</td>
</tr>
))}
</tbody>
</table>
{memberships.length === 0 && !loading && (
<div className="py-12 text-center text-slate-500">
{t("عضوی یافت نشد", "No members found")}
</div>
)}
</div>
</div>
</AdminLayout>
);
}