193 lines
7.9 KiB
TypeScript
193 lines
7.9 KiB
TypeScript
import { Users, ShoppingBag, DollarSign, TrendingUp, BarChart3, Plus, Clock } from 'lucide-react';
|
||
import { StatsCard } from '../components/dashboard/StatsCard';
|
||
import { BarChart } from '../components/charts/BarChart';
|
||
import { lazy, Suspense } from 'react';
|
||
import { useOrderStats } from './orders/core/_hooks';
|
||
|
||
const LineChart = lazy(() => import('../components/charts/LineChart').then(module => ({ default: module.LineChart })));
|
||
import { PieChart } from '../components/charts/PieChart';
|
||
import { Table } from '../components/ui/Table';
|
||
import { Button } from '../components/ui/Button';
|
||
import { PermissionWrapper } from '../components/common/PermissionWrapper';
|
||
import { PageContainer, PageTitle, CardTitle } from '../components/ui/Typography';
|
||
import { ChartData, TableColumn } from '../types';
|
||
|
||
const useDashboardStats = () => {
|
||
const { data, isLoading, error } = useOrderStats(true);
|
||
const items = [
|
||
{
|
||
title: 'کل سفارشات',
|
||
value: data?.total_orders_count ?? 0,
|
||
icon: ShoppingBag,
|
||
color: 'yellow' as const,
|
||
},
|
||
{
|
||
title: 'مجموع فروش',
|
||
value: data?.total_amount_of_sale ?? 0,
|
||
icon: DollarSign,
|
||
color: 'green' as const,
|
||
},
|
||
{
|
||
title: 'سفارشهای در انتظار',
|
||
value: data?.total_order_pending ?? 0,
|
||
icon: Clock,
|
||
color: 'blue' as const,
|
||
},
|
||
{
|
||
title: 'میانگین سفارش',
|
||
value: data?.order_avg ?? 0,
|
||
icon: TrendingUp,
|
||
color: 'purple' as const,
|
||
},
|
||
];
|
||
return { items, isLoading, error };
|
||
};
|
||
|
||
const chartData: ChartData[] = [
|
||
{ name: 'فروردین', value: 4000 },
|
||
{ name: 'اردیبهشت', value: 3000 },
|
||
{ name: 'خرداد', value: 5000 },
|
||
{ name: 'تیر', value: 4500 },
|
||
{ name: 'مرداد', value: 6000 },
|
||
{ name: 'شهریور', value: 5500 },
|
||
];
|
||
|
||
const pieData: ChartData[] = [
|
||
{ name: 'دسکتاپ', value: 45 },
|
||
{ name: 'موبایل', value: 35 },
|
||
{ name: 'تبلت', value: 20 },
|
||
];
|
||
|
||
const recentUsers = [
|
||
{ id: 1, name: 'علی احمدی', email: 'ali@example.com', role: 'کاربر', status: 'فعال', createdAt: '۱۴۰۲/۰۸/۱۵' },
|
||
{ id: 2, name: 'فاطمه حسینی', email: 'fateme@example.com', role: 'مدیر', status: 'فعال', createdAt: '۱۴۰۲/۰۸/۱۴' },
|
||
{ id: 3, name: 'محمد رضایی', email: 'mohammad@example.com', role: 'کاربر', status: 'غیرفعال', createdAt: '۱۴۰۲/۰۸/۱۳' },
|
||
{ id: 4, name: 'زهرا کریمی', email: 'zahra@example.com', role: 'کاربر', status: 'فعال', createdAt: '۱۴۰۲/۰۸/۱۲' },
|
||
];
|
||
|
||
const userColumns: TableColumn[] = [
|
||
{ key: 'name', label: 'نام', sortable: true },
|
||
{ key: 'email', label: 'ایمیل' },
|
||
{ key: 'role', label: 'نقش' },
|
||
{
|
||
key: 'status',
|
||
label: 'وضعیت',
|
||
render: (value) => (
|
||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${value === 'فعال'
|
||
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'
|
||
: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
|
||
}`}>
|
||
{value}
|
||
</span>
|
||
)
|
||
},
|
||
{ key: 'createdAt', label: 'تاریخ عضویت' },
|
||
{
|
||
key: 'actions',
|
||
label: 'عملیات',
|
||
render: () => (
|
||
<div className="flex space-x-2">
|
||
<Button size="sm" variant="secondary">
|
||
ویرایش
|
||
</Button>
|
||
<PermissionWrapper permission={22}>
|
||
<Button size="sm" variant="danger">
|
||
حذف
|
||
</Button>
|
||
</PermissionWrapper>
|
||
</div>
|
||
)
|
||
}
|
||
];
|
||
|
||
export const Dashboard = () => {
|
||
const { items: statsData, isLoading: statsLoading, error: statsError } = useDashboardStats();
|
||
return (
|
||
<PageContainer>
|
||
{/* Header with mobile-responsive layout */}
|
||
<div className="flex flex-col space-y-3 sm:flex-row sm:items-center sm:justify-between sm:space-y-0">
|
||
<PageTitle>داشبورد</PageTitle>
|
||
<div className="flex justify-start gap-3">
|
||
<button
|
||
className="flex items-center justify-center w-12 h-12 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 rounded-full transition-colors duration-200 text-gray-600 dark:text-gray-300"
|
||
title="گزارشگیری"
|
||
>
|
||
<BarChart3 className="h-5 w-5" />
|
||
</button>
|
||
<PermissionWrapper permission={25}>
|
||
<button
|
||
className="flex items-center justify-center w-12 h-12 bg-primary-600 hover:bg-primary-700 rounded-full transition-colors duration-200 text-white shadow-lg hover:shadow-xl"
|
||
title="اضافه کردن"
|
||
>
|
||
<Plus className="h-5 w-5" />
|
||
</button>
|
||
</PermissionWrapper>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Stats Cards - Mobile responsive grid */}
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 lg:gap-6">
|
||
{statsLoading ? (
|
||
<>
|
||
{[...Array(4)].map((_, idx) => (
|
||
<div key={idx} className="card p-6 animate-pulse bg-gray-100 dark:bg-gray-800 h-24" />
|
||
))}
|
||
</>
|
||
) : (
|
||
statsData.map((stat, index) => (
|
||
<StatsCard key={index} {...stat} />
|
||
))
|
||
)}
|
||
</div>
|
||
{statsError && (
|
||
<div className="mt-2 text-sm text-red-600 dark:text-red-400">
|
||
خطا در دریافت آمار سفارشات
|
||
</div>
|
||
)}
|
||
|
||
{/* Charts - Better mobile layout */}
|
||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4 sm:gap-6">
|
||
<div className="min-w-0">
|
||
<BarChart
|
||
data={chartData}
|
||
title="فروش ماهانه"
|
||
color="#3b82f6"
|
||
/>
|
||
</div>
|
||
<div className="min-w-0">
|
||
<Suspense fallback={<div className="card p-6 animate-pulse bg-gray-100 dark:bg-gray-800 h-64" />}>
|
||
<LineChart
|
||
data={chartData}
|
||
title="روند رشد"
|
||
color="#10b981"
|
||
/>
|
||
</Suspense>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Table and Pie Chart - Mobile responsive */}
|
||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4 sm:gap-6">
|
||
<div className="xl:col-span-2 min-w-0">
|
||
<div className="card p-3 sm:p-4 lg:p-6">
|
||
<CardTitle className="mb-3 sm:mb-4">
|
||
کاربران اخیر
|
||
</CardTitle>
|
||
<div className="overflow-x-auto">
|
||
<Table
|
||
columns={userColumns}
|
||
data={recentUsers}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="min-w-0">
|
||
<PieChart
|
||
data={pieData}
|
||
title="دستگاههای کاربری"
|
||
colors={['#3b82f6', '#10b981', '#f59e0b']}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</PageContainer>
|
||
);
|
||
};
|