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) => (
))}
فعالیتهای اخیر
در حال توسعه...
);
}