# Claude handoff: مزامنة بيانات التطبيق وتجميع الطلبات

## ما تغير في الخادم

أضاف الخادم ثلاثة أشياء للنسخ الجديدة من التطبيق. كل endpoint قديم بقي كما هو، فالنسخ المنشورة لا تتأثر:

1. `POST /api/v2/app/data`: طلبات الإقلاع والصفحة الرئيسية في طلب واحد. كل مجموعة لم تتغير منذ آخر مرة ترجع `null`.
2. `POST /api/v2/checkout/overview`: طلبات صفحة الدفع السبعة في طلب واحد.
3. مفاتيح جديدة على endpoints قائمة تُغني عن طلبات إضافية:
   - حقول الخصم في كل سطر من `POST carts`.
   - `cart_count` في ردود الإضافة والتعديل والحذف.
   - `?with=cart` في صفحة المنتج.

اقرأ قبل البدء:
- `docs/api/app-data-sync.md`: العقد الكامل بالأمثلة.
- `docs/api/mobile-performance-guide.md`: كيف تُخزَّن المجموعات والصور على الجهاز، وجدول الحالات الخاصة. هذا الملف ينفّذه.

أهم قاعدة: **كل جزء في هذه الردود هو جسم الـ endpoint القديم نفسه حرفياً**. حلّل كل جزء بالـ parser الموجود اليوم لذلك الـ endpoint. لا تكتب موديلات جديدة لنفس البيانات.

## المطلوب في التطبيق

### 1. مخزن محلي للمجموعات

- لكل مجموعة احفظ `last_updated` و`data` كما وصلا، **في سجل واحد يُكتب دفعة واحدة**، في Hive أو Isar أو ملف لكل مجموعة. لا تستعمل SharedPreferences للبيانات الكبيرة.
- الطابع نص معتم: يُخزَّن ويُعاد كما هو. لا يُحلَّل ولا يُقارن كتاريخ ولا تُستعمل ساعة الجهاز.
- أرسل `<group>_last_updated` **فقط** إن كانت بيانات تلك المجموعة مخزنة وسليمة. بيانات ممسوحة أو تثبيت جديد يعني: لا ترسل طابعاً.
- أضف `schemaVersion` للمخزن، وامسحه عند تغيّر الـ parsers في نسخة جديدة.
- مجموعة فشل تحليلها: احذفها وحدها واطلبها بلا طابع.
- عند تسجيل الخروج امسح بيانات المجموعات الخاصة بالحساب: `cart_count`، `unread_notifications`، `order_rating_pending`، `profile_counters`، `addresses`. الطابع آمن بين الحسابات لأنه مبني على المحتوى، لكن بيانات الحساب السابق يجب ألا تبقى على الجهاز.

### 2. الإقلاع والرئيسية عبر `app/data`

- في `AppInitProvider` استبدل الاستدعاءات المنفصلة بطلب واحد فيه:
  - `groups` بالترتيب الأهم أولاً.
  - `temp_user_id`.
  - الطوابع المخزنة.
- مجموعات الإقلاع: `business_settings`، `currencies`، `languages`، `app_version`، `event_logo`، `cart_count`. وللمسجّل أيضاً `order_rating_pending` و`unread_notifications`.
- مجموعات الرئيسية: `sliders`، `banners_one`، `flash_deal_banners`، `featured_categories`، `shops`، `brands`، `featured_products`، `todays_deal_products`، `best_selling_products`، `all_products`، `flash_deals`. وللمسجّل أيضاً `addresses`. يجوز دمجها مع مجموعات الإقلاع في طلب واحد.
- اعرض الرئيسية من المخزن **فوراً**، وأرسل الطلب في نفس اللحظة.
- لكل مجموعة طلبتها:
  - القيمة `null`: استعمل `data` المخزنة. إن لم توجد (لا يجب أن يحدث) فاستدعِ الـ endpoint القديم لها.
  - كائن `{last_updated, data}`: حلّل `data` بالـ parser القديم، واحفظها مع الطابع، وحدّث ذلك الجزء من الشاشة فقط. السيرفر لا يرسل طابعاً فارغاً. إن وصل فارغاً احتياطاً، فاحفظ البيانات بلا طابع.
  - **المفتاح غائب** أو الاسم في `_deferred`: استدعِ الـ endpoint القديم عبر الـ repository الحالي كما اليوم، والمستقل منها بالتوازي.
- فك JSON الرد الكبير خارج خيط الواجهة: `compute(jsonDecode, body)`.
- لا ترسل طلبي `app/data` في نفس الوقت.
- إن فشل الطلب كله، أو رجع `success` ليس `true`، فاستعمل المسار القديم كاملاً. السيرفر القديم يرد بـ HTTP 200 وبالنص `{"success": false, "status": 404, "message": "Invalid Route"}`.
- المجموعات هي الصفحة الأولى فقط. الصفحات التالية (`page=2`…) والبحث والفلاتر تبقى على الـ endpoints القديمة.
- `app_version` و`event_logo` لهما طابع مثل الباقي، لكنهما ترجعان ببياناتهما **دائماً** (لا `null`)، فلا تعتمد على نسخة مخزنة لفحص التحديث الإجباري.
- عند العودة من الخلفية بعد أكثر من 5 دقائق، وعند السحب للتحديث: نفس الطلب بالطوابع.

### 3. السلة

- في `POST carts` كل عنصر من `cart_items` فيه الآن: `has_discount`، `discount`، `stroked_price`، `main_price`. القيم نفسها التي تأتي من صفحة المنتج.
- احذف طلب `products/{slug}/{user_id}` لكل سطر في السلة، واقرأ الحقول من السطر نفسه.
- بعد `carts/add` و`carts/process` و`DELETE carts/{id}`: إن وُجد `cart_count` في الرد فاستعمله لشارة السلة بدل طلب `cart-count`. إن غاب فاستدعِ `cart-count` كما اليوم.

