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

6.9 KiB
Raw Permalink Blame History

رفع باگ تغییر محیط کاری — 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)

return $this->success([
    'db_uuid' => $dbUuid,
    'db_key'  => $this->buildDbKey($dbUuid),
    'context' => $matched,
]);

$matched از buildAvailableContexts() می‌آید و دارای فیلد role است:

// برای 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)

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)

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 کن:

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' — چون در آن محیط باید به عنوان نماینده کلینیک عمل کند:

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:

const uuid = isOwnProfile ? (dbUuid ?? undefined) : paramUuid;

وقتی isOwnProfile = true و primaryRole === 'clinic'، صفحه profile پزشک منطقی نیست — دکتر در حال مشاهده به عنوان نماینده کلینیک است. دو گزینه:

گزینه A (توصیه‌شده): در DoctorProfilePage.tsx و route /admin/profile، وقتی primaryRole === 'clinic'، به dashboard هدایت کن:

// 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 محدود کن:

// 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 به‌روزرسانی شود