mirror of
https://gitea.gofwd.group/sean/gunbuilder-next-tailwind.git
synced 2025-12-05 18:46:45 -05:00
278 lines
12 KiB
TypeScript
278 lines
12 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from 'react';
|
|
import {
|
|
Users,
|
|
ShoppingCart,
|
|
TrendingUp,
|
|
AlertTriangle,
|
|
CheckCircle,
|
|
Clock,
|
|
BarChart3,
|
|
Activity,
|
|
Calendar,
|
|
Settings
|
|
} from 'lucide-react';
|
|
|
|
export default function AdminDashboard() {
|
|
const [selectedPeriod, setSelectedPeriod] = useState('7d');
|
|
|
|
// Sample data - in a real app, this would come from your database
|
|
const stats = {
|
|
totalUsers: 1247,
|
|
activeUsers: 892,
|
|
totalProducts: 15420,
|
|
totalBuilds: 3421,
|
|
revenue: 45678,
|
|
growth: 12.5,
|
|
pendingApprovals: 23,
|
|
systemAlerts: 2
|
|
};
|
|
|
|
const recentActivity = [
|
|
{ id: 1, user: 'John Doe', action: 'Created new build', time: '2 minutes ago', type: 'build' },
|
|
{ id: 2, user: 'Jane Smith', action: 'Updated profile', time: '5 minutes ago', type: 'profile' },
|
|
{ id: 3, user: 'Mike Johnson', action: 'Added product to cart', time: '8 minutes ago', type: 'cart' },
|
|
{ id: 4, user: 'Sarah Wilson', action: 'Completed purchase', time: '12 minutes ago', type: 'purchase' },
|
|
{ id: 5, user: 'Admin User', action: 'Updated category mapping', time: '15 minutes ago', type: 'admin' }
|
|
];
|
|
|
|
const topProducts = [
|
|
{ name: 'AR-15 Lower Receiver', sales: 156, revenue: 12480 },
|
|
{ name: 'Tactical Scope', sales: 89, revenue: 17800 },
|
|
{ name: 'Gun Case', sales: 234, revenue: 11700 },
|
|
{ name: 'Ammo Storage', sales: 67, revenue: 3350 },
|
|
{ name: 'Cleaning Kit', sales: 189, revenue: 5670 }
|
|
];
|
|
|
|
const systemStatus = [
|
|
{ service: 'Database', status: 'healthy', uptime: '99.9%' },
|
|
{ service: 'API', status: 'healthy', uptime: '99.8%' },
|
|
{ service: 'File Storage', status: 'warning', uptime: '98.5%' },
|
|
{ service: 'Email Service', status: 'healthy', uptime: '99.7%' }
|
|
];
|
|
|
|
return (
|
|
<div className="p-8">
|
|
{/* Header */}
|
|
<div className="flex justify-between items-center mb-8">
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-gray-900">Admin Dashboard</h1>
|
|
<p className="text-gray-600 mt-1">Welcome back! Here's what's happening with your platform.</p>
|
|
</div>
|
|
<div className="flex items-center space-x-4">
|
|
<select
|
|
value={selectedPeriod}
|
|
onChange={(e) => setSelectedPeriod(e.target.value)}
|
|
className="border border-gray-300 rounded-md px-3 py-2 text-sm"
|
|
>
|
|
<option value="24h">Last 24 hours</option>
|
|
<option value="7d">Last 7 days</option>
|
|
<option value="30d">Last 30 days</option>
|
|
<option value="90d">Last 90 days</option>
|
|
</select>
|
|
<button className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors">
|
|
<Settings className="w-4 h-4 inline mr-2" />
|
|
Settings
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Cards */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
<div className="bg-white rounded-lg shadow p-6">
|
|
<div className="flex items-center">
|
|
<div className="p-2 bg-blue-100 rounded-lg">
|
|
<Users className="w-6 h-6 text-blue-600" />
|
|
</div>
|
|
<div className="ml-4">
|
|
<p className="text-sm font-medium text-gray-600">Total Users</p>
|
|
<p className="text-2xl font-bold text-gray-900">{stats.totalUsers.toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex items-center text-sm">
|
|
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
|
|
<span className="text-green-600">+{stats.growth}%</span>
|
|
<span className="text-gray-500 ml-1">from last month</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-lg shadow p-6">
|
|
<div className="flex items-center">
|
|
<div className="p-2 bg-green-100 rounded-lg">
|
|
<ShoppingCart className="w-6 h-6 text-green-600" />
|
|
</div>
|
|
<div className="ml-4">
|
|
<p className="text-sm font-medium text-gray-600">Total Products</p>
|
|
<p className="text-2xl font-bold text-gray-900">{stats.totalProducts.toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex items-center text-sm">
|
|
<CheckCircle className="w-4 h-4 text-green-500 mr-1" />
|
|
<span className="text-green-600">Active</span>
|
|
<span className="text-gray-500 ml-1">in catalog</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-lg shadow p-6">
|
|
<div className="flex items-center">
|
|
<div className="p-2 bg-purple-100 rounded-lg">
|
|
<BarChart3 className="w-6 h-6 text-purple-600" />
|
|
</div>
|
|
<div className="ml-4">
|
|
<p className="text-sm font-medium text-gray-600">Total Builds</p>
|
|
<p className="text-2xl font-bold text-gray-900">{stats.totalBuilds.toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex items-center text-sm">
|
|
<Activity className="w-4 h-4 text-blue-500 mr-1" />
|
|
<span className="text-blue-600">{stats.activeUsers}</span>
|
|
<span className="text-gray-500 ml-1">active users</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-lg shadow p-6">
|
|
<div className="flex items-center">
|
|
<div className="p-2 bg-orange-100 rounded-lg">
|
|
<TrendingUp className="w-6 h-6 text-orange-600" />
|
|
</div>
|
|
<div className="ml-4">
|
|
<p className="text-sm font-medium text-gray-600">Revenue</p>
|
|
<p className="text-2xl font-bold text-gray-900">${stats.revenue.toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 flex items-center text-sm">
|
|
<TrendingUp className="w-4 h-4 text-green-500 mr-1" />
|
|
<span className="text-green-600">+8.2%</span>
|
|
<span className="text-gray-500 ml-1">from last month</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Alerts and Notifications */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
|
<div className="lg:col-span-2">
|
|
<div className="bg-white rounded-lg shadow">
|
|
<div className="p-6 border-b border-gray-200">
|
|
<h3 className="text-lg font-medium text-gray-900">Recent Activity</h3>
|
|
</div>
|
|
<div className="p-6">
|
|
<div className="space-y-4">
|
|
{recentActivity.map((activity) => (
|
|
<div key={activity.id} className="flex items-center space-x-3">
|
|
<div className={`w-2 h-2 rounded-full ${
|
|
activity.type === 'build' ? 'bg-blue-500' :
|
|
activity.type === 'profile' ? 'bg-green-500' :
|
|
activity.type === 'cart' ? 'bg-orange-500' :
|
|
activity.type === 'purchase' ? 'bg-purple-500' :
|
|
'bg-gray-500'
|
|
}`} />
|
|
<div className="flex-1">
|
|
<p className="text-sm font-medium text-gray-900">{activity.user}</p>
|
|
<p className="text-sm text-gray-500">{activity.action}</p>
|
|
</div>
|
|
<div className="text-sm text-gray-400">{activity.time}</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
{/* Pending Actions */}
|
|
<div className="bg-white rounded-lg shadow">
|
|
<div className="p-6 border-b border-gray-200">
|
|
<h3 className="text-lg font-medium text-gray-900">Pending Actions</h3>
|
|
</div>
|
|
<div className="p-6">
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center">
|
|
<AlertTriangle className="w-5 h-5 text-yellow-500 mr-3" />
|
|
<span className="text-sm font-medium">Approvals Needed</span>
|
|
</div>
|
|
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-2 py-1 rounded-full">
|
|
{stats.pendingApprovals}
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center">
|
|
<AlertTriangle className="w-5 h-5 text-red-500 mr-3" />
|
|
<span className="text-sm font-medium">System Alerts</span>
|
|
</div>
|
|
<span className="bg-red-100 text-red-800 text-xs font-medium px-2 py-1 rounded-full">
|
|
{stats.systemAlerts}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* System Status */}
|
|
<div className="bg-white rounded-lg shadow">
|
|
<div className="p-6 border-b border-gray-200">
|
|
<h3 className="text-lg font-medium text-gray-900">System Status</h3>
|
|
</div>
|
|
<div className="p-6">
|
|
<div className="space-y-3">
|
|
{systemStatus.map((service, index) => (
|
|
<div key={index} className="flex items-center justify-between">
|
|
<span className="text-sm font-medium text-gray-900">{service.service}</span>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${
|
|
service.status === 'healthy' ? 'bg-green-500' : 'bg-yellow-500'
|
|
}`} />
|
|
<span className="text-xs text-gray-500">{service.uptime}</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Top Products */}
|
|
<div className="bg-white rounded-lg shadow">
|
|
<div className="p-6 border-b border-gray-200">
|
|
<h3 className="text-lg font-medium text-gray-900">Top Products</h3>
|
|
</div>
|
|
<div className="p-6">
|
|
<div className="overflow-x-auto">
|
|
<table className="min-w-full divide-y divide-gray-200">
|
|
<thead>
|
|
<tr>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Product
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Sales
|
|
</th>
|
|
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
Revenue
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="bg-white divide-y divide-gray-200">
|
|
{topProducts.map((product, index) => (
|
|
<tr key={index}>
|
|
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
|
|
{product.name}
|
|
</td>
|
|
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
{product.sales}
|
|
</td>
|
|
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
${product.revenue.toLocaleString()}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|