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>
8.3 KiB
رفع باگهای داشبورد کاربر: کوکی uuid اشتباه، URL غلط نوبتها/پرداختها، و crash هدر
پروژه
nobat724_front — سایت عمومی. بعد از پرامپت backend اجرا شود.
Cross-repo: تب پرداختها به endpoint جدید backend وابسته است:
GET /api/v1/my/payments(درclinicpro/.claude/prompt/my-payments-list-endpoint.md).
زمینه
داشبورد کاربر چند خطای ۴۰۴ و یک crash میدهد:
- پروفایل ۴۰۴ (server-side):
app/dashboard/page.jsپروفایل را باcookieStore.get("uuid")میگیرد، اما کوکیuuidهنگام لاگین با uuid اوتیپی (send-code) ست شده، نه uuid کاربر. پسGET /user-profile/{otp-uuid}۴۰۴ میدهد (نه با پروفایل match میشود نه با کاربر). - crash هدر:
components/dashboard/userAccount/Head.jsمقدارuserInfo.realNameرا روی نتیجهیgetParsedUserInfo()میخواند که ممکن استnullباشد → «Cannot read properties of null (reading 'realName')». - نوبتهای من ۴۰۴:
getMyAppointments(userId)بهappointment/my-appointments/{userId}میزند که route ناموجود است. route درست:GET /api/v1/my/appointments(کاربر از توکن). - تراکنشها ۴۰۴:
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.