- 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>
117 lines
7.1 KiB
Markdown
117 lines
7.1 KiB
Markdown
# اجباریکردن فیلدهای اطلاعات حساب کاربری در صفحه نوبتگیری
|
|
|
|
## پروژه
|
|
|
|
`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` — بدون اعتبارسنجی اجباری:
|
|
```js
|
|
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`):
|
|
```js
|
|
// data.<field> = { value: <...>, isEdit: <bool> }
|
|
// gender.value: رشته "male"/"female" (یا "" )
|
|
// basic_insurance.value: آبجکت { id } یا "" (در Form با findBasicInsuranceVal مپ میشود)
|
|
// national_code/name/family.value: رشته
|
|
```
|
|
|
|
`Form.js` از قبل `error` را به هر فیلد پاس میدهد:
|
|
```jsx
|
|
<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` (توقف).
|
|
|
|
```js
|
|
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` بدون خطا؛ دستی تست کن — با فیلدهای خالی دکمهی ادامه نباید جلو برود و باید زیر هر فیلد خطا نشان دهد؛ با تکمیل همه، باید به مرحلهی پرداخت برود.
|