import React from 'react'; import { useQuery } from '@tanstack/react-query'; import { UserGroupIcon, HeartIcon, BuildingOffice2Icon, CalendarDaysIcon, CreditCardIcon, ChatBubbleLeftEllipsisIcon, BanknotesIcon, ArrowPathIcon, } from '@heroicons/react/24/outline'; import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import { formatNumber, formatRial } from '../lib/utils'; interface DashboardStats { total_users: number; active_doctors: number; total_doctors: number; total_clinics: number; today_appointments: number; total_appointments: number; today_payments_count: number; today_payments_amount: number; total_payments_amount: number; pending_comments: number; pending_settlements: number; } interface StatCardProps { label: string; value: string | number; sub?: string; icon: React.ElementType; iconBg: string; iconColor: string; loading?: boolean; } function StatCard({ label, value, sub, icon: Icon, iconBg, iconColor, loading }: StatCardProps) { return (

{label}

{loading ? (
) : (

{value}

)} {sub && !loading && (

{sub}

)} {sub && loading && (
)}
); } export default function DashboardPage() { const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['dashboard-stats'], queryFn: () => api.get>('/api/v1/admin/dashboard/stats'), staleTime: 60_000, }); const stats: DashboardStats | undefined = (data?.data as any)?.data ?? data?.data; const fn = (n: number | undefined) => (n !== undefined ? formatNumber(n) : '—'); const cards: StatCardProps[] = [ { label: 'کل کاربران', value: fn(stats?.total_users), icon: UserGroupIcon, iconBg: 'bg-violet-100', iconColor: 'text-violet-600', }, { label: 'پزشکان فعال', value: fn(stats?.active_doctors), sub: stats ? `از ${formatNumber(stats.total_doctors)} پزشک` : undefined, icon: HeartIcon, iconBg: 'bg-emerald-100', iconColor: 'text-emerald-600', }, { label: 'کلینیک‌ها', value: fn(stats?.total_clinics), icon: BuildingOffice2Icon, iconBg: 'bg-blue-100', iconColor: 'text-blue-600', }, { label: 'نوبت‌های امروز', value: fn(stats?.today_appointments), sub: stats ? `مجموع: ${formatNumber(stats.total_appointments)} نوبت` : undefined, icon: CalendarDaysIcon, iconBg: 'bg-orange-100', iconColor: 'text-orange-600', }, { label: 'درآمد امروز', value: stats?.today_payments_amount !== undefined ? formatRial(stats.today_payments_amount) : '—', sub: stats ? `${formatNumber(stats.today_payments_count)} تراکنش` : undefined, icon: CreditCardIcon, iconBg: 'bg-pink-100', iconColor: 'text-pink-600', }, { label: 'کل درآمد', value: stats?.total_payments_amount !== undefined ? formatRial(stats.total_payments_amount) : '—', icon: CreditCardIcon, iconBg: 'bg-indigo-100', iconColor: 'text-indigo-600', }, { label: 'نظرات در انتظار', value: fn(stats?.pending_comments), icon: ChatBubbleLeftEllipsisIcon, iconBg: 'bg-yellow-100', iconColor: 'text-yellow-600', }, { label: 'درخواست‌های تسویه', value: fn(stats?.pending_settlements), icon: BanknotesIcon, iconBg: 'bg-teal-100', iconColor: 'text-teal-600', }, ]; return (

داشبورد

خلاصه وضعیت سیستم

{isError && ( )}
{isError && (
خطا در دریافت اطلاعات — اطلاعات نمایش داده شده ممکن است به‌روز نباشند.
)}
{cards.map((card) => ( ))}

فعالیت‌های اخیر

در حال توسعه...
); }