Files
nobat724_front/.claude/prompt/login-redirect-back.md
T

6.3 KiB
Raw Blame History

بازگشت به صفحهٔ مبدأ بعد از لاگین (redirect-back)

پروژه

nobat724_front (سایت عمومی)

زمینه

مکانیزم بازگشت بعد از لاگین از قبل وجود دارد: مرحلهٔ تأیید کد (SendReq.js) بعد از ورود موفق، پارامتر ?redirect= را از URL می‌خواند و کاربر را به همان مسیر برمی‌گرداند (فقط مسیر داخلی امن). اما لینک‌ها/ناوبری‌های لاگین در سایت این پارامتر را نمی‌سازند — به‌جز یک مورد (components/doctor/claim/index.js). نتیجه: کاربر از هر صفحه‌ای (مثلاً صفحهٔ پزشک برای گرفتن نوبت) روی «ورود | ثبت نام» بزند، بعد از لاگین به / (خانه) می‌رود، نه صفحهٔ مبدأ.

مشکل / هدف

هر جای سایت که به /login می‌رویم، باید مسیر فعلی را به‌صورت ?redirect=<current-path> به لینک لاگین اضافه کنیم تا بعد از ورود موفق کاربر به همان صفحه برگردد. الگوی درست از قبل در پروژه هست و فقط باید به بقیهٔ نقاط تعمیم داده شود.

فایل‌های مرتبط

فایل نقش
components/register/verificationPage/SendReq.js (بدون تغییر) منطق بازگشت با ?redirect= — L8995
components/doctor/claim/index.js (مرجع الگوی درست) L191 — /login?redirect=${encodeURIComponent(pathname)}
components/layout/header/Content.js لینک اصلی «ورود | ثبت نام» هدر — L43
app/payment/[uuid]/page.js router.push("/login") هنگام نبود auth — L35
app/dashboard/page.js redirect("/login") سمت سرور برای صفحهٔ محافظت‌شده — L29
app/component/ModalLogout.js router.replace("/login") بعد از خروج — L19 (به «نکات» رجوع کن)

وضعیت فعلی

منطق بازگشت که باید حفظ شود (SendReq.js L8995):

// بازگشت به صفحهٔ مبدأ اگر ?redirect= داده شده (فقط مسیر داخلی امن)
const redirect = new URLSearchParams(window.location.search).get("redirect");
window.location.href =
  redirect && redirect.startsWith("/") && !redirect.startsWith("//")
    ? redirect
    : "/";

الگوی درستِ موجود (components/doctor/claim/index.js L191):

<Link href={`/login?redirect=${encodeURIComponent(pathname)}`} className="w-full">

لینک هدر که پارامتر ندارد (components/layout/header/Content.js L40–47) — این کامپوننت "use client" است و همین حالا const pathname = usePathname(); را دارد (L17):

{isLogged ? (
  <ProfileUser />
) : (
  <Link href="/login">
    <Button variant="outlined" color="primary">
      ورود | ثبت نام
    </Button>
  </Link>
)}

وظایف

۱. لینک لاگین هدر (اصلی‌ترین)

در components/layout/header/Content.js L43، pathname که همین‌جا موجود است را به لینک اضافه کن. از رفتن به /login?redirect=/login جلوگیری کن:

<Link
  href={
    pathname && pathname !== "/login"
      ? `/login?redirect=${encodeURIComponent(pathname)}`
      : "/login"
  }
>
  <Button variant="outlined" color="primary">
    ورود | ثبت نام
  </Button>
</Link>

۲. ناوبری لاگین صفحهٔ پرداخت

در app/payment/[uuid]/page.js L35 (router.push("/login"))، مسیر فعلی را ضمیمه کن. این کامپوننت client است؛ اگر usePathname وارد نشده، آن را از next/navigation وارد کن و استفاده کن:

import { usePathname } from "next/navigation";
// ...
const pathname = usePathname();
// ...
router.push(`/login?redirect=${encodeURIComponent(pathname)}`);

۳. redirect سمت سرور داشبورد

در app/dashboard/page.js L29، صفحهٔ محافظت‌شده هنگام نبود auth به لاگین می‌رود؛ مقصد بازگشت را ثابت /dashboard بگذار:

return redirect("/login?redirect=/dashboard");

(چون این redirect سمت سرور است و به مسیر ثابت داشبورد مربوط است، نیازی به usePathname نیست.)

نکات مهم

  • پارامتر در طول جریان لاگین حفظ می‌شود: صفحهٔ /loginContentLoginRegisterPage مرحلهٔ ارسال کد و تأیید را با state داخلی (isSendMsg) عوض می‌کند و ناوبری جدید انجام نمی‌دهد، پس URL روی /login?redirect=... می‌ماند و SendReq.js با window.location.search آن را می‌خواند. نیازی به پاس‌دادن prop اضافه نیست.
  • امنیت redirect از قبل هندل شده: فقط مسیرِ داخلی که با / شروع شود و با // شروع نشود پذیرفته می‌شود (SendReq.js L92). مقدار را همیشه با encodeURIComponent(pathname) بساز.
  • app/login/page.js: کاربرِ از قبل لاگین‌شده به / هدایت می‌شود (ability.can("access","Login")). این رفتار درست است و نباید تغییر کند؛ فقط برای کاربرِ مهمان ?redirect= معنا دارد.
  • ModalLogout.js (L19) را تغییر نده: بعد از خروج بردن کاربر به /login با ?redirect= به صفحهٔ محافظت‌شده باعث حلقه/بازگشت ناخواسته می‌شود. لاگ‌اوت باید به /login سادهٔ فعلی برود.
  • صفحهٔ appointment inline login دارد: جریان گرفتن نوبت با setStep(3) بعد از لاگین در همان صفحه می‌ماند (SendReq.js L86–87) و ناوبری نمی‌کند؛ نیازی به ?redirect= ندارد و نباید دست بخورد.
  • usePathname فقط در Client Component کار می‌کند؛ برای redirectهای سمت سرور (وظیفهٔ ۳) از مسیر ثابت استفاده کن.
  • بعد از تغییر: npm run build بدون خطا.