From d3f465b5d4b20796c04e70e95b5f2f7d882ec085 Mon Sep 17 00:00:00 2001 From: charlesgauthereau Date: Tue, 29 Jul 2025 08:51:50 +0200 Subject: [PATCH] Working on the home page. --- .../dashboard/(organization)/home/page.tsx | 21 ----- .../(organization)/statistics/page.tsx | 4 +- app/(customer)/dashboard/home/page.tsx | 90 +++++++++++++++++++ .../common/sidebar/menu-sidebar-main.tsx | 9 +- src/lib/auth/auth.ts | 7 +- 5 files changed, 104 insertions(+), 27 deletions(-) delete mode 100644 app/(customer)/dashboard/(organization)/home/page.tsx create mode 100644 app/(customer)/dashboard/home/page.tsx diff --git a/app/(customer)/dashboard/(organization)/home/page.tsx b/app/(customer)/dashboard/(organization)/home/page.tsx deleted file mode 100644 index 25407a64..00000000 --- a/app/(customer)/dashboard/(organization)/home/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { PageParams } from "@/types/next"; -import {Page, PageHeader, PageTitle} from "@/features/layout/page"; - -export default async function RoutePage(props: PageParams<{}>) { - - return ( - - - Dashboard - -
-
-
-
-
-
-
- - - ); -} diff --git a/app/(customer)/dashboard/(organization)/statistics/page.tsx b/app/(customer)/dashboard/(organization)/statistics/page.tsx index 17f83386..4d7445a5 100644 --- a/app/(customer)/dashboard/(organization)/statistics/page.tsx +++ b/app/(customer)/dashboard/(organization)/statistics/page.tsx @@ -5,7 +5,7 @@ import {EvolutionLineChart} from "@/components/wrappers/dashboard/statistics/cha import {PercentageLineChart} from "@/components/wrappers/dashboard/statistics/charts/percentage-line-chart"; import {notFound} from "next/navigation"; import {db} from "@/db"; -import {asc, count, eq, inArray} from "drizzle-orm"; +import {and, asc, count, eq, inArray} from "drizzle-orm"; import * as drizzleDb from "@/db"; import {getOrganization} from "@/lib/auth/auth"; import {DatabaseBackup, Folder, RefreshCcw} from "lucide-react"; @@ -53,7 +53,7 @@ export default async function RoutePage(props: PageParams<{}>) { _count: count(), }) .from(drizzleDb.schemas.backup) - .where(inArray(drizzleDb.schemas.backup.status, ["success", "failed"])) + .where(and(inArray(drizzleDb.schemas.backup.status, ["success", "failed"]), inArray(drizzleDb.schemas.backup.databaseId, databaseIds))) .groupBy(drizzleDb.schemas.backup.createdAt, drizzleDb.schemas.backup.status) .orderBy(drizzleDb.schemas.backup.createdAt); diff --git a/app/(customer)/dashboard/home/page.tsx b/app/(customer)/dashboard/home/page.tsx new file mode 100644 index 00000000..1c0cbec2 --- /dev/null +++ b/app/(customer)/dashboard/home/page.tsx @@ -0,0 +1,90 @@ +import {PageParams} from "@/types/next"; +import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page"; +import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card"; +import {Building2, DatabaseBackup, Folder, RefreshCcw} from "lucide-react"; +import {EvolutionLineChart} from "@/components/wrappers/dashboard/statistics/charts/evolution-line-chart"; +import {PercentageLineChart} from "@/components/wrappers/dashboard/statistics/charts/percentage-line-chart"; +import {currentUser} from "@/lib/auth/current-user"; +import {notFound} from "next/navigation"; +import {db} from "@/db"; +import {asc, eq, inArray} from "drizzle-orm"; +import * as drizzleDb from "@/db"; +import {auth, listOrganizations} from "@/lib/auth/auth"; +import {authClient} from "@/lib/auth/auth-client"; + +export default async function RoutePage(props: PageParams<{}>) { + + const user = await currentUser(); + const organizations = await listOrganizations() + + if (!user || !organizations) notFound(); + + const organizationIds = organizations.map(project => project.id); + + + const projects = await db.query.project.findMany({ + where: inArray(drizzleDb.schemas.project.organizationId, organizationIds), + }); + + const projectIds = projects.map(project => project.id); + + + const databasesOfAllProjects = await db.query.database.findMany({ + where: inArray(drizzleDb.schemas.database.projectId, projectIds), + }) + const databaseIds = databasesOfAllProjects.map((database) => database.id); + + + const backupsEvolution = await db.query.backup.findMany({ + columns: { + id: true, + createdAt: true, + }, + orderBy: [asc(drizzleDb.schemas.backup.id)], + where: inArray(drizzleDb.schemas.backup.databaseId, databaseIds), + }); + + + return ( + + + + Dashboard + + +
+ + + + Organizations + + {organizations.length} + + + + + Projects + + {projects.length} + + + + + Backups + + {backupsEvolution.length} + + +
+
+
+
+
+
+
+
+ + + + ); +} diff --git a/src/components/wrappers/dashboard/common/sidebar/menu-sidebar-main.tsx b/src/components/wrappers/dashboard/common/sidebar/menu-sidebar-main.tsx index 54b38e3f..58170dc8 100644 --- a/src/components/wrappers/dashboard/common/sidebar/menu-sidebar-main.tsx +++ b/src/components/wrappers/dashboard/common/sidebar/menu-sidebar-main.tsx @@ -22,9 +22,11 @@ export const SidebarMenuCustomMain = () => { return null; } + const groupContentApplication: SidebarGroupItem["group_content"] = [ + { title: "Dashboard", url: "/home", icon: Home }, + ]; const groupContent: SidebarGroupItem["group_content"] = [ - { title: "Dashboard", url: "/home", icon: Home }, { title: "Projects", url: "/projects", icon: Layers, details:true }, { title: "Statistics", url: "/statistics", icon: ChartArea }, ]; @@ -37,6 +39,11 @@ export const SidebarMenuCustomMain = () => { { label: "Application", type: "list", + group_content: groupContentApplication, + }, + { + label: "Organization", + type: "list", group_content: groupContent, }, ]; diff --git a/src/lib/auth/auth.ts b/src/lib/auth/auth.ts index 5d1812be..cb886cb9 100644 --- a/src/lib/auth/auth.ts +++ b/src/lib/auth/auth.ts @@ -4,7 +4,7 @@ import * as drizzleDb from "@/db"; import {db} from "@/db"; import {env} from "@/env.mjs"; import {nextCookies} from "better-auth/next-js"; -import {admin as adminPlugin, openAPI, organization} from "better-auth/plugins"; +import {admin as adminPlugin, openAPI, Organization, organization} from "better-auth/plugins"; import {ac, admin, orgAdmin, orgMember, orgOwner, pending, superadmin, user} from "@/lib/auth/permissions"; import {headers} from "next/headers"; import {count, eq} from "drizzle-orm"; @@ -353,12 +353,13 @@ export const getOrganization = async ({ } }; -export const listOrganizations = async () => { +export const listOrganizations = async (): Promise => { try { return await auth.api.listOrganizations({ headers: await headers(), - }); + }) as Organization[]; } catch (e) { + return null; } };