feat: add doctor profile page with sidebar integration and routing

This commit is contained in:
hamed
2026-06-11 19:06:59 +03:30
parent 704075770b
commit 277922d4ae
7 changed files with 347 additions and 76 deletions
+202
View File
@@ -0,0 +1,202 @@
# صفحه پروفایل پزشک (Doctor Profile Page)
## هدف
پزشک باید صفحه‌ای داشته باشد که بتواند تمام اطلاعات مربوط به خودش را مشاهده و ویرایش کند — دقیقاً مشابه `/admin/doctors/{uuid}` که ادمین می‌بیند، اما:
- به صورت خودکار UUID پزشک لاگین‌شده از `authStore.dbUuid` خوانده می‌شود
- آدرس صفحه: `/admin/profile`
- در سایدبار دکتر یک آیتم "پروفایل من" اضافه می‌شود
---
## وضعیت فعلی (چه داریم)
### صفحه موجود
- `DoctorDetailPage.tsx` در مسیر `/admin/doctors/:uuid` برای **ادمین + دکتر** قابل دسترسی است
- صفحه کامل است و شامل: اطلاعات پروفایل، آدرس مطب، تنظیمات نوبت‌دهی، تعطیلات، تاریخ‌های خاص
- دکتر با UUID خودش می‌تواند این صفحه را ببیند اما **لینکی در منوی دکتر وجود ندارد**
### سایدبار دکتر (فعلی)
```
عمومی:
- داشبورد
مدیریت:
- نوبت‌های من
```
### Auth Store
- `authStore.dbUuid` = UUID دکتر لاگین‌شده
- `authStore.primaryRole` = 'doctor'
---
## API‌های موجود (بررسی‌شده)
| Endpoint | وضعیت | کاربرد |
|----------|-------|---------|
| `GET /api/v1/doctor/{uuid}` | ✅ PUBLIC | خواندن پروفایل (double-nested: `data?.data?.data`) |
| `PATCH /api/v1/doctor/{uuid}` | ✅ AUTH | ویرایش پروفایل |
| `POST /api/v1/clinic-pro/doctor-address` | ✅ AUTH | افزودن آدرس مطب |
| `PATCH /api/v1/clinic-pro/doctor-address/{id}` | ✅ AUTH | ویرایش آدرس |
| `DELETE /api/v1/clinic-pro/doctor-address/{id}` | ✅ AUTH | حذف آدرس |
| `GET /api/v1/clinic-pro/doctor-addresses/{doctorId}` | ✅ AUTH | لیست آدرس‌ها |
| `GET /api/v1/appointment-settings/weekly-schedule/{doctorUuid}` | ✅ AUTH | برنامه هفتگی |
| `POST /api/v1/appointment-settings/weekly-schedule` | ✅ AUTH | ساخت برنامه هفتگی |
| `PATCH /api/v1/appointment-settings/weekly-schedule/{uuid}` | ✅ AUTH | ویرایش برنامه هفتگی |
| `GET /api/v1/appointment-settings/date-override/list/{doctorUuid}` | ✅ AUTH | تاریخ‌های خاص |
| `GET /api/v1/appointment-settings/holidays/list/{doctorUuid}` | ✅ AUTH | تعطیلات |
| `GET /api/v1/my/appointments/today-stats?date=...` | ✅ AUTH | آمار نوبت‌ها |
---
## قابلیت‌هایی که باید ساخته شود
### قابلیت ۱ — Route + Sidebar
**فایل‌ها:**
- `assets/admin/App.tsx` — افزودن route `/admin/profile`
- `assets/admin/components/layout/Sidebar.tsx` — افزودن "پروفایل من" به منوی دکتر
**Route:**
```tsx
<Route path="profile" element={<DoctorProfilePage />} />
```
**Sidebar (doctor):**
```
عمومی:
- داشبورد
پروفایل:
- پروفایل من ← /admin/profile
مدیریت:
- نوبت‌های من
- تنظیمات نوبت‌دهی ← /admin/appointment-settings (اختیاری)
```
---
### قابلیت ۲ — `DoctorProfilePage.tsx`
**ساختار صفحه** (با tab برای سازماندهی):
```
┌──────────────────────────────────────────────────────────────┐
│ [عکس] دکتر [نام] ویرایش پروفایل │
│ [تخصص] [درجه] │
└──────────────────────────────────────────────────────────────┘
[ اطلاعات عمومی ] [ آدرس مطب ] [ تنظیمات نوبت‌دهی ]
↑ تب‌ها
──── محتوای هر تب ────
```
**تب ۱ — اطلاعات عمومی** (ویرایش inline):
- نام کامل
- جنسیت (مرد/زن)
- درجه علمی (عمومی / متخصص / فوق‌تخصص / فلوشیپ)
- کد نظام پزشکی
- تخصص‌ها (multi-select از `GET /api/v1/categorys/specially_doctor`)
- سرویس‌ها (multi-select از `GET /api/v1/categorys/doctor_services` یا `GET /api/v1/doctor-services`)
- بیوگرافی (textarea)
- بارگذاری عکس پروفایل
فرم: React Hook Form + Zod
Submit: `PATCH /api/v1/doctor/{uuid}`
**تب ۲ — آدرس مطب** (CRUD):
- لیست آدرس‌ها با نام + آدرس + تلفن
- دکمه "افزودن آدرس" → Modal با فرم:
- نام مطب
- آدرس
- تلفن
- استان + شهر (از category API)
- نقشه (Leaflet — اختیاری اگر پیچیده باشد)
- ویرایش + حذف هر آدرس
**تب ۳ — تنظیمات نوبت‌دهی** (مشابه آنچه در DoctorDetailPage وجود دارد):
- برنامه هفتگی (weekly schedule) — مشاهده + ویرایش
- تعطیلات (holidays) — لیست + افزودن + حذف
- تاریخ‌های خاص (date overrides) — لیست + مدیریت
---
## نکات پیاده‌سازی
### گرفتن UUID دکتر
```tsx
const uuid = useAuthStore(s => s.dbUuid);
```
### Double-nested response برای GET doctor
```tsx
// پاسخ: { success: true, data: { data: { uuid, name, ... } } }
const doctor = data?.data?.data;
```
### استفاده مجدد از DoctorDetailPage
اگر `DoctorDetailPage.tsx` قابل reuse است:
- می‌توان یک wrapper ساده ساخت که فقط `uuid` را از `authStore.dbUuid` می‌گیرد و پاس می‌دهد
- اما اگر رفتار صفحه برای ادمین و دکتر تفاوت دارد (مثلاً ادمین می‌تواند دکتر را غیرفعال کند ولی دکتر نمی‌تواند) باید برخی بخش‌ها را با `isAdmin` شرطی کرد
### بخش‌هایی که فقط ادمین می‌بیند (باید پنهان شوند):
- دکمه "غیرفعال کردن حساب دکتر"
- دکمه "حذف دکتر"
- لیست کلینیک‌هایی که دکتر عضو است (فقط نمایش — بدون حذف از کلینیک)
### بخش‌هایی که دکتر اضافه می‌بیند (اختیاری):
- آمار خلاصه نوبت‌های امروز (از `GET /api/v1/my/appointments/today-stats`)
---
## فایل‌های تأثیرپذیر
| فایل | تغییر |
|------|-------|
| `assets/admin/pages/DoctorProfilePage.tsx` | **جدید** — صفحه پروفایل پزشک |
| `assets/admin/App.tsx` | افزودن route `/admin/profile` |
| `assets/admin/components/layout/Sidebar.tsx` | افزودن "پروفایل من" به منوی دکتر |
| `assets/admin/pages/DoctorDetailPage.tsx` | اختیاری — اگر نیاز به تغییر رفتار ادمین/دکتر |
---
## رویکرد پیشنهادی
**ساده‌ترین راه** (بدون duplicate کد):
1. در `App.tsx` route جدید:
```tsx
<Route path="profile" element={<Navigate to={`/admin/doctors/${dbUuid}`} replace />} />
```
اما این روش نیاز به دسترسی به `dbUuid` در سطح App دارد.
**روش بهتر:**
```tsx
// DoctorProfilePage.tsx — wrapper
export default function DoctorProfilePage() {
const dbUuid = useAuthStore(s => s.dbUuid);
if (!dbUuid) return <div>در حال بارگذاری...</div>;
return <DoctorDetailPage overrideUuid={dbUuid} isOwnProfile={true} />;
}
```
و در `DoctorDetailPage.tsx` یک prop `isOwnProfile` اضافه کن که:
- دکمه‌های ادمین‌-only را پنهان کند
- عنوان صفحه را تغییر دهد ("پروفایل من" به جای "جزئیات پزشک")
**یا ساده‌تر:** فقط لینک sidebar را به `/admin/doctors/{dbUuid}` تنظیم کن و DoctorDetailPage را بدون تغییر reuse کن — چون دکتر از طریق `RoleRoute roles={['admin', 'doctor']}` به آن صفحه دسترسی دارد.
---
## الزامات
1. وقتی دکتر وارد پنل می‌شود، از سایدبار به "پروفایل من" دسترسی داشته باشد
2. پروفایل خودش را ببیند و ویرایش کند (نه پروفایل دکتر دیگری)
3. تنظیمات نوبت‌دهی‌اش را مدیریت کند
4. آدرس مطب‌هایش را مدیریت کند
5. دکمه‌های ادمین‌-only (حذف/غیرفعال کردن) نمایش داده نشوند
6. همه تاریخ‌ها شمسی نمایش داده شوند
+41 -9
View File
@@ -10,13 +10,14 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب
---
## قبل از شروع — تحلیل پرامپت
## قبل از شروع — تحلیل پرامپت و ساخت Todo
۱. فایل پرامپت را کامل بخوان
۲. مستندات موجود را بررسی کن: `docs/api/`
۳. کد مرتبط در `src/` و `assets/admin/` را مرور کن
۴. لیست قابلیت‌ها را از پرامپت استخراج کن
۵. به کاربر نمایش بده:
۵. **با `TodoWrite` یک todo کامل بساز** — یک آیتم به ازای هر قابلیت
۶. به کاربر نمایش بده:
```
📋 قابلیت‌های شناسایی‌شده:
@@ -31,23 +32,44 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب
## قوانین اجرا (اجباری — هیچ استثنایی ندارد)
### ۱. یک قابلیت در هر مرحله
### ۱. Todo — ستون فقرات اجرا
**در ابتدای هر اجرا** یک todo کامل با `TodoWrite` بساز:
- یک آیتم به ازای هر قابلیت با وضعیت `pending`
- آیتم‌های زیر-مجموعه اضافه کن اگر قابلیت چند بخش مستقل دارد
**در طول اجرا:**
- هر قابلیت را که شروع می‌کنی → وضعیتش را `in_progress` کن
- هر قابلیت را که تست و تأیید شد → فوری `completed` کن
- هرگز دو آیتم را همزمان `in_progress` نگذار
- اگر خطا داری که قابلیت را block کرده → یک آیتم `in_progress` باقی بماند تا رفع شود
**نمونه todo اولیه:**
```
[ ] قابلیت ۱: Stats Bar backend endpoint
[ ] قابلیت ۲: Stats Bar frontend component
[ ] قابلیت ۳: PersianCalendar popup
[ ] قابلیت ۴: AppointmentStatusDropdown
[ ] قابلیت ۵: بازطراحی AppointmentsPage
```
### ۲. یک قابلیت در هر مرحله
- هرگز دو قابلیت را همزمان پیاده‌سازی نکن
- هرگز بدون تأیید موفقیت مرحله قبل به مرحله بعد نرو
### ۲. ترتیب اجرای هر قابلیت
### ۳. ترتیب اجرای هر قابلیت
```
① تحلیل ② طراحی ③ پیاده‌سازی ④ تست ⑤ رفع خطا ⑥ مستندسازی ⑦ گزارش
① تحلیل ② طراحی ③ پیاده‌سازی ④ تست ⑤ رفع خطا ⑥ مستندسازی ⑦ Todo + گزارش
```
### ۳. سازگاری با پروژه
### ۴. سازگاری با پروژه
- همه تغییرات باید با Symfony 7 + React 19 سازگار باشند
- از الگوهای موجود پروژه پیروی کن (BaseController، TanStack Query، Zod، ...)
- اگر Entity تغییر کرد: `doctrine:migrations:diff` و `doctrine:migrations:migrate` اجرا کن
- اگر API تغییر کرد: همه بخش‌های وابسته (frontend types، api calls، ...) را اصلاح کن
### ۴. اصول کدنویسی
### ۵. اصول کدنویسی
- SOLID و Clean Code
- هیچ کامنت غیرضروری اضافه نکن
- نام‌گذاری معنادار
@@ -74,6 +96,7 @@ description: اجرای یک فایل پرامپت .md به صورت گام‌ب
### مرحله ③ — پیاده‌سازی
- قابلیت را در todo روی `in_progress` بگذار
- **Backend اول**: Entity → Migration → Repository → Service → Controller
- **Frontend بعد**: Types → API call → Component → Route
- یک فایل در هر Edit/Write — نه bulk
@@ -138,9 +161,12 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30
4. تمام status codes و error codes
5. اگر پارامتر query داشت → همه را مستند کن
### مرحله ⑦ — گزارش
### مرحله ⑦ — Todo + گزارش
بعد از اتمام هر قابلیت، گزارش کوتاه:
بعد از موفقیت تست و مستندسازی:
۱. **آیتم todo را `completed` کن** با `TodoWrite`
۲. گزارش کوتاه نمایش بده:
```
✅ قابلیت [شماره]: [نام] — تکمیل شد
@@ -150,6 +176,12 @@ ddev exec npx tsc --noEmit --project tsconfig.json 2>&1 | head -30
• assets/admin/...
• docs/api/...
📊 پیشرفت کلی:
✅ قابلیت ۱: [نام] — تکمیل
✅ قابلیت ۲: [نام] — تکمیل
⏳ قابلیت ۳: [نام] — در صف
...
─────────────────────────────────
▶ قابلیت بعدی: [شماره] — [نام]
آیا ادامه دهم؟
+33 -29
View File
@@ -6,11 +6,11 @@
## ادمین
| فیلد | مقدار |
|------|-------|
| فیلد | مقدار |
| ------ | ------------- |
| موبایل | `09120671713` |
| پسورد | `admin123` |
| نقش | `ROLE_ADMIN` |
| پسورد | `admin123` |
| نقش | `ROLE_ADMIN` |
---
@@ -18,49 +18,49 @@
### کاربر ۱ — دکتر در چند کلینیک
| فیلد | مقدار |
|------|-------|
| موبایل | `09100000011` |
| پسورد | `Test1234` |
| نقش | `ROLE_DOCTOR` |
| Contexts | مطب شخصی دکتر آرمان رضایی |
| فیلد | مقدار |
| -------- | -------------------------- |
| موبایل | `09100000011` |
| پسورد | `Test1234` |
| نقش | `ROLE_DOCTOR` |
| Contexts | مطب شخصی دکتر آرمان رضایی |
| | کلینیک جامع حضرت علی (عضو) |
| | بیمارستان ابن سینا (عضو) |
| | بیمارستان ابن سینا (عضو) |
---
### کاربر ۲ — صاحب کلینیک
| فیلد | مقدار |
|------|-------|
| موبایل | `09100000022` |
| پسورد | `Test1234` |
| نقش | `ROLE_CLINIC` |
| Contexts | کلینیک تست پگاه |
| فیلد | مقدار |
| ----------- | -------------------------------------- |
| موبایل | `09100000022` |
| پسورد | `Test1234` |
| نقش | `ROLE_CLINIC` |
| Contexts | کلینیک تست پگاه |
| UUID کلینیک | `0730373f-7c0a-4610-8120-d58ecf4a9916` |
---
### کاربر ۳ — منشی
| فیلد | مقدار |
|------|-------|
| موبایل | `09100000033` |
| پسورد | `Test1234` |
| نقش | `ROLE_SECRETARY` |
| فیلد | مقدار |
| -------- | ---------------------- |
| موبایل | `09100000033` |
| پسورد | `Test1234` |
| نقش | `ROLE_SECRETARY` |
| Contexts | مطب دکتر مهناز سلیمانی |
---
### کاربر ۴ — دکتر + صاحب کلینیک
| فیلد | مقدار |
|------|-------|
| موبایل | `09100000044` |
| پسورد | `Test1234` |
| نقش | `ROLE_DOCTOR` + `ROLE_CLINIC` |
| Contexts | مطب شخصی دکتر سامان علوی |
| | کلینیک تخصصی علوی |
| فیلد | مقدار |
| ----------- | -------------------------------------- |
| موبایل | `09100000044` |
| پسورد | `Test1234` |
| نقش | `ROLE_DOCTOR` + `ROLE_CLINIC` |
| Contexts | مطب شخصی دکتر سامان علوی |
| | کلینیک تخصصی علوی |
| UUID کلینیک | `26a1ff95-32aa-4a96-b0fd-03e75e810be9` |
---
@@ -72,3 +72,7 @@
```bash
ddev exec php create_test_users.php
```
09212908096
09212908096
+2
View File
@@ -28,6 +28,7 @@ import BlogFormPage from './pages/BlogFormPage';
import SecretariesPage from './pages/SecretariesPage';
import MyClinicPage from './pages/MyClinicPage';
import SettingsPage from './pages/SettingsPage';
import DoctorProfilePage from './pages/DoctorProfilePage';
// ── Guards ──────────────────────────────────────────────────────────────────
@@ -132,6 +133,7 @@ export default function App() {
<Route path="doctors" element={<RoleRoute roles={['admin']}><DoctorsPage /></RoleRoute>} />
<Route path="doctors/new" element={<RoleRoute roles={['admin']}><DoctorFormPage /></RoleRoute>} />
<Route path="doctors/:uuid" element={<RoleRoute roles={['admin', 'doctor']}><DoctorDetailPage /></RoleRoute>} />
<Route path="profile" element={<RoleRoute roles={['doctor']}><DoctorProfilePage /></RoleRoute>} />
</Route>
<Route path="*" element={<Navigate to="/admin/dashboard" replace />} />
@@ -14,6 +14,7 @@ import {
KeyIcon,
StarIcon,
TagIcon,
UserCircleIcon,
UserGroupIcon,
UsersIcon,
} from "@heroicons/react/24/outline";
@@ -92,6 +93,12 @@ function buildSections(primaryRole: string | null, dbUuid: string | null): Secti
{ to: '/admin/dashboard', icon: ChartBarIcon, label: 'داشبورد' },
],
},
{
label: 'پروفایل',
items: [
{ to: '/admin/profile', icon: UserCircleIcon, label: 'پروفایل من' },
],
},
{
label: 'مدیریت',
items: [
+57 -38
View File
@@ -1776,12 +1776,14 @@ type EditForm = z.infer<typeof editSchema>;
// ── Main Page ──────────────────────────────────────────────────────────────
export default function DoctorDetailPage() {
const { uuid } = useParams<{ uuid: string }>();
export default function DoctorDetailPage({ isOwnProfile = false }: { isOwnProfile?: boolean }) {
const { uuid: paramUuid } = useParams<{ uuid: string }>();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const qc = useQueryClient();
const primaryRole = useAuthStore(s => s.primaryRole);
const dbUuid = useAuthStore(s => s.dbUuid);
const uuid = isOwnProfile ? (dbUuid ?? undefined) : paramUuid;
const [editOpen, setEditOpen] = useState(searchParams.get('edit') === '1');
const [deleteOpen, setDeleteOpen] = useState(false);
@@ -1967,12 +1969,25 @@ export default function DoctorDetailPage() {
{/* Breadcrumb */}
<div className="flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400">
<button onClick={() => navigate('/admin/doctors')}
className="flex items-center gap-1.5 hover:text-slate-800 dark:hover:text-slate-100 transition-colors">
<ArrowRightIcon className="w-4 h-4" />پزشکان
</button>
<span>/</span>
<span className="text-slate-700 dark:text-slate-300 font-medium">پروفایل پزشک</span>
{isOwnProfile ? (
<>
<button onClick={() => navigate('/admin/dashboard')}
className="flex items-center gap-1.5 hover:text-slate-800 dark:hover:text-slate-100 transition-colors">
<ArrowRightIcon className="w-4 h-4" />داشبورد
</button>
<span>/</span>
<span className="text-slate-700 dark:text-slate-300 font-medium">پروفایل من</span>
</>
) : (
<>
<button onClick={() => navigate('/admin/doctors')}
className="flex items-center gap-1.5 hover:text-slate-800 dark:hover:text-slate-100 transition-colors">
<ArrowRightIcon className="w-4 h-4" />پزشکان
</button>
<span>/</span>
<span className="text-slate-700 dark:text-slate-300 font-medium">پروفایل پزشک</span>
</>
)}
</div>
{/* Profile Card */}
@@ -2026,39 +2041,43 @@ export default function DoctorDetailPage() {
<PencilIcon className="w-4 h-4" />ویرایش
</button>
{/* Toggle active button — styled by current state */}
<button
onClick={() => setToggleConfirm(true)}
disabled={toggleMut.isPending}
className={`inline-flex items-center gap-1.5 text-sm font-medium px-3 h-10 rounded-xl border transition-colors disabled:opacity-50 ${
doctor.active
? 'border-orange-300 dark:border-orange-500/40 text-orange-600 dark:text-orange-400 bg-orange-50 dark:bg-orange-500/10 hover:bg-orange-100 dark:hover:bg-orange-500/20'
: 'border-emerald-300 dark:border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 hover:bg-emerald-100 dark:hover:bg-emerald-500/20'
}`}
>
{toggleMut.isPending
? <span className="w-3.5 h-3.5 border-2 border-current/30 border-t-current rounded-full animate-spin" />
: doctor.active
? <XCircleIcon className="w-4 h-4" />
: <CheckCircleIcon className="w-4 h-4" />
}
{doctor.active ? 'غیرفعال کردن' : 'فعال کردن'}
</button>
{/* Toggle active / Delete — فقط ادمین */}
{!isOwnProfile && (
<>
<button
onClick={() => setToggleConfirm(true)}
disabled={toggleMut.isPending}
className={`inline-flex items-center gap-1.5 text-sm font-medium px-3 h-10 rounded-xl border transition-colors disabled:opacity-50 ${
doctor.active
? 'border-orange-300 dark:border-orange-500/40 text-orange-600 dark:text-orange-400 bg-orange-50 dark:bg-orange-500/10 hover:bg-orange-100 dark:hover:bg-orange-500/20'
: 'border-emerald-300 dark:border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10 hover:bg-emerald-100 dark:hover:bg-emerald-500/20'
}`}
>
{toggleMut.isPending
? <span className="w-3.5 h-3.5 border-2 border-current/30 border-t-current rounded-full animate-spin" />
: doctor.active
? <XCircleIcon className="w-4 h-4" />
: <CheckCircleIcon className="w-4 h-4" />
}
{doctor.active ? 'غیرفعال کردن' : 'فعال کردن'}
</button>
<div className="relative" data-dmenu>
<button data-dmenu onClick={() => setMenuOpen(!menuOpen)}
className="cp-btn-secondary h-10 w-10 flex items-center justify-center px-0">
<EllipsisVerticalIcon className="w-4 h-4" />
</button>
{menuOpen && (
<div className="absolute left-0 top-12 z-30 w-52 cp-card shadow-2xl border border-slate-200 dark:border-gray-700 py-1.5 animate-scale-in" data-dmenu>
<button onClick={() => { setDeleteOpen(true); setMenuOpen(false); }}
className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-500/10">
<TrashIcon className="w-4 h-4 shrink-0" />حذف این پزشک
<div className="relative" data-dmenu>
<button data-dmenu onClick={() => setMenuOpen(!menuOpen)}
className="cp-btn-secondary h-10 w-10 flex items-center justify-center px-0">
<EllipsisVerticalIcon className="w-4 h-4" />
</button>
{menuOpen && (
<div className="absolute left-0 top-12 z-30 w-52 cp-card shadow-2xl border border-slate-200 dark:border-gray-700 py-1.5 animate-scale-in" data-dmenu>
<button onClick={() => { setDeleteOpen(true); setMenuOpen(false); }}
className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-500/10">
<TrashIcon className="w-4 h-4 shrink-0" />حذف این پزشک
</button>
</div>
)}
</div>
)}
</div>
</>
)}
</div>
</div>
</div>
+5
View File
@@ -0,0 +1,5 @@
import DoctorDetailPage from './DoctorDetailPage';
export default function DoctorProfilePage() {
return <DoctorDetailPage isOwnProfile />;
}