1 import { useEffect } from "react";
2 import { useLocation } from "wouter";
3 import { useAuth } from "@/hooks/useAuth";
4 import { useAdminStats } from "@/hooks/useAdmin";
5 import { useToast } from "@/hooks/use-toast";
6 import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
7 import { Badge } from "@/components/ui/badge";
8
9 export default function AdminDashboard() {
10 const { user, isAuthenticated, isLoading: authLoading } = useAuth();
11 const { stats, isLoading: statsLoading } = useAdminStats();
12 const { toast } = useToast();
13 const [, setLocation] = useLocation();
14
15 // Redirect if not admin
16 useEffect(() => {
17 if (!authLoading && (!isAuthenticated || user?.role !== "admin")) {
18 toast({
19 title: "Access Denied",
20 description: "Administrator privileges required to access this page.",
21 variant: "destructive",
22 });
23 setLocation("/");
24 }
25 }, [user, isAuthenticated, authLoading, toast, setLocation]);
26
27 if (authLoading || statsLoading) {
28 return (
29 <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
30 <div className="animate-pulse space-y-6">
31 <div className="h-8 bg-muted rounded w-1/3"></div>
32 <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
33 {[...Array(3)].map((_, i) => (
34 <div key={i} className="h-32 bg-muted rounded-xl"></div>
35 ))}
36 </div>
37 </div>
38 </div>
39 );
40 }
41
42 if (!user || user.role !== "admin") {
43 return null; // Will redirect via useEffect
44 }
45
46 return (
47 <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-8">
48 {/* Header */}
49 <div className="mb-8">
50 <div className="flex items-center justify-between">
51 <div>
52 <h1 className="text-3xl font-bold text-gray-900 dark:text-white">
53 Admin Dashboard
54 </h1>
55 <p className="text-gray-600 dark:text-gray-400 mt-2">
56 Welcome back, {user.firstName || user.email}
57 </p>
58 </div>
59 <Badge variant="default" className="bg-green-600 text-white">
60 <i className="material-icons text-sm mr-1">admin_panel_settings</i>
61 Administrator
62 </Badge>
63 </div>
64 </div>
65
66 {/* Stats Cards */}
67 <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
68 <Card>
69 <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
70 <CardTitle className="text-sm font-medium">Total Guides</CardTitle>
71 <i className="material-icons text-primary-600">library_books</i>
72 </CardHeader>
73 <CardContent>
74 <div className="text-2xl font-bold">{stats?.totalGuides || 0}</div>
75 <p className="text-xs text-gray-600 dark:text-gray-400">
76 Active repair guides
77 </p>
78 </CardContent>
79 </Card>
80
81 <Card>
82 <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
83 <CardTitle className="text-sm font-medium">Total Views</CardTitle>
84 <i className="material-icons text-blue-600">visibility</i>
85 </CardHeader>
86 <CardContent>
87 <div className="text-2xl font-bold">{stats?.totalViews || 0}</div>
88 <p className="text-xs text-gray-600 dark:text-gray-400">
89 Across all guides
90 </p>
91 </CardContent>
92 </Card>
93
94 <Card>
95 <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
96 <CardTitle className="text-sm font-medium">Total Downloads</CardTitle>
97 <i className="material-icons text-green-600">download</i>
98 </CardHeader>
99 <CardContent>
100 <div className="text-2xl font-bold">{stats?.totalDownloads || 0}</div>
101 <p className="text-xs text-gray-600 dark:text-gray-400">
102 Guide downloads
103 </p>
104 </CardContent>
105 </Card>
106 </div>
107
108 {/* Admin Info */}
109 <Card className="mb-8">
110 <CardHeader>
111 <CardTitle className="flex items-center">
112 <i className="material-icons text-lg mr-2">account_circle</i>
113 Administrator Information
114 </CardTitle>
115 </CardHeader>
116 <CardContent>
117 <div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
118 <div>
119 <span className="font-medium text-gray-900 dark:text-white">Email:</span>
120 <span className="ml-2 text-gray-600 dark:text-gray-400">{user.email}</span>
121 </div>
122 <div>
123 <span className="font-medium text-gray-900 dark:text-white">Role:</span>
124 <span className="ml-2 text-gray-600 dark:text-gray-400">Administrator</span>
125 </div>
126 <div>
127 <span className="font-medium text-gray-900 dark:text-white">Name:</span>
128 <span className="ml-2 text-gray-600 dark:text-gray-400">
129 {user.firstName} {user.lastName}
130 </span>
131 </div>
132 <div>
133 <span className="font-medium text-gray-900 dark:text-white">User ID:</span>
134 <span className="ml-2 text-gray-600 dark:text-gray-400 font-mono text-xs">
135 {user.id}
136 </span>
137 </div>
138 </div>
139 </CardContent>
140 </Card>
141
142 {/* System Information */}
143 <Card>
144 <CardHeader>
145 <CardTitle className="flex items-center">
146 <i className="material-icons text-lg mr-2">info</i>
147 System Information
148 </CardTitle>
149 </CardHeader>
150 <CardContent>
151 <div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
152 <div>
153 <span className="font-medium text-gray-900 dark:text-white">App Version:</span>
154 <span className="ml-2 text-gray-600 dark:text-gray-400">1.0.0</span>
155 </div>
156 <div>
157 <span className="font-medium text-gray-900 dark:text-white">Build Date:</span>
158 <span className="ml-2 text-gray-600 dark:text-gray-400">2025.08.18</span>
159 </div>
160 <div>
161 <span className="font-medium text-gray-900 dark:text-white">Database:</span>
162 <span className="ml-2 text-gray-600 dark:text-gray-400">PostgreSQL (Connected)</span>
163 </div>
164 <div>
165 <span className="font-medium text-gray-900 dark:text-white">Authentication:</span>
166 <span className="ml-2 text-gray-600 dark:text-gray-400">Firebase Auth</span>
167 </div>
168 </div>
169 </CardContent>
170 </Card>
171 </div>
172 );
173 }