Skip to content

Commit fb8076f

Browse files
Merge pull request #7 from pritpatel2412/feature/admin-panel
feat: Add dynamic time filters, real user data, and Data Export Cente…
2 parents eb11354 + 9fb3218 commit fb8076f

10 files changed

Lines changed: 492 additions & 24 deletions

File tree

client/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import AdminOrders from "@/pages/admin/orders";
2828
import AdminRequests from "@/pages/admin/requests";
2929
import AdminSystem from "@/pages/admin/system";
3030
import AdminAuditLog from "@/pages/admin/audit-log";
31+
import AdminExport from "@/pages/admin/export";
3132
import { AuthProvider } from "@/hooks/use-auth";
3233
import { ThemeProvider } from "@/hooks/use-theme";
3334
import { ProtectedRoute, AdminProtectedRoute } from "@/lib/protected-route";
@@ -70,6 +71,7 @@ function App() {
7071
<AdminProtectedRoute path="/admin/requests" component={withLayout(AdminRequests)} />
7172
<AdminProtectedRoute path="/admin/system" component={withLayout(AdminSystem)} />
7273
<AdminProtectedRoute path="/admin/audit-log" component={withLayout(AdminAuditLog)} />
74+
<AdminProtectedRoute path="/admin/export" component={withLayout(AdminExport)} />
7375

7476
{/* Catch-all: Truly Full Screen 404 */}
7577
<Route component={NotFound} />

client/src/components/app-sidebar.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
MessageSquare,
1515
Search,
1616
ShoppingCart,
17+
Download,
1718
} from "lucide-react";
1819
import {
1920
Sidebar,
@@ -98,6 +99,11 @@ const adminNavItems = [
9899
url: "/admin/audit-log",
99100
icon: FileText,
100101
},
102+
{
103+
title: "Export Data",
104+
url: "/admin/export",
105+
icon: Download,
106+
},
101107
];
102108

