Files
nobat724_front/.claude/prompt/fix-dashboard-uuid-and-lists.md
hamedandClaude Opus 4.8 96b1684b82 fix(dashboard): guard null userInfo in Head to stop 500 crash
getParsedUserInfo() can return null (cookie missing/unparseable), so
reading userInfo.realName crashed the dashboard with a 500. Default to
an empty object and fall back to the user prop's name or 'کاربر'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:15:25 +03:30

8.3 KiB
Raw Permalink Blame History

رفع باگ‌های داشبورد کاربر: کوکی uuid اشتباه، URL غلط نوبت‌ها/پرداخت‌ها، و crash هدر

پروژه

nobat724_front — سایت عمومی. بعد از پرامپت backend اجرا شود.

Cross-repo: تب پرداخت‌ها به endpoint جدید backend وابسته است: GET /api/v1/my/payments (در clinicpro/.claude/prompt/my-payments-list-endpoint.md).

زمینه

داشبورد کاربر چند خطای ۴۰۴ و یک crash می‌دهد:

  1. پروفایل ۴۰۴ (server-side): app/dashboard/page.js پروفایل را با cookieStore.get("uuid") می‌گیرد، اما کوکی uuid هنگام لاگین با uuid اوتی‌پی (send-code) ست شده، نه uuid کاربر. پس GET /user-profile/{otp-uuid} ۴۰۴ می‌دهد (نه با پروفایل match می‌شود نه با کاربر).
  2. crash هدر: components/dashboard/userAccount/Head.js مقدار userInfo.realName را روی نتیجه‌ی getParsedUserInfo() می‌خواند که ممکن است null باشد → «Cannot read properties of null (reading 'realName')».
  3. نوبت‌های من ۴۰۴: getMyAppointments(userId) به appointment/my-appointments/{userId} می‌زند که route ناموجود است. route درست: GET /api/v1/my/appointments (کاربر از توکن).
  4. تراکنش‌ها ۴۰۴: getMyPayments(userId) به payment/my-payments/{userId} می‌زند که وجود ندارد → با endpoint جدید GET /api/v1/my/payments جایگزین می‌شود.

ریشه‌ی اصلی کوکی uuid

در components/register/verificationPage/SendReq.js، مقدار uuid که ست می‌شود uuid اوتی‌پی (از send-code) است، نه uuid کاربر. uuid واقعی کاربر در کوکی userInfo (res.data.uuid از userinfo) موجود است.

// SendReq.js — handleSetCookie
Cookies.set("uuid", uuid, { ... });   // ❌ uuid اوتی‌پی، نه uuid کاربر

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

فایل نقش
components/register/verificationPage/SendReq.js ست‌کردن کوکی uuid هنگام لاگین — باید uuid کاربر شود
app/dashboard/page.js fetch پروفایل server-side با کوکی uuid
components/dashboard/userAccount/Head.js userInfo.realName بدون گارد null
services/response.js getMyAppointments, getMyPayments — URLهای غلط
components/dashboard/userAccount/sidebars/turns/index.js مصرف getMyAppointments
components/dashboard/userAccount/sidebars/transactions/index.js مصرف getMyPayments

وضعیت فعلی (کد واقعی)

services/response.js — URLهای ناموجود

getMyAppointments: (userId, params) => api.get(`api/v1/appointment/my-appointments/${userId}`, { params, requireAuth: true }),
getMyPayments: (userId, params) => api.get(`api/v1/payment/my-payments/${userId}`, { params, requireAuth: true }),

app/dashboard/page.js

const uuid = cookieStore.get("uuid")?.value;   // ❌ uuid اوتی‌پی
profile = await fetchReq(`${API_URL}/api/v1/user-profile/${uuid}`, { headers: { Authorization: `Bearer ${token.value}` } });

Head.js

const userInfo = getParsedUserInfo();
// ...
{userInfo.realName}   // ❌ اگر null → crash

وظایف

۱. کوکی uuid = uuid کاربر (SendReq.js)

  • در handleSetCookie، به‌جای ست‌کردن uuid اوتی‌پی، uuid واقعی کاربر را ست کن. چون getInfo بعداً پروفایل/userinfo را می‌گیرد، بهترین جا برای ست‌کردن uuid کاربر داخل getInfo است بعد از دریافت res.data.uuid:
