# رفع نمایش نقشه صفحه پزشک + بهبود مودال claim (کپچا/موبایل) + حذف پروفایل توسط مالک

## پروژه

`nobat724_front` (سایت عمومی)
> پرامپت همتا (backend اول): `clinicpro/.claude/prompt/doctor-map-claim-captcha-delete.md` — کپچا و فیلد mobile روی endpoint claim، و اجازهٔ حذف پروفایل به مالک. این پرامپت آن قرارداد را مصرف می‌کند.

## زمینه

سه موضوع در صفحهٔ پزشک سایت:
1. نقشه در صفحهٔ پزشک درست نمایش داده نمی‌شود (مثال: `/doctor/ab747d75-2114-42b8-9e6d-abdaa338edbe`).
2. مودال «تأیید و مدیریت پروفایل» (claim) از قبل هست ولی طبق سناریو باید متن کادر اطلاع‌رسانی به‌روز شود، **فیلد موبایل** و **کپچای ALTCHA** اضافه شود.
3. پس از مالک‌شدن، پزشک باید دکمهٔ **حذف پروفایل** داشته باشد.

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

| فایل | نقش |
|------|-----|
| `app/doctor/[slug]/page.js` | فچ `doctor` + `getDoctorAddresses(doctor.id)` (خط ۲۴، ۱۰۵) |
| `components/doctor/detailDoctor/cards/locations/index.js` | کارت آدرس‌ها — از `doctor?.address` می‌خواند (خط ۱۱) |
| `components/doctor/detailDoctor/cards/locations/Item.js` | رندر iframe گوگل با `data.map.latitude/longitude` (خط ۴۶، ۶۵) |
| `components/doctor/claim/index.js` | `ClaimProfileSection` موجود (سکشن + مودال) |
| `components/Altcha.js` | کامپوننت ALTCHA موجود سایت |
| `services/response.js` | `getDoctorClaimInfo` / `postDoctorClaim` موجود |

## وظیفه ۱ — رفع نمایش نقشه صفحه پزشک

### ریشه (تأییدشده)

کارت آدرس‌ها از **`doctor?.address`** می‌خواند:

```jsx
// components/doctor/detailDoctor/cards/locations/index.js:11
{doctor?.address?.map((item, idx) => ( <Item data={item} /> ))}
```

اما مختصات نقشه در پاسخِ **جداگانه**‌ی `GET /api/v1/clinic-pro/doctor-addresses/{id}` است (backend آن را با شکل `map: { latitude, longitude }` برمی‌گرداند). در صفحه، این پاسخ در متغیر `addresses` فچ می‌شود و فقط در **JSON-LD** استفاده شده (`app/doctor/[slug]/page.js:105,141`)، ولی به کارت دیداری آدرس‌ها **پاس داده نمی‌شود**. پس `doctor.address` یا خالی است یا `map` ندارد → `Item` شرط `data?.map?.latitude` را رد می‌کند → نقشه هرگز نمایش داده نمی‌شود.

### راه‌حل

`addresses` (که `map.latitude/longitude` دارد) را به همان کارتی که نقشه را رندر می‌کند برسان:

- در `app/doctor/[slug]/page.js`، `addresses` را به `DoctorPage`/`detailDoctor` پاس بده (prop جدید یا ادغام در `doctor.address`).
- در `locations/index.js`، به‌جای `doctor?.address` از همان آرایهٔ `addresses` استفاده کن که هر آیتم `map: { latitude, longitude }` و `address`/`telephone` دارد.
- شکل مصرفی `Item` (`data.map.latitude`, `data.map.longitude`, `data.address`, `data.telephone`) را با شکل خروجی `doctor-addresses` هم‌تراز کن (backend همین کلیدها را می‌دهد — تأیید در `clinicpro/src/Doctor/Controller/DoctorController.php:166`).

```jsx
// locations/index.js — نمونه
export default function Locations({ addresses }) {
  if (!addresses?.length) return null;
  return (<>{addresses.map((item, idx) => <Item key={idx} data={item} />)}</>);
}
```

- **edge:** پزشکِ ایمپورت‌شده (مثل نمونهٔ کاربر) آدرس ندارد → آرایه خالی → کارت اصلاً رندر نشود (نه نقشهٔ خراب). این درست است.
- **edge:** آدرسِ بدون مختصات (`latitude=null`) → دکمهٔ مسیریابی/iframe نمایش داده نشود، ولی خود آدرس/تلفن نمایش داده شود.

## وظیفه ۲ — بهبود مودال claim (متن، موبایل، کپچا)

`components/doctor/claim/index.js` از قبل سکشن + مودال دارد. تغییرات:

