- Refactored PaymentsPage, RatingsPage, RepresentationDetailPage, RepresentationsPage, SecretariesPage, SettlementsPage, SmsPage, UserDetailPage, and UsersPage to use consistent class names for styling. - Updated button styles to use new utility classes for primary, secondary, and danger buttons. - Enhanced dark mode support across various components by adjusting text and background colors. - Introduced new utility classes for form inputs, labels, and info rows to standardize styling. - Implemented Zustand for persistent UI state management, including dark mode toggle functionality. - Updated CSS to include new styles for skeleton loading and animations. - Added optional dependencies for improved compatibility with different platforms.
111 lines
4.3 KiB
TypeScript
111 lines
4.3 KiB
TypeScript
import React from 'react';
|
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { ArrowRightIcon } from '@heroicons/react/24/outline';
|
|
import { api } from '../lib/api';
|
|
import type { ApiResponse } from '../lib/api';
|
|
import type { Doctor } from '../types';
|
|
import { formatDate } from '../lib/utils';
|
|
import PageHeader from '../components/ui/PageHeader';
|
|
import { ActiveBadge } from '../components/ui/StatusBadge';
|
|
|
|
function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
|
|
return (
|
|
<div className="cp-info-row">
|
|
<span className="cp-info-label text-sm">{label}</span>
|
|
<span className="cp-info-value">{value ?? '—'}</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function DoctorDetailPage() {
|
|
const { uuid } = useParams<{ uuid: string }>();
|
|
const navigate = useNavigate();
|
|
|
|
const { data, isLoading } = useQuery({
|
|
queryKey: ['doctor', uuid],
|
|
queryFn: () => api.get<ApiResponse<Doctor>>(`/api/v1/doctor/${uuid}`),
|
|
enabled: !!uuid,
|
|
});
|
|
|
|
const doctor = data?.data;
|
|
|
|
return (
|
|
<div>
|
|
<PageHeader
|
|
title="جزئیات پزشک"
|
|
breadcrumbs={[
|
|
{ label: 'داشبورد', to: '/admin/dashboard' },
|
|
{ label: 'پزشکان', to: '/admin/doctors' },
|
|
{ label: 'جزئیات' },
|
|
]}
|
|
action={
|
|
<button
|
|
onClick={() => navigate('/admin/doctors')}
|
|
className="flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-100 transition-colors"
|
|
>
|
|
<ArrowRightIcon className="w-4 h-4" />
|
|
بازگشت
|
|
</button>
|
|
}
|
|
/>
|
|
|
|
{isLoading ? (
|
|
<div className="cp-card p-6 space-y-3">
|
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
<div key={i} className="h-8 rounded-lg skeleton" />
|
|
))}
|
|
</div>
|
|
) : doctor ? (
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
|
|
<div className="flex items-center gap-4 mb-6">
|
|
{doctor.profile_image ? (
|
|
<img src={doctor.profile_image} alt="" className="w-16 h-16 rounded-full object-cover" />
|
|
) : (
|
|
<div className="w-16 h-16 rounded-full bg-primary-100 flex items-center justify-center text-primary-700 text-2xl font-bold">
|
|
{doctor.first_name?.[0] ?? '?'}
|
|
</div>
|
|
)}
|
|
<div>
|
|
<h2 className="font-bold text-gray-900">دکتر {doctor.first_name} {doctor.last_name}</h2>
|
|
<p className="text-sm text-gray-500">{doctor.degree}</p>
|
|
</div>
|
|
</div>
|
|
<InfoRow label="کد نظام پزشکی" value={<span dir="ltr">{doctor.medical_code}</span>} />
|
|
<InfoRow label="جنسیت" value={doctor.gender === 'male' ? 'آقا' : 'خانم'} />
|
|
<InfoRow label="وضعیت" value={<ActiveBadge active={doctor.is_active} />} />
|
|
<InfoRow label="تاریخ ثبت" value={formatDate(doctor.created_at)} />
|
|
</div>
|
|
|
|
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
|
|
<h3 className="font-semibold text-gray-800 mb-4">تخصصها</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{doctor.specialties?.length ? (
|
|
doctor.specialties.map((s) => (
|
|
<span key={s.uuid} className="px-3 py-1 bg-primary-50 text-primary-700 text-sm rounded-full">
|
|
{s.name}
|
|
</span>
|
|
))
|
|
) : (
|
|
<span className="text-gray-400 text-sm">تخصصی ثبت نشده</span>
|
|
)}
|
|
</div>
|
|
|
|
{doctor.bio && (
|
|
<div className="mt-6">
|
|
<h3 className="font-semibold text-gray-800 mb-2">بیوگرافی</h3>
|
|
<p className="text-sm text-gray-600 leading-relaxed">{doctor.bio}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="bg-white rounded-2xl border border-gray-100 p-16 text-center text-gray-400">
|
|
پزشکی یافت نشد
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|