diff --git a/mvp/b2c/src/app/admin/layout.tsx b/mvp/b2c/src/app/admin/layout.tsx new file mode 100644 index 0000000..e36379d --- /dev/null +++ b/mvp/b2c/src/app/admin/layout.tsx @@ -0,0 +1,30 @@ +import Link from 'next/link'; +import type { Metadata } from 'next'; +import { requireAdmin } from '@/lib/auth/current-user'; + +export const metadata: Metadata = { title: 'Admin ยท Reformix' }; + +export default async function AdminLayout({ children }: { children: React.ReactNode }) { + await requireAdmin(); + return ( +
+
+
+ + R + Reformix + / + Admin + + +
+
+
{children}
+
+ ); +} diff --git a/mvp/b2c/src/app/admin/page.tsx b/mvp/b2c/src/app/admin/page.tsx new file mode 100644 index 0000000..0aed04f --- /dev/null +++ b/mvp/b2c/src/app/admin/page.tsx @@ -0,0 +1,26 @@ +import { listTenants, listUsers, listPlans } from '@/db/admin-queries'; + +export const dynamic = 'force-dynamic'; + +export default async function AdminHome() { + const [tenants, users, plans] = await Promise.all([listTenants(), listUsers(), listPlans()]); + const cards = [ + { label: 'Reformistas (tenants)', value: tenants.length }, + { label: 'Usuarios', value: users.length }, + { label: 'Planes activos', value: plans.length }, + { label: 'En trial', value: tenants.filter((t) => t.subscriptionStatus === 'trial').length }, + ]; + return ( +
+

Resumen

+
+ {cards.map((c) => ( +
+
{c.value}
+
{c.label}
+
+ ))} +
+
+ ); +}