# نافذة التطبيق لجمهور محدد + زر يفتح صفحة + شريط اكتمال الملف — المطلوب من تطبيق الموبايل

**التاريخ:** 2026-11-09
**باختصار:** لا يوجد endpoint جديد، ولم يتغيّر اسم أو شكل أي مفتاح موجود. أضفنا مفتاحين جديدين فقط: `popup.action` و`profile_completion`. النسخ القديمة من التطبيق تستمر بالعمل كما هي.

المطلوب من التطبيق خمسة أمور، مرتبة حسب الأهمية:

1. إرسال التوكن مع طلبات الإعدادات (إن لم يكن مطبقاً بعد).
2. قراءة `popup.action` لفتح الصفحة المطلوبة من زر النافذة.
3. إضافة قسم العناوين إلى شاشة "تعديل الملف الشخصي".
4. رسم شريط اكتمال الملف من `profile_completion`.
5. اختياري: منتقي تاريخ الميلاد يطلب اليوم والشهر أيضاً.
6. إضافة رقم برمز تحقق للعميل الذي ليس لديه رقم، ولا تغيير للرقم بعد ذلك.

---

## 1) إرسال التوكن مع طلبات الإعدادات (مهم جداً)

النافذة صار لها جمهور يحدده فريق التسويق: مثلاً "العملاء الذين ملفهم غير مكتمل"، أو "الإناث من 18 إلى 30"، أو "من لم يطلب قط"، أو "الزوار فقط". **السيرفر هو من يقرر** لكل عميل، ويرجّع `show_popup: false` لمن لا تنطبق عليه.

السيرفر يعرف العميل فقط من الهيدر `Authorization: Bearer <token>`. بدون توكن يعامله كزائر، فلا تظهر له أي نافذة موجهة للعملاء المسجلين.

| الطلب | ملاحظة |
|---|---|
| `GET /api/v2/business-settings` | المفتاح `popup` |
| `POST /api/v2/business-settings` (مع `keys`) | إذا طلب مفاتيح `app_popup_*` |
| `POST /api/v2/app/data` | مجموعة `business_settings` تأخذ هيدرات الطلب نفسه |

- **بعد تسجيل الدخول أو الخروج:** أعد طلب الإعدادات واعرض النافذة حسب الجواب الجديد.
- **بعد حفظ الملف الشخصي:** أعد طلب الإعدادات أيضاً. نافذة "كمّل ملفك" تختفي فوراً من السيرفر عندما يكتمل الملف، فلا تُبقِ نسخة محفوظة منها.

(هذا البند نفسه مطلوب منذ `docs/api/coupon-min-orders-app.md`. إذا كان مطبقاً، فلا عمل هنا.)

**قد تعمل عدة نوافذ معاً لفئات مختلفة.** السيرفر يختار لكل عميل نافذة واحدة فقط، ويبقى `popup` نافذة واحدة بنفس الشكل. لكن:

- عميلان مختلفان قد يستقبلان نافذتين مختلفتين، والعميل نفسه قد تتغيّر نافذته عندما تتغيّر حاله (مثلاً بعد أن يكمل ملفه تظهر له النافذة التالية).
- إذا كان التطبيق يتذكر النوافذ التي عرضها (حتى لا يكررها)، فليتذكرها بـ `id` كل نافذة، ولا يعتبر عرض نافذة سبباً لعدم عرض نافذة أخرى بـ `id` مختلف.

## 2) زر النافذة يفتح صفحة: المفتاح الجديد `popup.action`

```json
"popup": {
  "show_popup": true,
  "id": 41,
  "type": "general",
  "title": "كمّل ملفك واربح 50$",
  "body": "...",
  "button_text": "كمّل ملفي",
  "expires_at": "2026-11-30T23:59:59+03:00",
  "discount": null,
  "action": { "type": "url", "url": "https://kapitano.shop/profile" }
}
```

| `action` | ماذا يفعل التطبيق |
|---|---|
| `null` (لا يوجد action) | كما الآن: يغلق النافذة، وينسخ الكود إذا كانت نافذة كوبون |
| `{ "type": "url", "url": ... }` | يغلق النافذة ويفتح الرابط |
| أي `type` آخر لا تعرفه | تعامل معه كـ `null`، فقد نضيف أنواعاً لاحقاً |

**الزر رابط فقط.** فريق التسويق يكتب رابطاً من موقعنا، والتطبيق يحوّله إلى شاشته كما يفعل مع الـ deep links (`docs/api/deep-links/README.md`). إذا لم تكن للرابط شاشة في التطبيق، يفتحه في المتصفح.

**مطلوب: الرابط `https://kapitano.shop/profile` يفتح شاشة "تعديل الملف الشخصي"** (أو `kapitano://profile`). هذا هو الرابط الذي ستستعمله حملة "كمّل ملفك واربح 50$".

## 3) العناوين في شاشة تعديل الملف الشخصي

اتفقنا أن يكون الملف الشخصي كله في صفحة واحدة، والموقع صار كذلك:

- أضف تحت حقول الشاشة الحالية (الصورة، الاسم، الكنية، تاريخ الميلاد، الهاتف، الجنس، البريد) قسم **العناوين**: قائمة العناوين، وزر "إضافة عنوان"، و"تعيين كافتراضي".
- استعمل الـ endpoints الموجودة للعناوين كما هي، فلا شيء جديد على السيرفر.
- **الهاتف** للعرض فقط ولا يُعدَّل، لأنه وسيلة تسجيل الدخول. الموقع يعرضه للقراءة فقط أيضاً. العميل الذي **ليس لديه رقم** يضيفه برمز تحقق: انظر البند 6.