### 4. صفحة المنتج

- اطلب `products/{slug}/{user_id}?with=cart`، وأضف `&temp_user_id=` للزائر.
- استعمل `cart_count` و`in_cart_quantity` و`in_cart` (كل عنصر: `cart_id` و`variant` و`quantity`) بدل طلب `POST carts` من صفحة المنتج.
- لتغيير الكمية أو الحذف استعمل `cart_id` من `in_cart`.

### 5. صفحة الدفع

- عند فتح الصفحة وعند تغيير العنوان: طلب واحد `POST checkout/overview` بنفس الحقول التي ترسلها اليوم للاستدعاءات السبعة: `address_id`، `seller_list`، حقول عنوان الزائر، و`mode`/`list`.
- الأجزاء التي ترجع: `carts`، `addresses`، `update_address_in_cart`، `delivery_info`، `shipping_cost`، `payment_types`، `cart_summary`. حلّل كلاً منها بالـ parser القديم.
- `carts` يُقرأ **قبل** الكتابتين، كما كانت الصفحة تفعل. خذ مبالغ الشحن والمجموع من `shipping_cost` و`cart_summary`.
- الجزء الغائب يعني أن استدعاءه لم يرجع 200. استدعِ الـ endpoint القديم لذلك الجزء. الأجزاء التالية له نُفذت فعلاً.
- `result: false` داخل جزء هو رد ذلك الاستدعاء نفسه، فاعرضه كما تفعل اليوم.
- تغيير نوع الشحن وحده يمكن أن يبقى `shipping_cost` ثم `cart-summary`.

### 6. الصور

التفاصيل في §5 من `mobile-performance-guide.md`.

- كل صور الكتالوج عبر `CachedNetworkImage`، **لا `Image.network`**، بمدير كاش مخصص:
  - مفتاحه الرابط.
  - `stalePeriod` 90 يوماً.
  - `maxNrOfCacheObjects` 3000.
- في الشبكات والقوائم: `memCacheWidth` بحجم العرض.
- رابط الصورة على سيرفرنا لا يتغير محتواه أبداً: كل صورة جديدة لها رابط جديد. فالكاش بالرابط يكفي، ولا حاجة لأي فحص آخر.
- صور الفئات:
  - عند وصول `featured_categories` أو `top_categories` ببيانات جديدة: حمّل في الخلفية الروابط غير الموجودة في الكاش (`getFileFromCache` ثم `downloadFile`)، واحذف روابط الفئات التي اختفت (`removeFile`).
  - شغّل نفس الفحص عند الإقلاع حتى لو رجعت `null`، ليعيد تحميل ما مسحه النظام.
- لا تمسح كاش الصور عند تسجيل الخروج، فالصور عامة.

### 7. الشبكة

- `http.Client` واحد مشترك في كل التطبيق (keep-alive)، مع إبقاء gzip.
- إعادة المحاولة بتأخير متزايد لطلبات القراءة فقط، **لا لطلبات الكتابة**.
- البحث: انتظار 300 إلى 400 ميلي ثانية بعد آخر حرف، وإلغاء الطلب السابق.
- الصفحة التالية عند الوصول لنحو 75% من القائمة.

## اختبارات التطبيق المطلوبة

- أول إقلاع بلا مخزن: لا طوابع في الطلب، وكل مجموعة تُحلَّل وتُحفظ.
- إقلاع ثانٍ: الطوابع تُرسل، والقيم `null` تعرض البيانات المخزنة دون خطأ.
- مجموعة غائبة أو في `_deferred`: الـ endpoint القديم يُستدعى لها وحدها.
- رد `Invalid Route` أو خطأ شبكة: يعود التطبيق للمسار القديم كاملاً.
- تبديل اللغة: البيانات الجديدة تُستبدل بالمخزنة.
- تسجيل الخروج: تُمسح بيانات مجموعات الحساب.
- السلة: لا طلب `products/{slug}` لأي سطر، والخصم يظهر كما قبل.
- شارة السلة تتحدث من `cart_count` بعد الإضافة والتعديل والحذف.
- صفحة المنتج: تظهر الكمية الموجودة في السلة دون `POST carts`.
- صفحة الدفع: طلب واحد يملأ الصفحة كاملة، وجزء غائب يُستدعى وحده.
- مخزن تالف لمجموعة: تُحذف وتُطلب بلا طابع، والتطبيق لا يتعطل.
- رفع `schemaVersion`: يُمسح المخزن ويُعاد التحميل.
- فتح شاشة الفئات مرة ثانية: صفر طلبات صور، وتعمل بلا إنترنت.
- تغيير صورة فئة من لوحة التحكم: تظهر الجديدة بعد المزامنة التالية، وتُحذف القديمة من الكاش.
- مسح كاش الصور من إعدادات النظام: تعود صور الفئات في الإقلاع التالي.

## دليل التسليم المطلوب من Claude

- أسماء ملفات التطبيق المعدلة: الـ repositories، والـ providers، وطبقة التخزين.
- نتائج اختبارات API client والحالة والواجهة.
- لقطة Network:
  - إقلاع بلا مخزن.
  - إقلاع ثانٍ يرجع `null`، مع حجم الرد.
  - السلة بلا طلبات `products/{slug}`.
  - صفحة دفع بطلب واحد.
  - فتح ثانٍ لشاشة الفئات بلا طلبات صور.
- تأكيد أن التطبيق يعمل على سيرفر قديم يرد `Invalid Route`.
- عدد الطلبات وحجمها لكل شاشة، قبل التغيير وبعده.