**الف) متن کادر اطلاع‌رسانی** (طبق سناریو):

> «این پروفایل بر اساس اطلاعات عمومی سازمان نظام پزشکی ایجاد شده است و هنوز توسط پزشک تأیید و مدیریت نمی‌شود. نوبت‌های این پروفایل عمومی و غیرخاص هستند.
> آیا شما این پزشک هستید؟» + دکمهٔ «تأیید و مدیریت این پروفایل».

**ب) فیلد موبایل در فرم:** علاوه بر نام/نام‌خانوادگی/کد ملی/تاریخ تولد، فیلد **شماره موبایل** اضافه شود (پیش‌پرشده از کاربر لاگین‌شده اگر در دسترس است). به بدنهٔ `postDoctorClaim` اضافه شود:

```js
await request.postDoctorClaim(doctor.uuid, {
  national_code, birth_date, first_name, last_name, mobile, altcha, // ← mobile و altcha جدید
});
```

**ج) کپچای ALTCHA:** از کامپوننت موجود `components/Altcha.js` استفاده کن. تا وقتی کاربر کپچا را حل نکرده، دکمهٔ ارسال **غیرفعال** بماند:

```jsx
import Altcha from "@/components/Altcha";
// ...
const [altcha, setAltcha] = useState("");
// در فرم:
<Altcha onVerified={setAltcha} />
<Button disabled={loading || !altcha} onClick={submit}>تأیید هویت و تصاحب پروفایل</Button>
```

- payload کپچا را در بدنهٔ claim بفرست (backend همتا `CaptchaGuard::assertValid` را چک می‌کند). نام فیلد را با آنچه `CaptchaGuard` انتظار دارد هماهنگ کن (بررسی `AuthController` سایت/بک‌اند — معمولاً `altcha`).
- اگر `ALTCHA_ENABLED=false` (dev) بک‌اند کپچا را نادیده می‌گیرد؛ ولی UI کپچا را نشان بده تا در prod کار کند.

**stateهای موجود مودال** (loading/error/success/double-submit/پیام خوش‌آمد) حفظ شوند؛ فقط فیلدها و کپچا اضافه می‌شوند. خطای `ERR_CAPTCHA_001` از بک‌اند → پیام «تأیید امنیتی ناموفق بود، دوباره تلاش کنید».

## وظیفه ۳ — حذف پروفایل توسط مالک

پس از claim موفق (پزشک مالک شد)، در صفحهٔ مدیریت پروفایل پزشک (یا همان صفحهٔ پزشک وقتی کاربرِ لاگین‌شده مالک است) دکمهٔ **«حذف پروفایل»** نمایش داده شود.

- فقط وقتی نمایش داده شود که کاربرِ لاگین‌شده مالکِ `claimed` این پروفایل باشد (از `owner_status` + تطبیق کاربر). مرجع نهایی مجوز، backend است.
- کلیک → **دیالوگ تأیید** با پیام هشدار (طبق سناریو: «قبل از حذف، پیام هشدار نمایش داده شود»)، سپس:

```js
// متد جدید در services/response.js
deleteDoctor: (uuid) => api.delete(`api/v1/doctor/${uuid}`, { requireAuth: true }),
```

- backend اجازهٔ حذف مالک را می‌دهد (پرامپت همتا). خطاها: ۴۰۳ (مالک نیست)، ۴۰۹ (پزشک نوبت ثبت‌شده دارد) → پیام فارسی مناسب.
- پس از حذف موفق → هدایت به صفحهٔ اصلی/پنل + toast موفقیت.

## نکات مهم

- **backend اول اجرا شود** (کپچا + فیلد mobile + delete مالک) وگرنه این تغییرات ۴۲۲/۴۰۳ می‌گیرند.
- multi-domain: مودال claim کامپوننت مشترک است و روی همهٔ دامنه‌ها/زیردامنه‌ها کار می‌کند؛ منطق را per-domain تکرار نکن.
- RTL، فارسی، Vazir، date-picker شمسی موجود؛ کتابخانهٔ جدید اضافه نکن.
- هیچ درخواستی از فرانت به API سازمان (شاهکار/ثبت‌احوال) نرود؛ همه backend.
- تست:
  ```bash
  cd nobat724_front && npm run lint && npm run build
  # صفحهٔ پزشکِ دارای آدرس با مختصات → نقشه نمایش داده شود؛
  # پزشک ایمپورت‌شدهٔ بدون آدرس → کارت نقشه رندر نشود (نه خراب)؛
  # مودال claim → کپچا اجباری، فیلد موبایل، ارسال موفق؛ دکمهٔ حذف فقط برای مالک.
  ```
