Files
clinicpro/.claude/prompt/fix-switch-context-role.md
T

169 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# رفع باگ تغییر محیط کاری — primaryRole آپدیت نمی‌شود
## زمینه
دکتری که عضو چند کلینیک است، در صفحه «انتخاب محیط کاری» می‌تواند بین مطب شخصی و کلینیک‌های مختلف سوئیچ کند. اما بعد از سوئیچ، `primaryRole` در authStore تغییر نمی‌کند — هنوز `'doctor'` می‌ماند. نتیجه: وقتی به `/admin/profile` می‌رود، کد `uuid = dbUuid` (که حالا uuid کلینیک است) را به `GET /api/v1/doctor/{clinicUuid}` می‌فرستد → 404.
## مشکل / هدف
وقتی `switchContext` صدا زده می‌شود:
- `dbUuid` در store تغییر می‌کند (به uuid کلینیک)
- اما `primaryRole` تغییر **نمی‌کند** (هنوز `'doctor'` می‌ماند)
- `context.role` در store ذخیره می‌شود اما از آن برای آپدیت `primaryRole` استفاده نمی‌شود
## فایل‌های مرتبط
| فایل | نقش |
|------|-----|
| `src/Auth/Controller/AuthController.php` | `switchContext` endpoint — خط 571 |
| `assets/admin/stores/authStore.ts` | `switchContext` action — خط 105 |
| `assets/admin/pages/DoctorDetailPage.tsx` | `uuid = isOwnProfile ? dbUuid : paramUuid` — خط 2162 |
| `assets/admin/pages/SelectContextPage.tsx` | `handleSelect` — خط 23 |
## وضعیت فعلی
### Backend — `switchContext` response (خط 595-599)
```php
return $this->success([
'db_uuid' => $dbUuid,
'db_key' => $this->buildDbKey($dbUuid),
'context' => $matched,
]);
```
`$matched` از `buildAvailableContexts()` می‌آید و دارای فیلد `role` است:
```php
// برای context کلینیک‌هایی که دکتر در آن‌ها عضو است:
$contexts[] = [
'type' => 'clinic',
'db_uuid' => $clinic->getUuid(),
'name' => $clinic->getName() ?? '',
'role' => 'doctor', // ← نه 'clinic'، چون دکتر است نه صاحب کلینیک
];
// برای context مطب شخصی:
$contexts[] = [
'type' => 'doctor',
'db_uuid' => $doctor->getUuid(),
'name' => 'مطب شخصی ...',
'role' => 'doctor',
];
```
پس `context.role` موجود است اما backend آن را به عنوان `primary_role` جداگانه برنمی‌گرداند.
### Frontend — `switchContext` در authStore (خط 105-117)
```ts
switchContext: async (dbUuid: string) => {
const res = await apiFetch('/api/v1/auth/switch-context', {
method: 'POST',
body: JSON.stringify({ db_uuid: dbUuid }),
});
if (res.success) {
set({
dbUuid: res.data.db_uuid,
dbKey: res.data.db_key,
context: res.data.context,
// ← primaryRole آپدیت نمی‌شود!
});
}
},
```
### Frontend — DoctorDetailPage (خط 2162)
```tsx
const uuid = isOwnProfile ? (dbUuid ?? undefined) : paramUuid;
// وقتی context کلینیک است، dbUuid = uuid کلینیک است
// اما primaryRole هنوز 'doctor' است
// پس GET /api/v1/doctor/{clinicUuid} → 404
```
## وظایف
### ۱. Frontend — آپدیت `primaryRole` در `switchContext`
در `assets/admin/stores/authStore.ts`، خط 110-115، `primaryRole` را از `res.data.context.role` بخوان و set کن:
```ts
switchContext: async (dbUuid: string) => {
const res = await apiFetch('/api/v1/auth/switch-context', {
method: 'POST',
body: JSON.stringify({ db_uuid: dbUuid }),
});
if (res.success) {
set({
dbUuid: res.data.db_uuid,
dbKey: res.data.db_key,
context: res.data.context,
primaryRole: res.data.context?.role ?? null, // ← اضافه شود
});
}
},
```
### ۲. Backend — بررسی `role` در context کلینیک‌های عضو دکتر
در `buildAvailableContexts()` (خط 626-633)، وقتی دکتر به context یک کلینیک سوئیچ می‌کند، role باید `'clinic'` باشد نه `'doctor'` — چون در آن محیط باید به عنوان نماینده کلینیک عمل کند:
```php
foreach ($this->clinicRepo->findByDoctor($doctor) as $clinic) {
$contexts[] = [
'type' => 'clinic',
'db_uuid' => $clinic->getUuid(),
'name' => $clinic->getName() ?? '',
'role' => 'clinic', // ← از 'doctor' به 'clinic' تغییر دهید
];
}
```
**نکته مهم:** این تغییر باعث می‌شود وقتی دکتر در context کلینیک است، `primaryRole === 'clinic'` شود. در `DoctorDetailPage` این رفتار درست است — read-only view کلینیک فعال می‌شود و از `GET /api/v1/clinic/my-doctor/{uuid}` استفاده می‌کند.
### ۳. رفع مشکل `/admin/profile` برای context کلینیک
در `DoctorDetailPage.tsx` خط 2162:
```tsx
const uuid = isOwnProfile ? (dbUuid ?? undefined) : paramUuid;
```
وقتی `isOwnProfile = true` و `primaryRole === 'clinic'`، صفحه profile پزشک منطقی نیست — دکتر در حال مشاهده به عنوان نماینده کلینیک است. دو گزینه:
**گزینه A (توصیه‌شده):** در `DoctorProfilePage.tsx` و route `/admin/profile`، وقتی `primaryRole === 'clinic'`، به dashboard هدایت کن:
```tsx
// assets/admin/pages/DoctorProfilePage.tsx
export default function DoctorProfilePage() {
const primaryRole = useAuthStore(s => s.primaryRole);
const navigate = useNavigate();
useEffect(() => {
if (primaryRole === 'clinic') navigate('/admin/dashboard', { replace: true });
}, [primaryRole, navigate]);
return <DoctorDetailPage isOwnProfile />;
}
```
**گزینه B:** در `App.tsx` route `profile` را فقط به role `doctor` محدود کن:
```tsx
// App.tsx — خط 142
<Route path="profile" element={<RoleRoute roles={['doctor']}><DoctorProfilePage /></RoleRoute>} />
// این از قبل هست — مشکل این است که primaryRole درست آپدیت نمی‌شود
```
گزینه B کافی است اگر وظیفه ۱ و ۲ درست اجرا شوند — بعد از switch، `primaryRole === 'clinic'` می‌شود و `RoleRoute` کاربر را به dashboard redirect می‌کند.
## نکات مهم
- **migration لازم نیست** — هیچ entity تغییر نمی‌کند
- **`context.role` از قبل در response موجود است** — backend فقط نیاز به بررسی مقدار دارد، endpoint تغییر نمی‌کند
- بعد از اصلاح، context کلینیک‌های عضو دکتر `role: 'clinic'` خواهند داشت — این با guard های `primaryRole === 'clinic'` در DoctorDetailPage سازگار است
- `cache:clear` بعد از تغییر backend لازم است
- `yarn dev` بعد از تغییر frontend لازم است
- مستندات: `docs/api/auth.md` — توضیح رفتار `context.role` در `switch-context` response به‌روزرسانی شود