106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { RefreshCw, Bell } 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 NotificationItem {
|
|
id: string;
|
|
event_type: string;
|
|
title: string;
|
|
message: string;
|
|
status: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export default function AdminNotificationsPage() {
|
|
const { lang } = useLanguage();
|
|
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const token = localStorage.getItem("access_token");
|
|
if (!token) {
|
|
window.location.href = "/login?redirect=/admin/notifications";
|
|
return;
|
|
}
|
|
|
|
const fetchData = async () => {
|
|
const baseURL = process.env.NEXT_PUBLIC_API_URL;
|
|
try {
|
|
const res = await fetch(`${baseURL}/health/notifications/`, {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
const data = await res.json();
|
|
setNotifications(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">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="text-xl font-bold text-white">{t("اعلانات", "Notifications")}</h2>
|
|
<Button variant="ghost" size="sm" onClick={() => window.location.reload()}>
|
|
<RefreshCw className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
{notifications.map((n) => (
|
|
<div
|
|
key={n.id}
|
|
className={`flex items-start gap-3 rounded-xl border border-white/10 p-4 ${
|
|
n.status === "unread" ? "bg-brand-500/5" : "bg-white/[0.02]"
|
|
}`}
|
|
>
|
|
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-brand-gradient text-white">
|
|
<Bell className="h-4 w-4" />
|
|
</span>
|
|
<div className="flex-1">
|
|
<div className="flex items-center justify-between">
|
|
<p className="text-sm font-medium text-white">{n.title}</p>
|
|
<Badge variant={n.status === "unread" ? "default" : "secondary"} className="text-xs">
|
|
{n.status}
|
|
</Badge>
|
|
</div>
|
|
<p className="mt-1 text-sm text-slate-400">{n.message}</p>
|
|
<p className="mt-2 text-xs text-slate-500">
|
|
{new Date(n.created_at).toLocaleString(lang === "fa" ? "fa-IR" : "en-US")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
{notifications.length === 0 && !loading && (
|
|
<div className="py-12 text-center text-slate-500">
|
|
{t("اعلانی یافت نشد", "No notifications found")}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</AdminLayout>
|
|
);
|
|
}
|