Add admin dashboard data loading & package dependencies

Removed 'admin-header.tsx' and 'admin-sidebar.tsx' components and added 'admin-dashboard.loader.ts' to handle loading data for the admin dashboard. Updated 'admin-dashboard.tsx' and 'page.tsx' to use this loader. Package dependencies were also updated in 'pnpm-lock.yaml' and 'package.json' files of relevant packages. This commit prioritizes loading dashboard data effectively and managing package dependencies.
This commit is contained in:
giancarlo
2024-04-08 14:34:47 +08:00
parent 9a5e614ad5
commit 4655f56143
11 changed files with 175 additions and 98 deletions

View File

@@ -1,17 +1,16 @@
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@kit/ui/card';
interface Data {
usersCount: number;
organizationsCount: number;
activeSubscriptions: number;
trialSubscriptions: number;
}
import { loadAdminDashboard } from '../lib/server/loaders/admin-dashboard.loader';
export async function AdminDashboard() {
const data = await loadAdminDashboard();
export function AdminDashboard({
data,
}: React.PropsWithChildren<{
data: Data;
}>) {
return (
<div
className={
@@ -22,23 +21,31 @@ export function AdminDashboard({
<Card>
<CardHeader>
<CardTitle>Users</CardTitle>
<CardDescription>
The number of personal accounts that have been created.
</CardDescription>
</CardHeader>
<CardContent>
<div className={'flex justify-between'}>
<Figure>{data.usersCount}</Figure>
<Figure>{data.accounts}</Figure>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Organizations</CardTitle>
<CardTitle>Team Accounts</CardTitle>
<CardDescription>
The number of team accounts that have been created.
</CardDescription>
</CardHeader>
<CardContent>
<div className={'flex justify-between'}>
<Figure>{data.organizationsCount}</Figure>
<Figure>{data.teamAccounts}</Figure>
</div>
</CardContent>
</Card>
@@ -46,11 +53,14 @@ export function AdminDashboard({
<Card>
<CardHeader>
<CardTitle>Paying Customers</CardTitle>
<CardDescription>
The number of paying customers with active subscriptions.
</CardDescription>
</CardHeader>
<CardContent>
<div className={'flex justify-between'}>
<Figure>{data.activeSubscriptions}</Figure>
<Figure>{data.subscriptions}</Figure>
</div>
</CardContent>
</Card>
@@ -58,11 +68,15 @@ export function AdminDashboard({
<Card>
<CardHeader>
<CardTitle>Trials</CardTitle>
<CardDescription>
Th number of trial subscriptions currently active.
</CardDescription>
</CardHeader>
<CardContent>
<div className={'flex justify-between'}>
<Figure>{data.trialSubscriptions}</Figure>
<Figure>{data.trials}</Figure>
</div>
</CardContent>
</Card>

View File

@@ -1,29 +0,0 @@
import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
import { Button } from '@kit/ui/button';
import { PageHeader } from '@kit/ui/page';
export function AdminHeader({
children,
paths,
}: React.PropsWithChildren<{
paths: {
appHome: string;
};
}>) {
return (
<PageHeader
title={children}
description={`Manage your app from the admin dashboard.`}
>
<Link href={paths.appHome}>
<Button variant={'link'}>
<ArrowLeft className={'h-4'} />
<span>Back to App</span>
</Button>
</Link>
</PageHeader>
);
}

View File

@@ -1,28 +0,0 @@
import { Home, User, Users } from 'lucide-react';
import { Sidebar, SidebarContent, SidebarItem } from '@kit/ui/sidebar';
export function AdminSidebar(props: { Logo: React.ReactNode }) {
return (
<Sidebar>
<SidebarContent className={'mb-6 mt-4 pt-2'}>{props.Logo}</SidebarContent>
<SidebarContent>
<SidebarItem end path={'/admin'} Icon={<Home className={'h-4'} />}>
Admin
</SidebarItem>
<SidebarItem path={'/admin/users'} Icon={<User className={'h-4'} />}>
Users
</SidebarItem>
<SidebarItem
path={'/admin/organizations'}
Icon={<Users className={'h-4'} />}
>
Organizations
</SidebarItem>
</SidebarContent>
</Sidebar>
);
}

View File

@@ -1 +1 @@
export * from './lib/is-super-admin';
export * from './lib/server/is-super-admin';

View File

@@ -0,0 +1,51 @@
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
export async function loadAdminDashboard(params?: {
count: 'exact' | 'estimated' | 'planned';
}) {
const count = params?.count ?? 'estimated';
const client = getSupabaseServerComponentClient({ admin: true });
const selectParams = {
count,
head: true,
};
const subscriptionsPromise = client
.from('subscriptions')
.select('*', selectParams)
.eq('status', 'active')
.then((response) => response.count);
const trialsPromise = client
.from('subscriptions')
.select('*', selectParams)
.eq('status', 'trialing')
.then((response) => response.count);
const accountsPromise = client
.from('accounts')
.select('*', selectParams)
.eq('is_personal_account', true)
.then((response) => response.count);
const teamAccountsPromise = client
.from('accounts')
.select('*', selectParams)
.eq('is_personal_account', false)
.then((response) => response.count);
const [subscriptions, trials, accounts, teamAccounts] = await Promise.all([
subscriptionsPromise,
trialsPromise,
accountsPromise,
teamAccountsPromise,
]);
return {
subscriptions,
trials,
accounts,
teamAccounts,
};
}