const getInfo = (token, cookieOptions) => {
  request.getUserInfo({ headers: { Authorization: `Bearer ${token}` } })
    .then((res) => {
      const profile = res?.data;
      if (profile?.uuid) {
        Cookies.set("uuid", profile.uuid, cookieOptions);   // ✅ uuid کاربر (overwrite uuid اوتی‌پی)
        Cookies.set("userInfo", JSON.stringify({ ...profile, username: profile.mobile_number }), cookieOptions);
        // ... redirect / setStep ...
      }
    });
};

کوکی uuid در handleSetCookie با uuid اوتی‌پی ست می‌شود؛ این خط را یا حذف کن یا بگذار و در getInfo با uuid کاربر overwrite کن (overwrite ساده‌تر است). نتیجه: کوکی نهایی uuid = uuid کاربر.

۲. گارد null در Head.js

const userInfo = getParsedUserInfo() || {};
// ...
{userInfo?.realName || "کاربر"}
  • اگر user (prop از buildPatientUser) هم اطلاعات دارد، می‌توانی به‌جای کوکی از user.name استفاده کنی؛ ولی حداقل گارد null اجباری است تا crash نشود.

۳. اصلاح URLها در services/response.js

getMyAppointments: (params) => api.get(`api/v1/my/appointments`, { params, requireAuth: true }),
getMyPayments: (params) => api.get(`api/v1/my/payments`, { params, requireAuth: true }),
  • امضای تابع userId را حذف کن (کاربر از توکن می‌آید). همه‌ی callerها را به‌روز کن.

۴. به‌روزرسانی callerها (turns + transactions)

  • در sidebars/turns/index.js و sidebars/transactions/index.js: userId را حذف کن، فقط params بفرست:
const response = await request.getMyAppointments(params);   // turns
const response = await request.getMyPayments(params);       // transactions
  • شکل پاسخ paginated است (paginated() در backend): items از response?.data و total از response?.meta?.totalRecords/totalPages. کد فعلی response.page.totalPages می‌خواند — با شکل واقعی (meta) هم‌خوان کن:
if (Array.isArray(response?.data)) {
  setAppointments(response.data);                 // یا setPayments
  setTotalPages(response?.meta?.totalPages || 1);
}

قرارداد دقیق پاسخ را از پرامپت/داک backend بگیر (docs/api/payment.md و docs/api/appointment.md بخش my/*). اگر my/appointments برای نقش کاربرِ ساده خالی برمی‌گرداند، با backend چک کن کدام endpoint نوبت‌های خود بیمار را می‌دهد (شاید GET /api/v1/appointments/user). اگر مبهم بود متوقف شو و بپرس.

۵. (در صورت لزوم) app/dashboard/page.js

  • حالا که کوکی uuid = uuid کاربر است، fetchReq(/user-profile/{uuid}) با endpoint اصلاح‌شده‌ی backend (resolve با user-uuid + lazy-create) ۲۰۰ می‌دهد. تأیید کن buildPatientUser(profile) با شکل پاسخ ({success, data:{data:{...}}}profile.data.data) هم‌خوان است؛ اگر buildPatientUser از profile?.data می‌خواند ولی پاسخ دوبار تودرتو است، عمق استخراج را اصلاح کن.

نکات مهم

  • وابستگی cross-repo: تب تراکنش‌ها به GET /api/v1/my/payments جدید نیاز دارد؛ اگر نبود اول backend را اجرا کن.
  • امنیت/درستی: endpointهای my/* کاربر را از توکن می‌گیرند؛ دیگر userId در URL نفرست.
  • شکل پاسخ: paginated()data آرایه، meta.totalRecords/meta.totalPages. این با success(['data'=>...]) (دوبار تودرتو) فرق دارد — هرکدام را درست مصرف کن.
  • کوکی uuid: بعد از این تغییر، همه‌ی مصرف‌کننده‌های کوکی uuid (dashboard/page.js, SubmitData.js, lib/auth.js) uuid کاربر می‌گیرند — درست.
  • RTL/Jalali/multi-domain حفظ شوند؛ توهم‌سازی داده نکن (لیست خالی = پیام «موردی نیست»).
  • تست: npm run build؛ سپس دستی با کاربر 09210651788: داشبورد بدون ۴۰۴/crash لود شود؛ هدر نام کاربر یا «کاربر» را نشان دهد؛ تب نوبت‌ها و تراکنش‌ها بدون خطا (لیست خالی یا واقعی). سپس commit.