Skip to content

Commit b9f3970

Browse files
committed
Perf: Optimize Admin Dashboard with client-side hydration and revamped loading states
1 parent 9f328fa commit b9f3970

3 files changed

Lines changed: 57 additions & 14 deletions

File tree

web/src/actions/content.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,23 @@ export async function getPublicBodhakathas(page: number = 1, pageSize: number =
166166
hasMore: total > skip + items.length
167167
};
168168
}
169+
170+
export async function getAdminDashboardStats() {
171+
if (!await isAdmin()) throw new Error('Unauthorized');
172+
173+
const [leelaCount, bodhakathaCount, glossaryCount, ticketCount, openTickets] = await Promise.all([
174+
prisma.leela.count(),
175+
prisma.bodhakatha.count(),
176+
prisma.glossary.count(),
177+
prisma.ticket.count(),
178+
prisma.ticket.count({ where: { status: 'OPEN' } })
179+
]);
180+
181+
return {
182+
leelaCount,
183+
bodhakathaCount,
184+
glossaryCount,
185+
ticketCount,
186+
openTickets
187+
};
188+
}

web/src/app/admin/loading.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ export default function AdminLoading() {
2828
<span className="w-1.5 h-1.5 bg-ochre rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
2929
</div>
3030
<h3 className="text-sm font-black text-gray-900 tracking-[0.3em] uppercase">
31-
Admin Console
31+
Admin Interface
3232
</h3>
3333
<p className="text-[10px] font-bold text-gray-400 uppercase tracking-widest">
34-
Initializing System Data...
34+
Securing Connection...
3535
</p>
3636
</div>
3737
</div>

web/src/app/admin/page.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
11

2+
'use client';
3+
4+
import { useState, useEffect } from 'react';
25
import Link from 'next/link';
3-
import prisma from '@/lib/db';
4-
import { Footprints, Lightbulb, Book, Ticket, Activity, MessageSquare } from 'lucide-react';
6+
import { Footprints, Lightbulb, Book, Ticket, Activity, MessageSquare, Loader2 } from 'lucide-react';
7+
import { getAdminDashboardStats } from '@/actions/content';
8+
9+
export default function AdminDashboard() {
10+
const [statsData, setStatsData] = useState<any>(null);
11+
const [isLoading, setIsLoading] = useState(true);
12+
13+
useEffect(() => {
14+
fetchStats();
15+
}, []);
16+
17+
const fetchStats = async () => {
18+
try {
19+
const data = await getAdminDashboardStats();
20+
setStatsData(data);
21+
} catch (error) {
22+
console.error('Error fetching dashboard stats:', error);
23+
} finally {
24+
setIsLoading(false);
25+
}
26+
};
27+
28+
if (isLoading || !statsData) {
29+
return (
30+
<div className="flex flex-col items-center justify-center min-h-[60vh] text-gray-400 animate-in fade-in duration-700">
31+
<Loader2 className="w-10 h-10 animate-spin mb-4 text-ochre" />
32+
<p className="text-lg uppercase font-black tracking-widest">Loading Dashboard...</p>
33+
</div>
34+
);
35+
}
536

6-
export default async function AdminDashboard() {
7-
// Fetch stats for the dashboard
8-
const [leelaCount, bodhakathaCount, glossaryCount, ticketCount, openTickets] = await Promise.all([
9-
prisma.leela.count(),
10-
prisma.bodhakatha.count(),
11-
prisma.glossary.count(),
12-
prisma.ticket.count(),
13-
prisma.ticket.count({ where: { status: 'OPEN' } })
14-
]);
37+
const { leelaCount, bodhakathaCount, glossaryCount, ticketCount, openTickets } = statsData;
1538

1639
const stats = [
1740
{ label: 'Content', value: leelaCount + bodhakathaCount + glossaryCount, icon: Activity, color: 'text-blue-600', href: '/admin/leela' },
@@ -63,7 +86,7 @@ export default async function AdminDashboard() {
6386
];
6487

6588
return (
66-
<div className="max-w-7xl mx-auto p-4 md:p-8 space-y-6 md:space-y-12">
89+
<div className="max-w-7xl mx-auto p-4 md:p-8 space-y-6 md:space-y-12 animate-in fade-in duration-1000">
6790
{/* Header Content */}
6891
<div className="flex flex-col md:flex-row md:items-end justify-between gap-4 md:pb-2">
6992
<div className="space-y-1">

0 commit comments

Comments
 (0)