templates2.Base.Next/app/admin/page.tsx
w4c-templates 219be916cb
Some checks are pending
CI / quality (push) Waiting to run
chore(template): publish Base.Next
2026-10-11 23:23:30 +03:00

46 lines
1.6 KiB
TypeScript

import { Card } from '@/components/ui';
import { db } from '@/lib/server/db';
import { t } from '@/lib/i18n';
export const dynamic = 'force-dynamic';
export default async function AdminOverviewPage() {
const [totalUsers, activeSubs, recent] = await Promise.all([
db.user.count(),
db.subscription.count({ where: { status: 'active' } }),
db.auditLog.findMany({ orderBy: { createdAt: 'desc' }, take: 5, include: { actor: true } }),
]);
const stats = [
{ label: t('admin.totalUsers'), value: totalUsers },
{ label: t('admin.activeSubs'), value: activeSubs },
];
return (
<div className="space-y-6">
<h1 className="text-2xl font-bold">{t('admin.overview')}</h1>
<div className="grid gap-5 sm:grid-cols-2">
{stats.map((s) => (
<div key={s.label} className="card">
<p className="muted text-sm">{s.label}</p>
<p className="mt-2 text-3xl font-bold">{s.value}</p>
</div>
))}
</div>
<Card title={t('admin.audit')}>
<ul className="divide-y" style={{ borderColor: 'var(--border)' }}>
{recent.map((entry) => (
<li key={entry.id} className="flex items-center justify-between py-2 text-sm">
<span>
<span className="font-medium">{entry.action}</span>
{entry.target ? <span className="muted"> → {entry.target}</span> : null}
</span>
<span className="muted text-xs">{entry.actor?.email ?? 'system'}</span>
</li>
))}
</ul>
</Card>
</div>
);
}