From 4b0bd2cf8c4e3d2c2a50a93cfd879459adf004b2 Mon Sep 17 00:00:00 2001 From: g Date: Fri, 28 Nov 2025 19:08:40 +0000 Subject: [PATCH] Revamp admin dashboard analytics and UI Refactored the admin dashboard to use tabbed navigation for analytics and management. Enhanced AdminAnalytics with Recharts visualizations, added top vendors by revenue, and improved chart tooltips. Removed unused columns from vendor table. Updated layout and notification context to exclude admin pages from dashboard-specific UI and notifications. Minor debug logging added to SystemStatusCard. --- app/dashboard/admin/page.tsx | 35 +- app/dashboard/admin/vendors/page.tsx | 9 +- components/admin/AdminAnalytics.tsx | 492 +++++++++++++++--------- components/admin/SystemStatusCard.tsx | 1 + components/layout/KeepOnlineWrapper.tsx | 3 +- components/layout/layout.tsx | 4 +- lib/notification-context.tsx | 8 +- public/git-info.json | 4 +- 8 files changed, 337 insertions(+), 219 deletions(-) diff --git a/app/dashboard/admin/page.tsx b/app/dashboard/admin/page.tsx index 816d1ba..c4b6b75 100644 --- a/app/dashboard/admin/page.tsx +++ b/app/dashboard/admin/page.tsx @@ -1,38 +1,47 @@ export const dynamic = "force-dynamic"; import React from "react"; +import AdminAnalytics from "@/components/admin/AdminAnalytics"; import InviteVendorCard from "@/components/admin/InviteVendorCard"; import BanUserCard from "@/components/admin/BanUserCard"; -import RecentOrdersCard from "@/components/admin/RecentOrdersCard"; -import SystemStatusCard from "@/components/admin/SystemStatusCard"; import InvitationsListCard from "@/components/admin/InvitationsListCard"; import VendorsCard from "@/components/admin/VendorsCard"; import { Button } from "@/components/ui/button"; import Link from "next/link"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; export default function AdminPage() { return (
-

Admin

-

Restricted area. Only admin1 can access.

+

Admin Dashboard

+

Platform analytics and vendor management

-
- - - - - - + + + Analytics + Management + - {/* Disabled/hidden cards as requested */} -
+ + + + + +
+ + + + +
+
+
); } diff --git a/app/dashboard/admin/vendors/page.tsx b/app/dashboard/admin/vendors/page.tsx index 60810fc..c2ab1a1 100644 --- a/app/dashboard/admin/vendors/page.tsx +++ b/app/dashboard/admin/vendors/page.tsx @@ -130,8 +130,6 @@ export default async function AdminVendorsPage() { Store Status Join Date - Orders - Revenue Actions @@ -139,10 +137,7 @@ export default async function AdminVendorsPage() { {vendors.map((vendor) => ( -
-
{vendor.username}
-
{vendor.email || 'No email'}
-
+
{vendor.username}
{vendor.storeId || 'No store'} @@ -162,8 +157,6 @@ export default async function AdminVendorsPage() { {vendor.createdAt ? new Date(vendor.createdAt).toLocaleDateString() : 'N/A'} - N/A - N/A
+ +
+ {showDebug && analyticsData && ( + + + Debug: Raw Data + Date Range: {dateRange} + + +
+
+
Orders:
+
+
Total: {analyticsData?.orders?.total || 'N/A'}
+
Today: {analyticsData?.orders?.totalToday || 'N/A'}
+
Daily Orders Array Length: {analyticsData?.orders?.dailyOrders?.length || 0}
+
First 3 Daily Orders:
+
+                    {JSON.stringify(analyticsData?.orders?.dailyOrders?.slice(0, 3), null, 2)}
+                  
+
+
+ +
+
Revenue:
+
+
Total: {analyticsData?.revenue?.total || 'N/A'}
+
Today: {analyticsData?.revenue?.today || 'N/A'}
+
Daily Revenue Array Length: {analyticsData?.revenue?.dailyRevenue?.length || 0}
+
First 3 Daily Revenue:
+
+                    {JSON.stringify(analyticsData?.revenue?.dailyRevenue?.slice(0, 3), null, 2)}
+                  
+
+
+ +
+
Vendors:
+
+
Total: {analyticsData?.vendors?.total || 'N/A'}
+
Daily Growth Array Length: {analyticsData?.vendors?.dailyGrowth?.length || 0}
+
First 3 Daily Growth:
+
+                    {JSON.stringify(analyticsData?.vendors?.dailyGrowth?.slice(0, 3), null, 2)}
+                  
+
+
+ +
+ Full JSON Response +
+                  {JSON.stringify(analyticsData, null, 2)}
+                
+
+
+
+
+ )} +
{/* Orders Card */} @@ -261,13 +369,17 @@ export default function AdminAnalytics() { />
- {analyticsData?.orders?.dailyOrders && ( -
- + {analyticsData?.orders?.dailyOrders && analyticsData.orders.dailyOrders.length > 0 ? ( +
+ + + + } /> + +
+ ) : ( +
No chart data available
)} @@ -292,15 +404,17 @@ export default function AdminAnalytics() { />
- {analyticsData?.revenue?.dailyRevenue && ( -
- + {analyticsData?.revenue?.dailyRevenue && analyticsData.revenue.dailyRevenue.length > 0 ? ( +
+ + + + } /> + +
+ ) : ( +
No chart data available
)} @@ -317,6 +431,10 @@ export default function AdminAnalytics() {
{analyticsData?.vendors?.total?.toLocaleString() || '0'}
+
+ Active: {analyticsData?.vendors?.active || 0} + Stores: {analyticsData?.vendors?.activeStores || 0} +
New Today: {analyticsData?.vendors?.newToday || 0}
- {analyticsData?.vendors?.dailyGrowth && ( -
- + {analyticsData?.vendors?.dailyGrowth && analyticsData.vendors.dailyGrowth.length > 0 ? ( +
+ + + + } /> + +
+ ) : ( +
No chart data available
)} @@ -359,9 +480,7 @@ export default function AdminAnalytics() { Orders - Revenue Vendors - Engagement @@ -369,18 +488,49 @@ export default function AdminAnalytics() { Order Trends - Daily order volume over the selected time period + Daily order volume and revenue processed over the selected time period - {analyticsData?.orders?.dailyOrders ? ( - + {analyticsData?.orders?.dailyOrders && analyticsData.orders.dailyOrders.length > 0 ? ( +
+ + + + + + `£${(value / 1000).toFixed(0)}k`} + label={{ value: 'Revenue', angle: 90, position: 'insideRight' }} + /> + } /> + + + + +
) : (
- No order data available + No order data available for the selected time period
)} @@ -402,46 +552,6 @@ export default function AdminAnalytics() {
- - - - Revenue Trends - - Daily revenue over the selected time period - - - - {analyticsData?.revenue?.dailyRevenue ? ( - - ) : ( -
- No revenue data available -
- )} - -
-
-
Total Revenue
-
{formatCurrency(analyticsData?.revenue?.total || 0)}
-
-
-
Today's Revenue
-
{formatCurrency(analyticsData?.revenue?.today || 0)}
-
-
-
This Week's Revenue
-
{formatCurrency(analyticsData?.revenue?.thisWeek || 0)}
-
-
-
-
-
- @@ -451,71 +561,73 @@ export default function AdminAnalytics() { - {analyticsData?.vendors?.dailyGrowth ? ( - + {analyticsData?.vendors?.dailyGrowth && analyticsData.vendors.dailyGrowth.length > 0 ? ( +
+ + + + + + } /> + + + +
) : (
- No vendor data available + No vendor data available for the selected time period
)} -
+
Total Vendors
{analyticsData?.vendors?.total?.toLocaleString() || '0'}
-
New Today
-
{analyticsData?.vendors?.newToday?.toLocaleString() || '0'}
+
Active Vendors
+
{analyticsData?.vendors?.active?.toLocaleString() || '0'}
+
+
+
Active Stores
+
{analyticsData?.vendors?.activeStores?.toLocaleString() || '0'}
New This Week
{analyticsData?.vendors?.newThisWeek?.toLocaleString() || '0'}
- - - - - - - - User Engagement - - Chat and message activity - - - - {analyticsData?.engagement?.dailyMessages ? ( - - ) : ( -
- No engagement data available + + {/* Top Vendors by Revenue */} + {analyticsData?.vendors?.topVendors && analyticsData.vendors.topVendors.length > 0 && ( +
+

Top Vendors by Revenue

+
+ {analyticsData.vendors.topVendors.map((vendor, index) => ( +
+
+
+ {index + 1} +
+
+
{vendor.vendorName}
+
{vendor.orderCount} orders
+
+
+
+
{formatCurrency(vendor.totalRevenue)}
+
+
+ ))} +
)} - -
-
-
Total Messages
-
{analyticsData?.engagement?.totalMessages?.toLocaleString() || '0'}
-
-
-
Active Chats
-
{analyticsData?.engagement?.activeChats?.toLocaleString() || '0'}
-
-
-
Sessions
-
{analyticsData?.sessions?.active?.toLocaleString() || '0'} / {analyticsData?.sessions?.total?.toLocaleString() || '0'}
-
-
diff --git a/components/admin/SystemStatusCard.tsx b/components/admin/SystemStatusCard.tsx index 01a583b..55c7035 100644 --- a/components/admin/SystemStatusCard.tsx +++ b/components/admin/SystemStatusCard.tsx @@ -25,6 +25,7 @@ export default function SystemStatusCard() { (async () => { try { const res = await fetchClient("/admin/system-status"); + console.log(`Here is your mother fuckin data: ${JSON.stringify(res)}`); if (mounted) setData(res); } catch (e: any) { if (mounted) setError(e?.message || "Failed to load status"); diff --git a/components/layout/KeepOnlineWrapper.tsx b/components/layout/KeepOnlineWrapper.tsx index 4ade706..0fba45d 100644 --- a/components/layout/KeepOnlineWrapper.tsx +++ b/components/layout/KeepOnlineWrapper.tsx @@ -6,7 +6,8 @@ import KeepOnline from "@/components/KeepOnline"; const KeepOnlineWrapper = () => { const pathname = usePathname(); - if (!pathname?.includes("/dashboard")) { + // Don't show KeepOnline on admin pages or non-dashboard pages + if (!pathname?.includes("/dashboard") || pathname?.includes("/dashboard/admin")) { return null; } diff --git a/components/layout/layout.tsx b/components/layout/layout.tsx index 4789d08..7daf193 100644 --- a/components/layout/layout.tsx +++ b/components/layout/layout.tsx @@ -18,6 +18,8 @@ export default function Layout({ children }: LayoutProps) { // Check if we're in a chat detail page const isChatDetailPage = pathname?.includes('/dashboard/chats/') && !pathname?.endsWith('/chats') && !pathname?.endsWith('/new') + // Check if we're on an admin page + const isAdminPage = pathname?.includes('/dashboard/admin') useEffect(() => setMounted(true), []) @@ -27,7 +29,7 @@ export default function Layout({ children }: LayoutProps) {
- {!isChatDetailPage && ( + {!isChatDetailPage && !isAdminPage && (
diff --git a/lib/notification-context.tsx b/lib/notification-context.tsx index ca43034..c161c44 100644 --- a/lib/notification-context.tsx +++ b/lib/notification-context.tsx @@ -167,8 +167,8 @@ export function NotificationProvider({ children }: NotificationProviderProps) { // Check for new paid orders useEffect(() => { - // Only run this on dashboard pages - if (typeof window === 'undefined' || !window.location.pathname.includes("/dashboard")) return; + // Only run this on dashboard pages, but not on admin pages + if (typeof window === 'undefined' || !window.location.pathname.includes("/dashboard") || window.location.pathname.includes("/dashboard/admin")) return; const checkForNewOrders = async () => { try { @@ -250,8 +250,8 @@ export function NotificationProvider({ children }: NotificationProviderProps) { // Fetch unread chat counts useEffect(() => { - // Only run this on dashboard pages - if (typeof window === 'undefined' || !window.location.pathname.includes("/dashboard")) return; + // Only run this on dashboard pages, but not on admin pages + if (typeof window === 'undefined' || !window.location.pathname.includes("/dashboard") || window.location.pathname.includes("/dashboard/admin")) return; const fetchUnreadCounts = async () => { try { diff --git a/public/git-info.json b/public/git-info.json index 0b9483c..6b43518 100644 --- a/public/git-info.json +++ b/public/git-info.json @@ -1,4 +1,4 @@ { - "commitHash": "28e292a", - "buildTime": "2025-11-28T18:29:50.128Z" + "commitHash": "f212859", + "buildTime": "2025-11-28T18:47:55.501Z" } \ No newline at end of file