admin/src/pages/Dashboard.tsx

193 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
};