fixing platform admin

This commit is contained in:
root
2026-05-06 22:58:23 -04:00
parent 695a7f7cc7
commit 750ae56a29
175 changed files with 31249 additions and 328 deletions
+111
View File
@@ -0,0 +1,111 @@
'use client'
import { useEffect, useState } from 'react'
import Link from 'next/link'
import { useAdminI18n } from '@/components/I18nProvider'
const API_BASE = '/api/v1'
interface Metrics {
totalCompanies: number
activeCompanies: number
totalRenters: number
totalReservations: number
mrr?: number
}
export default function AdminDashboardPage() {
const { language, dict } = useAdminI18n()
const copy = {
en: {
kpis: ['Total companies', 'Active companies', 'Total renters', 'Total reservations'],
platformOverview: 'Platform overview',
cards: [
['Companies', 'List, search, suspend, reactivate, and review subscription state.', 'View all →'],
['Renters', 'Support flows for blocking and unblocking marketplace renters.', 'View all →'],
['Audit logs', 'Full trace of every admin action taken on the platform.', 'View logs →'],
],
},
fr: {
kpis: ['Entreprises totales', 'Entreprises actives', 'Locataires totaux', 'Réservations totales'],
platformOverview: 'Vue plateforme',
cards: [
['Entreprises', 'Lister, rechercher, suspendre, réactiver et revoir l’état des abonnements.', 'Voir tout →'],
['Locataires', 'Flux de support pour bloquer et débloquer les locataires marketplace.', 'Voir tout →'],
['Journaux daudit', 'Trace complète de chaque action admin sur la plateforme.', 'Voir les journaux →'],
],
},
ar: {
kpis: ['إجمالي الشركات', 'الشركات النشطة', 'إجمالي المستأجرين', 'إجمالي الحجوزات'],
platformOverview: 'نظرة عامة على المنصة',
cards: [
['الشركات', 'اعرض وابحث وعلّق وأعد التفعيل وراجع حالة الاشتراك.', 'عرض الكل ←'],
['المستأجرون', 'مسارات دعم لحظر وفك حظر مستأجري السوق.', 'عرض الكل ←'],
['سجلات التدقيق', 'تتبع كامل لكل إجراء إداري تم على المنصة.', 'عرض السجلات ←'],
],
},
}[language]
const [metrics, setMetrics] = useState<Metrics | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
const token = localStorage.getItem('admin_token') ?? ''
fetch(`${API_BASE}/admin/metrics`, {
headers: { Authorization: `Bearer ${token}` },
cache: 'no-store',
})
.then((r) => r.json())
.then((json) => setMetrics(json.data))
.catch(() => null)
.finally(() => setLoading(false))
}, [])
const kpis = metrics
? [
{ label: 'Total companies', value: metrics.totalCompanies },
{ label: copy.kpis[1], value: metrics.activeCompanies },
{ label: copy.kpis[2], value: metrics.totalRenters },
{ label: copy.kpis[3], value: metrics.totalReservations },
]
: []
if (kpis.length > 0) kpis[0].label = copy.kpis[0]
return (
<div className="shell py-8 space-y-8">
<div>
<p className="text-xs uppercase tracking-[0.2em] text-emerald-400">{dict.admin}</p>
<h1 className="mt-1 text-3xl font-black">{copy.platformOverview}</h1>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{loading
? Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="panel p-6 animate-pulse">
<div className="h-3 w-24 rounded bg-zinc-800" />
<div className="mt-3 h-8 w-16 rounded bg-zinc-800" />
</div>
))
: kpis.map((kpi) => (
<div key={kpi.label} className="panel p-6">
<p className="text-xs text-zinc-500">{kpi.label}</p>
<p className="mt-1 text-3xl font-black">{kpi.value?.toLocaleString() ?? '—'}</p>
</div>
))}
</div>
<div className="grid gap-6 md:grid-cols-3">
{[
['/dashboard/companies', ...copy.cards[0]],
['/dashboard/renters', ...copy.cards[1]],
['/dashboard/audit-logs', ...copy.cards[2]],
].map(([href, title, body, cta]) => (
<Link key={href} href={href} className="panel p-6 hover:border-zinc-700 transition-colors block">
<p className="text-sm font-semibold text-zinc-200">{title}</p>
<p className="mt-2 text-sm text-zinc-500">{body}</p>
<p className="mt-4 text-xs text-emerald-400 font-medium">{cta}</p>
</Link>
))}
</div>
</div>
)
}