129 lines
5.4 KiB
TypeScript
129 lines
5.4 KiB
TypeScript
import { useState, useEffect } from 'react';
|
||
import { DollarSign, ShoppingCart, Users, Activity } from 'lucide-react';
|
||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
|
||
import api from '../services/api';
|
||
|
||
export default function Dashboard() {
|
||
const [data, setData] = useState({
|
||
revenue: 0,
|
||
newOrders: 0,
|
||
users: 0,
|
||
todayVisits: 0
|
||
});
|
||
|
||
useEffect(() => {
|
||
const fetchStats = async () => {
|
||
try {
|
||
const response = await api.get('/admin/dashboard/stats');
|
||
if (response.data?.success) {
|
||
setData(response.data.data);
|
||
}
|
||
} catch (err) {
|
||
console.error('Failed to fetch stats', err);
|
||
}
|
||
};
|
||
fetchStats();
|
||
}, []);
|
||
|
||
const chartData = [
|
||
{ name: 'شنبه', بازدید: 400, فروش: 2400 },
|
||
{ name: 'یکشنبه', بازدید: 300, فروش: 1398 },
|
||
{ name: 'دوشنبه', بازدید: 200, فروش: 9800 },
|
||
{ name: 'سهشنبه', بازدید: 278, فروش: 3908 },
|
||
{ name: 'چهارشنبه', بازدید: 189, فروش: 4800 },
|
||
{ name: 'پنجشنبه', بازدید: 239, فروش: 3800 },
|
||
{ name: 'جمعه', بازدید: 349, فروش: 4300 },
|
||
];
|
||
|
||
const pieData = [
|
||
{ name: 'سگ', value: 400 },
|
||
{ name: 'گربه', value: 300 },
|
||
{ name: 'پرنده', value: 300 },
|
||
];
|
||
const COLORS = ['#0088FE', '#00C49F', '#FFBB28'];
|
||
|
||
const stats = [
|
||
{ title: 'درآمد کل', value: `${data.revenue.toLocaleString()} تومان`, icon: DollarSign, color: 'text-green-600', bg: 'bg-green-100' },
|
||
{ title: 'سفارشات جدید', value: data.newOrders.toString(), icon: ShoppingCart, color: 'text-blue-600', bg: 'bg-blue-100' },
|
||
{ title: 'کاربران فعال', value: data.users.toString(), icon: Users, color: 'text-purple-600', bg: 'bg-purple-100' },
|
||
{ title: 'بازدید امروز', value: data.todayVisits.toString(), icon: Activity, color: 'text-orange-600', bg: 'bg-orange-100' },
|
||
];
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<div>
|
||
<h2 className="text-2xl font-black text-gray-900">داشبورد</h2>
|
||
<p className="text-gray-500 font-medium mt-1">خلاصهای از وضعیت فروشگاه کانینو</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||
{stats.map((stat, i) => {
|
||
const Icon = stat.icon;
|
||
return (
|
||
<div key={i} className="bg-white p-6 rounded-2xl shadow-sm border border-gray-100 flex items-center gap-4">
|
||
<div className={`w-14 h-14 rounded-2xl flex items-center justify-center ${stat.bg}`}>
|
||
<Icon className={`w-6 h-6 ${stat.color}`} />
|
||
</div>
|
||
<div>
|
||
<p className="text-sm font-bold text-gray-500">{stat.title}</p>
|
||
<p className="text-xl font-black text-gray-900 mt-1">{stat.value}</p>
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-100 col-span-1 lg:col-span-2">
|
||
<h3 className="text-lg font-bold text-gray-900 mb-6">روند بازدید و فروش (۷ روز گذشته)</h3>
|
||
<div className="h-80 w-full" dir="ltr">
|
||
<ResponsiveContainer width="100%" height="100%">
|
||
<LineChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
|
||
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
||
<XAxis dataKey="name" axisLine={false} tickLine={false} />
|
||
<YAxis axisLine={false} tickLine={false} />
|
||
<Tooltip />
|
||
<Line type="monotone" dataKey="فروش" stroke="#8b5cf6" strokeWidth={3} dot={{ r: 4 }} activeDot={{ r: 8 }} />
|
||
<Line type="monotone" dataKey="بازدید" stroke="#10b981" strokeWidth={3} dot={{ r: 4 }} />
|
||
</LineChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="bg-white p-6 rounded-2xl shadow-sm border border-gray-100 col-span-1">
|
||
<h3 className="text-lg font-bold text-gray-900 mb-6">دستهبندی محصولات</h3>
|
||
<div className="h-80 w-full flex items-center justify-center">
|
||
<ResponsiveContainer width="100%" height="100%">
|
||
<PieChart>
|
||
<Pie
|
||
data={pieData}
|
||
cx="50%"
|
||
cy="50%"
|
||
innerRadius={60}
|
||
outerRadius={80}
|
||
fill="#8884d8"
|
||
paddingAngle={5}
|
||
dataKey="value"
|
||
>
|
||
{pieData.map((_entry, index) => (
|
||
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
|
||
))}
|
||
</Pie>
|
||
<Tooltip />
|
||
</PieChart>
|
||
</ResponsiveContainer>
|
||
</div>
|
||
<div className="flex justify-center gap-4 mt-4">
|
||
{pieData.map((entry, index) => (
|
||
<div key={entry.name} className="flex items-center gap-2">
|
||
<div className="w-3 h-3 rounded-full" style={{ backgroundColor: COLORS[index % COLORS.length] }}></div>
|
||
<span className="text-sm font-medium text-gray-600">{entry.name}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|