fix(dashboard): map insurance and medical history correctly in account tab
The account tab read basic_insurance.id (object) but the profile returns basic_insurance_id (number), yielding [NaN], and never loaded the medical history (other). Map basic_insurance_id/supplementary_insurance_id and merge profile.other on load, and keep the profile uuid even for an empty profile so PATCH saves work. Verified round-trip (name→label, insurance, other) against the live API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
# اتصال دقیق همهی تبهای داشبورد کاربر به دادهی واقعی backend
|
||||
|
||||
## پروژه
|
||||
|
||||
`nobat724_front` — سایت عمومی. **frontend-only**؛ همهی endpointهای لازم در backend موجودند (پروفایل، نوبتهای کاربر، پرداختها). تبهایی که backend ندارند (نظرات/پیامها) باید empty-state درست نشان دهند، نه دادهی جعلی.
|
||||
|
||||
## زمینه
|
||||
|
||||
`/dashboard` شش تب دارد (`components/dashboard/userAccount/index.js`):
|
||||
۱. **حساب کاربری** (DetailUser → اطلاعات عمومی + سوابق پزشکی: بیماریها/آلرژی/داروها/جراحی/سابقهخانوادگی/بستگان)
|
||||
۲. **نوبتهای من** (Turns)
|
||||
۳. **تراکنشهای من** (Transactions)
|
||||
۴. **نظرات من** (Comments)
|
||||
۵. **پیامها** (Messages)
|
||||
۶. **خروج**
|
||||
|
||||
وضعیت فعلی بعد از رفعهای اخیر:
|
||||
- نوبتها → `GET /api/v1/appointments/user` (وصل شده)
|
||||
- تراکنشها → `GET /api/v1/my/payments` (وصل شده)
|
||||
- حساب کاربری → `getUserProfile(userUuid)` لود میشود ولی **مپینگ فیلدها چند ایراد دارد** (بیمه، سوابق پزشکی) و کامل round-trip نمیشود.
|
||||
- نظرات/پیامها → از `user.comments`/`user.messages` که `buildPatientUser` همیشه `[]` میگذارد؛ **هیچ endpoint کاربری برای این دو در backend نیست** (تأییدشده: فقط `/comments/{doctorUuid}` و admin؛ messages اصلاً نیست).
|
||||
|
||||
## مشکل / هدف
|
||||
|
||||
۱. تب **حساب کاربری** را درست لود و ذخیره کن: مپینگ صحیح بیمه و سوابق پزشکی (`other`)، استفاده از `uuid` پروفایل برای PATCH.
|
||||
۲. تبهای **نوبتها/تراکنشها** را تأیید کن (شکل پاسخ، empty-state، تاریخ شمسی، مبلغ).
|
||||
۳. تبهای **نظرات/پیامها**: چون backend ندارند، empty-state تمیز نشان بده (نه crash، نه دادهی ساختگی). در گزارش ذکر کن که نیاز به endpoint backend دارند (cross-repo آینده).
|
||||
|
||||
## فایلهای مرتبط
|
||||
|
||||
| فایل | نقش |
|
||||
|------|-----|
|
||||
| `components/dashboard/userAccount/detailUser/information/index.js` | لود پروفایل برای فرم اطلاعات + سوابق |
|
||||
| `components/dashboard/userAccount/detailUser/index.js` | PATCH ذخیره (`patchUserProfile(usedKeys, information?.uuid)`) |
|
||||
| `components/dashboard/userAccount/detailUser/function.js` | `setNewData` (تغییر سوابق پزشکی) |
|
||||
| `helper/index.js` | `removeAdditionalKeysDashboard`, `changeDateType` |
|
||||
| `components/dashboard/userAccount/sidebars/turns/index.js` | نوبتها (وصلشده — تأیید) |
|
||||
| `components/dashboard/userAccount/sidebars/transactions/index.js` | تراکنشها (وصلشده — تأیید) |
|
||||
| `components/dashboard/userAccount/sidebars/comments/index.js` | `user.comments` |
|
||||
| `components/dashboard/userAccount/sidebars/messages/index.js` | `user.messages` |
|
||||
| `lib/representationAdapters.js` | `buildPatientUser` |
|
||||
| `clinicpro/docs/api/user-profile.md` | قرارداد پروفایل + فیلد `other` |
|
||||
|
||||
## وضعیت فعلی (کد واقعی)
|
||||
|
||||
### مپینگ غلط بیمه در `information/index.js`
|
||||
|
||||
```js
|
||||
const profile = res?.data?.data;
|
||||
// ...
|
||||
let changedData = { ...profile };
|
||||
changedData.basic_insurance = [Number(profile?.basic_insurance?.id)]; // ❌ backend فیلد basic_insurance_id (عدد) میدهد، نه object با .id → [NaN]
|
||||
changedData.prev_data = true;
|
||||
changedData = changeDateType(changedData, false);
|
||||
setInformation(changedData);
|
||||
```
|
||||
|
||||
> پاسخ پروفایل backend (از `toArray`): `basic_insurance_id`, `supplementary_insurance_id` (اعداد یا null)، نه `basic_insurance.id`. همچنین سوابق پزشکی در `other` است (`{ disease, allergies, medications, surgeries, family_history, relatives }`).
|
||||
|
||||
### قرارداد backend (از `user-profile.md` و entity `toArray`)
|
||||
|
||||
```json
|
||||
{
|
||||
"uuid": "...", "user_uuid": "...",
|
||||
"label": "...", "family": "...", "national_code": "...", "gender": "male",
|
||||
"date_of_birth": null, "fathers_name": null, "blood_type": null,
|
||||
"marital_status": null, "education": null, "job": null, "address": null,
|
||||
"home_phone": null, "work_phone": null,
|
||||
"insurance_id": null, "basic_insurance_id": 1, "supplementary_insurance_id": null,
|
||||
"other": { "disease": [...], "allergies": [...], "medications": [...], "surgeries": [...], "family_history": [...], "relatives": [...] },
|
||||
"description": null, "sharing_with_user": false
|
||||
}
|
||||
```
|
||||
> پاسخ دوبار تودرتو است → `res.data.data`.
|
||||
|
||||
### ذخیره در `detailUser/index.js`
|
||||
|
||||
```js
|
||||
const updateData = () => {
|
||||
const usedKays = removeAdditionalKeysDashboard(information);
|
||||
request.patchUserProfile(usedKays, information?.uuid, Cookies.get("access_token")) // arg سوم نادیده گرفته میشود
|
||||
.then(...).catch(...);
|
||||
};
|
||||
```
|
||||
|
||||
## وظایف
|
||||
|
||||
### ۱. مپینگ درست پروفایل هنگام لود (`information/index.js`)
|
||||
|
||||
- بیمه را از فیلد درست بخوان (نه `.id`):
|
||||
|
||||
```js
|
||||
let changedData = { ...profile };
|
||||
changedData.basic_insurance = profile?.basic_insurance_id ? [profile.basic_insurance_id] : [];
|
||||
changedData.supplementary_insurance = profile?.supplementary_insurance_id ? [profile.supplementary_insurance_id] : [];
|
||||
changedData.other = profile?.other ?? { disease, allergies: [], medications: [], surgeries: [], family_history: [], relatives: [] };
|
||||
changedData.prev_data = true;
|
||||
changedData = changeDateType(changedData, false);
|
||||
setInformation(changedData);
|
||||
```
|
||||
|
||||
- اطمینان حاصل کن `changedData.uuid = profile.uuid` (uuid پروفایل) حفظ میشود تا `patchUserProfile(..., information.uuid)` درست کار کند.
|
||||
- `hasProfileData` فعلی (`label || family || national_code`) قابلقبول است؛ ولی چون backend حالا پروفایل خالی lazy-create میکند، پروفایل همیشه `uuid` دارد — برای تشخیص «پر بودن» همان منطق فیلد محتوا را نگهدار، ولی `uuid` را حتی در حالت خالی هم در `information` بگذار تا PATCH کار کند:
|
||||
|
||||
```js
|
||||
} else {
|
||||
setInformation({
|
||||
uuid: profile?.uuid, // ✅ تا ذخیره ممکن باشد
|
||||
prev_data: false,
|
||||
other: { disease, allergies: [], medications: [], surgeries: [], family_history: [], relatives: [] },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### ۲. تأیید ذخیره (سوابق پزشکی → `other`)
|
||||
|
||||
- `removeAdditionalKeysDashboard(information)` باید payloadی بسازد که شامل `other` (سوابق) و فیلدهای پروفایل باشد و کلیدهای اضافی frontend (مثل `prev_data`) را حذف کند. بررسی کن خروجی با آنچه backend `hydrate` میپذیرد همخوان است (`name`/`label`, `family`, `national_code`, `gender`, `basic_insurance`, `supplementary_insurance`, `other`, ...).
|
||||
- بعد از PATCH موفق، `information.uuid` را از پاسخ بهروز نگهدار (اگر backend پروفایل جدید برگرداند).
|
||||
- arg سوم `patchUserProfile` (access_token) زائد است (interceptor خودش توکن میزند) — حذفش کن یا بگذار (بیاثر). ترجیحاً امضای تابع را تمیز نگهدار.
|
||||
|
||||
### ۳. تأیید تبهای نوبتها و تراکنشها
|
||||
|
||||
- **نوبتها** (`turns/index.js`): پاسخ `appointments/user` دوبار تودرتو است → `res.data.data` (آرایه). تأیید کن کارتها (`turns/Card.js`, `List.js`) فیلدهای واقعی نوبت (`slot_start`, `status`, `doctor`, `patient_name`) را میخوانند؛ تاریخ شمسی با `moment-jalaali`، وضعیتها به فارسی map شوند. اگر کارت فیلدهای mock قدیمی میخواند، با شکل واقعی `Appointment.toArray()` همخوان کن.
|
||||
- **تراکنشها** (`transactions/index.js`): پاسخ `my/payments` paginated است → `res.data` آرایه، `res.meta.totalPages`. تأیید کن `Card.js`/`List.js` فیلدهای واقعی پرداخت (`amount_rials`, `status`, `gateway`, `type`, `created_at`) را میخوانند؛ مبلغ ریال→تومان با جداکنندهی فارسی، وضعیتها فارسی.
|
||||
- **empty-state:** اگر آرایه خالی بود، پیام «موردی یافت نشد» (نه crash، نه اسپینر بیپایان).
|
||||
|
||||
### ۴. تبهای نظرات و پیامها (بدون backend)
|
||||
|
||||
- چون endpoint کاربری وجود ندارد، `Comments`/`Messages` از `user.comments`/`user.messages` (همیشه `[]`) میخوانند → empty-state تمیز نشان بده: «نظری ثبت نکردهاید» / «پیامی ندارید». مطمئن شو روی آرایهی خالی crash نمیکنند (`user.comments?.map`، گارد طول).
|
||||
- **دادهی جعلی نساز.** در گزارش پایانی ذکر کن که این دو تب برای دادهی واقعی نیاز به endpoint backend دارند (پرامپت cross-repo جداگانه در آینده).
|
||||
|
||||
## نکات مهم
|
||||
|
||||
- **هیچ تغییر backend در این پرامپت نیست.** پروفایل/نوبت/پرداخت همه آمادهاند؛ نظرات/پیامها عمداً empty میمانند.
|
||||
- **double-nesting:** `user-profile` و `appointments/user` → `res.data.data`؛ `my/payments` → paginated (`res.data` + `res.meta`). هرکدام را درست مصرف کن (با pitfallهای قبلی یکدست).
|
||||
- **uuid پروفایل برای PATCH:** `information.uuid` باید uuid پروفایل باشد (از `res.data.data.uuid`)، نه user-uuid.
|
||||
- **سوابق پزشکی = `other`:** همهی sub-tabها (allergies/medications/...) داخل `information.other` کار میکنند و با PATCH `other` ذخیره میشوند.
|
||||
- **Jalali/RTL/مبلغ:** تاریخها شمسی، مبالغ ریال→تومان با جداکنندهی فارسی، timestampها یونیکس.
|
||||
- **تست:** `npm run build`؛ سپس دستی با کاربر `09210651788` (پروفایل خالی + ۱ نوبت): تب حساب کاربری فرم خالی قابلویرایش و ذخیره؛ تب نوبتها ۱ نوبت با تاریخ/وضعیت درست؛ تب تراکنشها empty-state؛ نظرات/پیامها empty-state بدون crash. سپس commit per-tab.
|
||||
@@ -35,12 +35,22 @@ function Information({ information, setInformation }) {
|
||||
|
||||
if (hasProfileData) {
|
||||
let changedData = { ...profile };
|
||||
changedData.basic_insurance = [Number(profile?.basic_insurance?.id)];
|
||||
changedData.basic_insurance = profile?.basic_insurance_id ? [profile.basic_insurance_id] : [];
|
||||
changedData.supplementary_insurance = profile?.supplementary_insurance_id ? [profile.supplementary_insurance_id] : [];
|
||||
changedData.other = profile?.other ?? {
|
||||
disease,
|
||||
allergies: [],
|
||||
medications: [],
|
||||
surgeries: [],
|
||||
family_history: [],
|
||||
relatives: [],
|
||||
};
|
||||
changedData.prev_data = true;
|
||||
changedData = changeDateType(changedData, false);
|
||||
setInformation(changedData);
|
||||
} else {
|
||||
setInformation({
|
||||
uuid: profile?.uuid,
|
||||
prev_data: false,
|
||||
other: {
|
||||
disease: disease,
|
||||
|
||||
Reference in New Issue
Block a user