- Add package.json with development and production dependencies - Create postcss.config.js for Tailwind CSS integration - Implement AdminController for handling admin routes - Add admin index template with React root element - Create base template for consistent layout - Configure TypeScript with tsconfig.json - Set up Webpack configuration for asset management
130 lines
3.5 KiB
TypeScript
130 lines
3.5 KiB
TypeScript
import React from 'react';
|
||
import {
|
||
UserGroupIcon,
|
||
HeartIcon,
|
||
BuildingOffice2Icon,
|
||
CalendarDaysIcon,
|
||
CreditCardIcon,
|
||
ChatBubbleLeftEllipsisIcon,
|
||
BanknotesIcon,
|
||
ArrowTrendingUpIcon,
|
||
} from '@heroicons/react/24/outline';
|
||
|
||
interface StatCardProps {
|
||
label: string;
|
||
value: string | number;
|
||
trend?: string;
|
||
trendUp?: boolean;
|
||
icon: React.ElementType;
|
||
iconBg: string;
|
||
iconColor: string;
|
||
}
|
||
|
||
function StatCard({ label, value, trend, trendUp, icon: Icon, iconBg, iconColor }: StatCardProps) {
|
||
return (
|
||
<div className="bg-white rounded-2xl shadow-[0_1px_3px_rgba(0,0,0,.08)] p-6">
|
||
<div className="flex items-start justify-between">
|
||
<div>
|
||
<p className="text-sm text-gray-500 mb-1">{label}</p>
|
||
<p className="text-3xl font-bold text-gray-900">{value}</p>
|
||
{trend && (
|
||
<div className={`flex items-center gap-1 mt-2 text-xs font-medium ${trendUp ? 'text-emerald-600' : 'text-red-500'}`}>
|
||
<ArrowTrendingUpIcon className={`w-3.5 h-3.5 ${!trendUp && 'rotate-180'}`} />
|
||
<span>{trend}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${iconBg}`}>
|
||
<Icon className={`w-6 h-6 ${iconColor}`} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const stats: StatCardProps[] = [
|
||
{
|
||
label: 'کل کاربران',
|
||
value: '۱۲,۴۸۴',
|
||
trend: '۸٪ نسبت به ماه قبل',
|
||
trendUp: true,
|
||
icon: UserGroupIcon,
|
||
iconBg: 'bg-violet-100',
|
||
iconColor: 'text-violet-600',
|
||
},
|
||
{
|
||
label: 'پزشکان فعال',
|
||
value: '۱,۲۸۴',
|
||
trend: '۱۲٪ نسبت به ماه قبل',
|
||
trendUp: true,
|
||
icon: HeartIcon,
|
||
iconBg: 'bg-emerald-100',
|
||
iconColor: 'text-emerald-600',
|
||
},
|
||
{
|
||
label: 'کلینیکها',
|
||
value: '۳۲۱',
|
||
trend: '۴٪ نسبت به ماه قبل',
|
||
trendUp: false,
|
||
icon: BuildingOffice2Icon,
|
||
iconBg: 'bg-blue-100',
|
||
iconColor: 'text-blue-600',
|
||
},
|
||
{
|
||
label: 'نوبتهای امروز',
|
||
value: '۱۴۸',
|
||
trend: '۲۳٪ نسبت به دیروز',
|
||
trendUp: true,
|
||
icon: CalendarDaysIcon,
|
||
iconBg: 'bg-orange-100',
|
||
iconColor: 'text-orange-600',
|
||
},
|
||
{
|
||
label: 'پرداختهای امروز',
|
||
value: '۴۸,۲۰۰,۰۰۰',
|
||
trend: '۱۵٪ نسبت به دیروز',
|
||
trendUp: true,
|
||
icon: CreditCardIcon,
|
||
iconBg: 'bg-pink-100',
|
||
iconColor: 'text-pink-600',
|
||
},
|
||
{
|
||
label: 'نظرات در انتظار',
|
||
value: '۱۲',
|
||
icon: ChatBubbleLeftEllipsisIcon,
|
||
iconBg: 'bg-yellow-100',
|
||
iconColor: 'text-yellow-600',
|
||
},
|
||
{
|
||
label: 'درخواست تسویه',
|
||
value: '۵',
|
||
icon: BanknotesIcon,
|
||
iconBg: 'bg-teal-100',
|
||
iconColor: 'text-teal-600',
|
||
},
|
||
];
|
||
|
||
export default function DashboardPage() {
|
||
return (
|
||
<div>
|
||
<div className="mb-6">
|
||
<h1 className="text-2xl font-bold text-gray-900">داشبورد</h1>
|
||
<p className="text-sm text-gray-500 mt-1">خلاصه وضعیت سیستم</p>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
|
||
{stats.map((stat) => (
|
||
<StatCard key={stat.label} {...stat} />
|
||
))}
|
||
</div>
|
||
|
||
<div className="mt-6 bg-white rounded-2xl shadow-[0_1px_3px_rgba(0,0,0,.08)] p-6">
|
||
<h3 className="text-base font-semibold text-gray-800 mb-4">فعالیتهای اخیر</h3>
|
||
<div className="text-center py-10 text-gray-400 text-sm">
|
||
در حال توسعه...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|