admin dashboard
This commit is contained in:
@@ -1,11 +1,155 @@
|
|||||||
import React from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { UsersIcon, CogIcon, DatabaseIcon, ChartBarIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { adminAPI } from '../../services/api';
|
||||||
|
import LoadingSpinner from '../../components/UI/LoadingSpinner';
|
||||||
|
|
||||||
const AdminDashboard = () => {
|
const AdminDashboard = () => {
|
||||||
|
const [stats, setStats] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchDashboardData = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await adminAPI.getDashboard();
|
||||||
|
setStats(response.data.data);
|
||||||
|
setError(null);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to fetch admin dashboard:', err);
|
||||||
|
setError('Failed to load dashboard data');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchDashboardData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div className="p-6">
|
||||||
|
<h1 className="text-2xl font-bold text-gray-900 mb-6">Admin Dashboard</h1>
|
||||||
|
<div className="flex justify-center items-center h-64">
|
||||||
|
<LoadingSpinner size="lg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-6">Admin Dashboard</h1>
|
<h1 className="text-2xl font-bold text-gray-900 mb-6">Admin Dashboard</h1>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<p className="text-gray-600">Admin dashboard coming soon...</p>
|
<div className="text-center py-8">
|
||||||
|
<p className="text-red-600 mb-4">{error}</p>
|
||||||
|
<button
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
className="btn-primary"
|
||||||
|
>
|
||||||
|
Retry
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const statCards = [
|
||||||
|
{
|
||||||
|
title: 'Total Users',
|
||||||
|
value: stats?.stats?.totalUsers || 0,
|
||||||
|
icon: UsersIcon,
|
||||||
|
color: 'blue',
|
||||||
|
subtitle: `${stats?.stats?.adminUsers || 0} admins`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Total Properties',
|
||||||
|
value: stats?.stats?.totalProperties || 0,
|
||||||
|
icon: DatabaseIcon,
|
||||||
|
color: 'green',
|
||||||
|
subtitle: `${stats?.stats?.totalEquipment || 0} equipment items`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Total Applications',
|
||||||
|
value: stats?.stats?.totalApplications || 0,
|
||||||
|
icon: ChartBarIcon,
|
||||||
|
color: 'purple',
|
||||||
|
subtitle: `${stats?.stats?.recentApplications || 0} recent`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Total Products',
|
||||||
|
value: stats?.stats?.totalProducts || 0,
|
||||||
|
icon: CogIcon,
|
||||||
|
color: 'green',
|
||||||
|
subtitle: `${stats?.stats?.customProducts || 0} custom`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6">
|
||||||
|
<div className="mb-6">
|
||||||
|
<h1 className="text-2xl font-bold text-gray-900">Admin Dashboard</h1>
|
||||||
|
<p className="text-gray-600">System overview and management</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stats Grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||||
|
{statCards.map((stat, index) => (
|
||||||
|
<div key={index} className="card">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className={`p-3 rounded-full bg-${stat.color}-100`}>
|
||||||
|
<stat.icon className={`h-6 w-6 text-${stat.color}-600`} />
|
||||||
|
</div>
|
||||||
|
<div className="ml-4">
|
||||||
|
<p className="text-sm font-medium text-gray-600">{stat.title}</p>
|
||||||
|
<p className="text-2xl font-bold text-gray-900">{stat.value}</p>
|
||||||
|
<p className="text-xs text-gray-500">{stat.subtitle}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Actions */}
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
<div className="card">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Quick Actions</h3>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<button className="w-full text-left p-3 rounded-lg border border-gray-200 hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="font-medium text-gray-900">Manage Users</div>
|
||||||
|
<div className="text-sm text-gray-500">View and manage user accounts</div>
|
||||||
|
</button>
|
||||||
|
<button className="w-full text-left p-3 rounded-lg border border-gray-200 hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="font-medium text-gray-900">System Settings</div>
|
||||||
|
<div className="text-sm text-gray-500">Configure system preferences</div>
|
||||||
|
</button>
|
||||||
|
<button className="w-full text-left p-3 rounded-lg border border-gray-200 hover:bg-gray-50 transition-colors">
|
||||||
|
<div className="font-medium text-gray-900">View Logs</div>
|
||||||
|
<div className="text-sm text-gray-500">Check system and application logs</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="card">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">Recent Activity</h3>
|
||||||
|
<div className="space-y-3">
|
||||||
|
{stats?.recentActivity?.length > 0 ? (
|
||||||
|
stats.recentActivity.map((activity, index) => (
|
||||||
|
<div key={index} className="flex items-center justify-between py-2">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-medium text-gray-900">{activity.action}</p>
|
||||||
|
<p className="text-xs text-gray-500">{activity.user}</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-gray-400">{activity.timestamp}</p>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p className="text-gray-500 text-sm">No recent activity</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user