## 4) شريط اكتمال الملف: المفتاح الجديد `profile_completion`

يأتي في `GET /api/v2/profile/counters` (يُطلب أصلاً عند كل فتح للتطبيق):

```json
"profile_completion": {
  "complete": false,
  "percent": 60,
  "missing": ["birthday", "address"],
  "completed_at": null
}
```

- `missing` بالترتيب: `name`, `gender`, `birthday`, `phone`, `address`. ارسم بنداً لكل عنصر يفتح الحقل المقصود، و`address` يفتح قسم العناوين.
- `phone` يعني أن العميل **ليس لديه رقم** (حسابات قديمة سجّلت بالإيميل أو بحسابات التواصل الاجتماعي، نحو 580 حساباً)، أو أن رقمه لم يُؤكَّد برمز. البند يفتح إضافة الرقم (البند 6).
- عند `complete: true` أخفِ الشريط أو اعرض "ملفك مكتمل".

**الملف المكتمل** = الاسم + الجنس (ذكر/أنثى) + تاريخ ميلاد + رقم موبايل محقّق + عنوان فيه محافظة ومدينة. البريد اختياري.

- **تاريخ الميلاد في السنة الحالية لا يُقبل**، لأن منتقي التاريخ يتركه هكذا إن لم يلمسه العميل.
- **تاريخ 1/1 من أي سنة سابقة مقبول.**

## 5) اختياري: منتقي تاريخ الميلاد

حالياً إذا اختار العميل السنة فقط، يُحفظ اليوم والشهر 1/1. في النسخة المحلية من القاعدة حوالي 19% من تواريخ الميلاد هي 1/1. العمر صحيح في هذه الحالة، لكن يوم عيد الميلاد غير معروف (فلا تصلها حملات أو كوبونات عيد الميلاد). اجعل المنتقي يطلب اليوم والشهر أيضاً.

---

## كيف تختبر

1. من لوحة الأدمن: التسويق ← نافذة التطبيق ← نشر نافذة جديدة. في "تظهر لـ" اختر "العملاء المسجّلون الذين تنطبق عليهم الفلاتر"، وفي "الملف الشخصي" اختر "غير مكتمل"، وفي "الزر يفتح" اختر "رابط" واكتب `https://kapitano.shop/profile`.
2. **عميل ملفه ناقص:** تظهر النافذة، والزر يفتح تعديل الملف.
3. أكمل الملف (أضف عنواناً) ثم أعد طلب الإعدادات: `show_popup: false`، و`profile_completion.complete: true`.
4. **زائر بلا توكن:** لا تظهر النافذة.

---

## 6) الرقم: يُضاف برمز تحقق ولا يُغيَّر

قرار 2026-11-09:

- **الرقم المحقّق** هو الرقم الذي أكّده رمز واتساب. كل عميل كان لديه رقم قبل هذا التاريخ يُحسب محقّقاً.
- **العميل الذي لديه رقم لا يستطيع تغييره** من الملف الشخصي.
- **العميل الذي ليس لديه رقم** يضيفه برمز تحقق.

ماذا يفعل السيرفر في `POST /api/v2/profile/update` عندما يصله `phone`:

| الحالة | الجواب |
|---|---|
| نفس رقم الحساب | يُتجاهل ويُحفظ الباقي (التطبيق يرسل الرقم مع كل حفظ، فلا يتأثر) |
| رقم مختلف والحساب لديه رقم | `result: false` برسالة "رقم موبايلك هو ما تسجّل الدخول به، لذلك لا يمكن تغييره من هنا." ولا يُحفظ شيء |
| الحساب بلا رقم، والرقم لم يُؤكَّد برمز | `result: false` برسالة "أكّد رقم موبايلك برمز واتساب أولاً." |
| الحساب بلا رقم، والرقم أُكّد برمز خلال آخر 15 دقيقة | يُحفظ الرقم ويصير محقّقاً |

**كيف يضيف التطبيق رقماً لعميل بلا رقم** (بالـ endpoints الموجودة، ولا شيء جديد):

**خانة الرقم نفس خانة تسجيل الدخول في التطبيق:** اختيار الدولة لوحده (سوريا +963 افتراضياً) والرقم لوحده، ونفس فحص الرقم قبل إرسال الرمز (libphonenumber)، ونفس شاشة إدخال الرمز وإعادة الإرسال. ويُرسَل الرقم بصيغته الكاملة `+963…` مع `country_code` كما في الدخول.

1. `POST /api/v2/send-otp` بالرقم: يصل العميل رمز على واتساب.
2. `POST /api/v2/verify-otp` بالرقم والرمز. الرقم غير مسجّل لأحد، فالجواب `action: register`: **تجاهله ولا تفتح شاشة التسجيل**، فالعميل مسجّل دخوله أصلاً. السيرفر يتذكر أن الرقم تأكّد لمدة 15 دقيقة.
3. `POST /api/v2/profile/update` مع `phone`: يُحفظ الرقم محقّقاً.

إذا كان الرقم مسجّلاً لحساب آخر، فـ `verify-otp` سيسجّل الدخول إلى ذلك الحساب. لذلك افحص الرقم أولاً بـ `profile/check-phone-and-email`، واعرض "هذا الرقم مسجّل لحساب آخر" قبل إرسال الرمز.

**على الموقع:** صفحة الملف الشخصي تعرض للعميل بلا رقم بطاقة "أضف رقم موبايلك" فيها نفس خانة تسجيل الدخول: اختيار الدولة والرقم وفحص الرقم، ثم أرسل الرمز ← أدخل الرمز. وللعميل الذي لديه رقم يظهر الرقم للقراءة فقط.
