From 7029583475c00aecef07d7519bd1667ab5f8e76d Mon Sep 17 00:00:00 2001 From: Simone Cavalli Date: Fri, 15 May 2026 10:45:59 +0200 Subject: [PATCH] feat(02-02): add admin-queries, NavBar, and admin layout - src/lib/admin-queries.ts: getAllClientsWithPayments() and getClientById() for admin DB reads - src/components/admin/NavBar.tsx: minimal nav with Clienti link and Esci (logout) button - src/app/admin/layout.tsx: wraps all /admin/* pages with NavBar + centered main content area --- src/app/admin/layout.tsx | 14 ++++++++ src/components/admin/NavBar.tsx | 29 +++++++++++++++++ src/lib/admin-queries.ts | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/app/admin/layout.tsx create mode 100644 src/components/admin/NavBar.tsx create mode 100644 src/lib/admin-queries.ts diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx new file mode 100644 index 0000000..7a4eb38 --- /dev/null +++ b/src/app/admin/layout.tsx @@ -0,0 +1,14 @@ +import { NavBar } from "@/components/admin/NavBar"; + +export default function AdminLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ +
{children}
+
+ ); +} diff --git a/src/components/admin/NavBar.tsx b/src/components/admin/NavBar.tsx new file mode 100644 index 0000000..1a4305f --- /dev/null +++ b/src/components/admin/NavBar.tsx @@ -0,0 +1,29 @@ +"use client"; + +import Link from "next/link"; +import { signOut } from "next-auth/react"; +import { Button } from "@/components/ui/button"; + +export function NavBar() { + return ( + + ); +} diff --git a/src/lib/admin-queries.ts b/src/lib/admin-queries.ts new file mode 100644 index 0000000..d04c110 --- /dev/null +++ b/src/lib/admin-queries.ts @@ -0,0 +1,57 @@ +import { db } from "@/db"; +import { clients, payments } from "@/db/schema"; +import { eq } from "drizzle-orm"; + +export type ClientWithPayments = { + id: string; + name: string; + brand_name: string; + token: string; + accepted_total: string; + created_at: Date; + payments: Array<{ + id: string; + label: string; + status: string; + amount: string; + }>; +}; + +export async function getAllClientsWithPayments(): Promise { + const allClients = await db + .select() + .from(clients) + .orderBy(clients.created_at); + + if (allClients.length === 0) return []; + + const allPayments = await db + .select() + .from(payments); + + return allClients.map((c) => ({ + id: c.id, + name: c.name, + brand_name: c.brand_name, + token: c.token, + accepted_total: c.accepted_total ?? "0", + created_at: c.created_at, + payments: allPayments + .filter((p) => p.client_id === c.id) + .map((p) => ({ + id: p.id, + label: p.label, + status: p.status, + amount: p.amount, + })), + })); +} + +export async function getClientById(id: string) { + const rows = await db + .select() + .from(clients) + .where(eq(clients.id, id)) + .limit(1); + return rows[0] ?? null; +}