103109
export function AppSidebar() {

client/src/pages/admin/export.tsx

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { useState } from "react";
2+
import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/card";
3+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
4+
import { Button } from "@/components/ui/button";
5+
import { FileJson, FileText, Download } from "lucide-react";
6+
import { useToast } from "@/hooks/use-toast";
7+
8+
export default function AdminExport() {
9+
const [entity, setEntity] = useState<string>("users");
10+
const [range, setRange] = useState<string>("7d");
11+
const [isExporting, setIsExporting] = useState<boolean>(false);
12+
const { toast } = useToast();
13+
14+
const handleExport = async (format: "json" | "pdf") => {
15+
try {
16+
setIsExporting(true);
17+
const url = `/api/admin/export/${entity}?range=${range}&format=${format}`;
18+
19+
const response = await fetch(url);
20+
if (!response.ok) {
21+
throw new Error("Export failed");
22+
}
23+
24+
const blob = await response.blob();
25+
const downloadUrl = window.URL.createObjectURL(blob);
26+
const link = document.createElement("a");
27+
link.href = downloadUrl;
28+
link.download = `export_${entity}_${range}.${format}`;
29+
document.body.appendChild(link);
30+
link.click();
31+
link.remove();
32+
window.URL.revokeObjectURL(downloadUrl);
33+
34+
toast({
35+
title: "Export Successful",
36+
description: `Successfully exported ${entity} as ${format.toUpperCase()}`,
37+
});
38+
} catch (error: any) {
39+
toast({
40+
title: "Export Failed",
41+
description: error.message,
42+
variant: "destructive",
43+
});
44+
} finally {
45+
setIsExporting(false);
46+
}
47+
};
48+
49+
return (
50+
<div className="container mx-auto py-8 px-4 max-w-4xl space-y-8">
51+
<div>
52+
<h1 className="text-3xl font-bold tracking-tight">Data Export Center</h1>
53+
<p className="text-muted-foreground">Download raw platform data for external analysis or compliance.</p>
54+
</div>
55+
56+
<Card>
57+
<CardHeader>
58+
<CardTitle>Export Configuration</CardTitle>
59+
<CardDescription>Select the data entity and time range to export.</CardDescription>
60+
</CardHeader>
61+
<CardContent className="space-y-6">
62+
<div className="space-y-4">
63+
<div className="space-y-2">
64+
<label className="text-sm font-medium">Data Entity</label>
65+
<Select value={entity} onValueChange={setEntity}>
66+
<SelectTrigger>
67+
<SelectValue placeholder="Select Data Type" />
68+
</SelectTrigger>
69+
<SelectContent>
70+
<SelectItem value="users">Users & Accounts</SelectItem>
71+
<SelectItem value="orders">Audit Orders & Payments</SelectItem>
72+
<SelectItem value="reviews">PR Reviews & Analysis</SelectItem>
73+
<SelectItem value="logs">System Access Logs</SelectItem>
74+
</SelectContent>
75+
</Select>
76+
</div>
77+
78+
<div className="space-y-2">
79+
<label className="text-sm font-medium">Time Range</label>
80+
<Select value={range} onValueChange={setRange}>
81+
<SelectTrigger>
82+
<SelectValue placeholder="Select Time Range" />
83+
</SelectTrigger>
84+
<SelectContent>
85+
<SelectItem value="7d">Last 7 Days</SelectItem>
86+
<SelectItem value="15d">Last 15 Days</SelectItem>
87+
<SelectItem value="30d">Last 30 Days</SelectItem>
88+
<SelectItem value="all">All Time</SelectItem>
89+
</SelectContent>
90+
</Select>
91+
</div>
92+
</div>
93+
</CardContent>
94+
<CardFooter className="flex gap-4">
95+
<Button
96+
variant="outline"
97+
className="w-full flex items-center gap-2"
98+
onClick={() => handleExport("json")}
99+
disabled={isExporting}
100+
>
101+
<FileJson className="w-4 h-4" />
102+
Export as JSON
103+
</Button>
104+
<Button
105+
className="w-full flex items-center gap-2"
106+
onClick={() => handleExport("pdf")}
107+
disabled={isExporting}
108+
>
109+
<FileText className="w-4 h-4" />
110+
Export as PDF
111+
</Button>
112+
</CardFooter>
113+
</Card>
114+
</div>
115+
);
116+
}

client/src/pages/admin/overview.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ import { useQuery } from "@tanstack/react-query";
22
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
33
import { Users, ShieldCheck, DollarSign, Activity, Loader2 } from "lucide-react";
44
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
5+
import { useState } from "react";
6+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
57

68
export default function AdminOverview() {
9+
const [range, setRange] = useState("7d");
10+
711
const { data: metrics, isLoading } = useQuery<any>({
8-
queryKey: ["/api/admin/overview"],
12+
queryKey: ["/api/admin/overview", { range }],
913
refetchInterval: 2000,
1014
});
1115

@@ -21,9 +25,24 @@ export default function AdminOverview() {
2125

2226
return (
2327
<div className="container mx-auto py-8 px-4 max-w-6xl space-y-8">
24-
<div>
25-
<h1 className="text-3xl font-bold tracking-tight">Admin Overview</h1>
26-
<p className="text-muted-foreground">High-level metrics for CodeGuard.</p>
28+
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
29+
<div>
30+
<h1 className="text-3xl font-bold tracking-tight">Admin Overview</h1>
31+
<p className="text-muted-foreground">High-level metrics for CodeGuard.</p>
32+
</div>
33+
<div className="w-[180px]">
34+
<Select value={range} onValueChange={setRange}>
35+
<SelectTrigger>
36+
<SelectValue placeholder="Select Time Range" />
37+
</SelectTrigger>
38+
<SelectContent>
39+
<SelectItem value="7d">Last 7 Days</SelectItem>
40+
<SelectItem value="15d">Last 15 Days</SelectItem>
41+
<SelectItem value="30d">Last 30 Days</SelectItem>
42+
<SelectItem value="all">All Time</SelectItem>
43+
</SelectContent>
44+
</Select>
45+
</div>
2746
</div>
2847

2948
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
@@ -68,7 +87,7 @@ export default function AdminOverview() {
6887
<div className="grid gap-4 md:grid-cols-2">
6988
<Card className="col-span-1">
7089
<CardHeader>
71-
<CardTitle>User Growth (Last 7 Days)</CardTitle>
90+
<CardTitle>User Growth</CardTitle>
7291
<CardDescription>New user registrations over time</CardDescription>
7392
</CardHeader>
7493
<CardContent>
@@ -94,7 +113,7 @@ export default function AdminOverview() {
94113

95114
<Card className="col-span-1">
96115
<CardHeader>
97-
<CardTitle>Orders Volume (Last 7 Days)</CardTitle>
116+
<CardTitle>Orders Volume</CardTitle>
98117
<CardDescription>New audit orders placed over time</CardDescription>
99118
</CardHeader>
100119
<CardContent>

0 commit comments

Comments
 (0)