- 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>
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(جنسیت/بیمه) باید پیام خطا را نمایش دهد؛ تأیید کنerrorprop در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بدون خطا؛ دستی تست کن — با فیلدهای خالی دکمهی ادامه نباید جلو برود و باید زیر هر فیلد خطا نشان دهد؛ با تکمیل همه، باید به مرحلهی پرداخت برود.