Files
nobat724_front/.claude/prompt/appointment-required-account-fields.md
hamedandClaude Opus 4.8 7949da9ba9 fix(appointment): real status filter + required account fields
- My-appointments tabs sent invalid status values (reserved/waiting_for_payment/
  ...) that don't exist in the backend, so every tab but "all" returned empty.
  Map tabs to real statuses (pending/confirmed/completed/cancelled_by_user/
  expired) so booked appointments show up.
- Booking form now validates required account fields before proceeding to
  payment (national_code 10 digits, name, family, gender, basic_insurance),
  in both self and other-person modes, surfacing per-field errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 10:45:41 +03:30

7.1 KiB

اجباری‌کردن فیلدهای اطلاعات حساب کاربری در صفحه نوبت‌گیری

پروژه

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

کاملاً frontend است. هیچ تغییری در بک‌اند لازم نیست — فقط اعتبارسنجی سمت کلاینت قبل از ادامه به مرحله‌ی پرداخت.

زمینه

در صفحه‌ی نوبت‌گیری (/appointment/[doctorId])، بخش «اطلاعات حساب کاربری» (و در حالت «شخص دیگر»، «اطلاعات کاربر جدید») قبل از رفتن به مرحله‌ی پرداخت هیچ اعتبارسنجی اجباری ندارد؛ SubmitData.handleSubmit فقط setErrors({}) می‌کند و مستقیم به API می‌فرستد، و خطاها فقط از پاسخ سرور برمی‌گردند. در نتیجه کاربر می‌تواند بدون نام/کد ملی/جنسیت/بیمه نوبت بگیرد و رکورد ناقص ثبت شود (همان مشکلی که باعث شد نام کاربر خالی بماند).

مشکل / هدف

این پنج فیلد در هر دو حالت (نوبت برای خود کاربر و برای شخص دیگر) اجباری شوند و تا تکمیل نشدن، فرم به مرحله‌ی بعد نرود و خطای فیلدی نمایش دهد:

  • کد ملی (national_code) — ۱۰ رقم
  • نام (name)
  • نام خانوادگی (family)
  • جنسیت (gender)
  • نوع بیمه (basic_insurance)

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

فایل نقش
components/appointment/detail/SubmitData.js handleSubmit — جای افزودن اعتبارسنجی اجباری قبل از API
components/appointment/detail/Form.js فیلدها از قبل error={errors?.<field>} می‌گیرند (نیازی به تغییر ساختار نیست)
components/appointment/detail/index.js errors state و emptyPatientData() (شکل فیلدها)

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

SubmitData.handleSubmit — بدون اعتبارسنجی اجباری:

const handleSubmit = async () => {
  const isChanged = JSON.stringify(prevData) !== JSON.stringify(data);
  setErrors({});
  setLoading(true);
  try {
    if (!isForAnother && isChanged) { /* PATCH/POST profile */ }
    if (doctor && selectedSlot) { /* postAppointment */ }
    ...
  } catch (error) {
    if (error?.response?.status === 409) { setStep(0); ... }
    setErrors(error.response.data);  // فقط خطای سرور
  }
};

شکل داده‌ی هر فیلد (از detail/index.js):

// data.<field> = { value: <...>, isEdit: <bool> }
// gender.value: رشته "male"/"female"   (یا "" )
// basic_insurance.value: آبجکت { id } یا ""  (در Form با findBasicInsuranceVal مپ می‌شود)
// national_code/name/family.value: رشته

Form.js از قبل error را به هر فیلد پاس می‌دهد:

<EditField ... name="national_code" error={errors?.national_code} />
<EditField ... name="name" error={errors?.name} />
<EditField ... name="family" error={errors?.family} />
<DefaultSelect ... name="gender" error={errors?.gender} />
<DefaultSelect ... name="basic_insurance" error={errors?.basic_insurance} />

یعنی فقط کافی است SubmitData یک آبجکت errors با کلیدهای همین فیلدها بسازد و setErrors کند؛ نمایش خطا خودکار کار می‌کند.

وظایف

۱. تابع اعتبارسنجی اجباری در SubmitData

یک validate(data) بساز که آبجکت خطا (کلید فیلد → پیام فارسی) برگرداند. در ابتدای handleSubmit، قبل از setLoading(true) و قبل از هر فراخوانی API، اجرا شود؛ اگر خطا داشت setErrors(...) و return (توقف).

const validate = () => {
  const errs = {};
  const nationalCode = (data?.national_code?.value || "").trim();
  if (!data?.name?.value?.trim())   errs.name = "نام الزامی است";
  if (!data?.family?.value?.trim()) errs.family = "نام خانوادگی الزامی است";
  if (!nationalCode)                errs.national_code = "کد ملی الزامی است";
  else if (!/^\d{10}$/.test(nationalCode)) errs.national_code = "کد ملی باید ۱۰ رقم باشد";
  // gender.value رشته است
  if (!data?.gender?.value)         errs.gender = "جنسیت الزامی است";
  // basic_insurance.value آبجکت {id} یا "" است
  if (!data?.basic_insurance?.value?.id) errs.basic_insurance = "نوع بیمه الزامی است";
  return errs;
};

const handleSubmit = async () => {
  const errs = validate();
  if (Object.keys(errs).length > 0) {
    setErrors(errs);
    return;
  }
  setErrors({});
  setLoading(true);
  // ... بقیه بدون تغییر
};
  • این اعتبارسنجی در هر دو حالت اجرا شود (هم isForAnother=false هم true) — یعنی خارج از شرط if (!isForAnother && isChanged) و قبل از آن.
  • DefaultSelect (جنسیت/بیمه) باید پیام خطا را نمایش دهد؛ تأیید کن error prop در DefaultSelect به helperText/حالت خطای MUI وصل است (اگر نیست، اضافه کن — ولی EditField این را دارد).

۲. هماهنگی شکل داده

  • gender.value رشته‌ی "male"/"female" است (از buildProfileData/DefaultSelect)، پس بررسی !data.gender.value درست است.
  • basic_insurance.value یا آبجکت { id } است (از پروفایل) یا کل آیتم بیمه (از انتخاب کاربر در DefaultSelect) — هر دو id دارند، پس ?.value?.id درست کار می‌کند.
  • کد ملی ممکن است از پروفایلِ تأییدشده isEdit:false (قفل) ولی پر باشد — این حالت معتبر است (مقدار دارد، خطا نمی‌دهد).

نکات مهم

  • بک‌اند تغییر نمی‌کند؛ این صرفاً gate سمت کلاینت است. خطاهای سرور (setErrors(error.response.data)) در catch دست‌نخورده بماند.
  • اعتبارسنجی باید قبل از ساخت/ارسال نوبت و پروفایل اجرا شود تا رکورد ناقص ثبت نشود.
  • پیام‌ها فارسی، فیلدها همان کلیدهایی که Form.js انتظار دارد (name, family, national_code, gender, basic_insurance).
  • در حالت «شخص دیگر»، فیلد phone هم در فرم هست؛ اگر می‌خواهی آن را هم اجباری کنی به validate اضافه کن — ولی طبق درخواست فقط این پنج فیلد لازم‌اند.
  • App Router، RTL، MUI v5؛ از EditField/DefaultSelect موجود استفاده کن، کامپوننت جدید نساز.
  • بعد از تغییر: npm run build بدون خطا؛ دستی تست کن — با فیلدهای خالی دکمه‌ی ادامه نباید جلو برود و باید زیر هر فیلد خطا نشان دهد؛ با تکمیل همه، باید به مرحله‌ی پرداخت برود.