# أقسام الصفحة الرئيسية

يستطيع تطبيقك قراءة أقسام الصفحة الرئيسية للمتجر وتغييرها. القسم كتلة في الصفحة الرئيسية لها نوع وإعدادات. يمكن إضافة عشرة أنواع في كل قالب: `category-products` و`featured` و`categories` و`banner` و`image-with-text` و`rich-text` و`trust-badges` و`testimonials` و`faq` و`video`؛ ويقدّم قالب مبني على الأقسام مثل `atlas` أيضاً `hero` و`product-grid`. كل كتابة تظهر في المتجر بمجرد أن تُرجع استجابتها.

المرجع الكامل للطلبات والردود موجود في وصف `OpenAPI`، ورابطه في صفحة [مرجع الواجهة البرمجية](https://dzbuild.dev/ar/ar/api-reference.md): `getStoreHomeLayout` و`addStoreHomeSection` و`updateStoreHomeSection` و`deleteStoreHomeSection` و`reorderStoreHomeSections` و`replaceStoreHomeLayout`. تشرح هذه الصفحة كيف تترابط هذه الأجزاء.

## الصلاحيات[​](#الصلاحيات "رابط مباشر إلى الصلاحيات")

| الصلاحية      | تسمح بـ                                                                                                                                                                                             |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `store:read`  | `GET /v1/store/home-layout`                                                                                                                                                                         |
| `store:write` | `POST /v1/store/home-layout/sections`, `PATCH /v1/store/home-layout/sections/{id}`, `DELETE /v1/store/home-layout/sections/{id}`, `POST /v1/store/home-layout/reorder`, `PUT /v1/store/home-layout` |

الاستدعاء الذي ينقصه النطاق يُرجع `403` بالرمز `forbidden` والرسالة `Missing scope: store:write` (أو `store:read`). انظر [الصلاحيات](https://dzbuild.dev/ar/ar/scopes.md).

## قراءة التخطيط[​](#قراءة-التخطيط "رابط مباشر إلى قراءة التخطيط")

تُرجع `GET /v1/store/home-layout`:

| الحقل          | المعنى                                                                                                                                                                                                 |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `theme`        | مفتاح قالب المتجر.                                                                                                                                                                                     |
| `rendered`     | `false` عندما لا يعرض قالب المتجر الحالي أقسام الصفحة الرئيسية. تبقى الأقسام محفوظة وتظهر من جديد مع قالب يعرضها. وفي قالب مبني على الأقسام لا تكون `true` إلا ما دام قسم `product-grid` ظاهر محفوظاً. |
| `max_sections` | 25، أقصى عدد من الأقسام تحمله صفحة رئيسية واحدة.                                                                                                                                                       |
| `cap`          | عدد الأقسام الذي تسمح به خطة المتجر: 3 في الخطة المجانية أو خطة منتهية، و25 ابتداءً من `Pro`. يُثبَّت تطبيقك على متاجر من كل الخطط، فاقرأ `cap` بدل افتراض 25.                                         |
| `version`      | بصمة التخطيط المخزَّن، تُستعمل مع `PUT`.                                                                                                                                                               |
| `sections`     | `{id, type, settings, is_active, available}` بترتيب العرض، ومعها الأقسام المخفية. تكون `available` بقيمة `false` عندما لا يعود القالب يملك ذلك النوع، ويبقى القسم كما خُزّن.                           |
| `types`        | الأنواع التي يمكن إضافتها في هذا القالب، ولكل نوع `name` و`description` و`icon` و`limit` و`settings_schema`.                                                                                           |

ابنِ نماذجك من `settings_schema` بدل كتابة نوع ثابت في برنامجك: القائمة تتبع قالب المتجر. لكل إعداد `id` و`type` (`checkbox` أو `range` أو `select` أو `text` أو `textarea` أو `color` أو `link` أو `image` أو `category` أو `youtube`) و`default`، و`min` و`max` أو `options` حيث تنطبق، و`label` و`option_labels` بالعربية والفرنسية.

إعدادات `category-products` هي `category` (رقم فئة من `GET /v1/categories` التي تحتاج إلى `products:read`)، و`title` (حتى 80 حرفاً، والفارغ يُظهر اسم الفئة)، و`count` (من 4 إلى 12)، و`layout` (`grid` أو `slider`)، و`show_view_all` (رابط إلى صفحة الفئة).

القسم الذي لم يُملأ محتواه بعد (بلا فئة أو بفئة لا منتجات فيها، أو `banner` بلا `image`، أو `image-with-text` بلا `image` أو بلا `title` و`text` معاً، أو `rich-text` أو `testimonials` أو `faq` أو `video` فارغ) يُخزَّن وتُرجع الكتابة `2xx`، لكن المشترين لا يرونه حتى يُملأ. لا تقول `rendered` إلا إن كان القالب يعرض الأقسام المخزّنة.

إعداد `image` لا يقبل إلا مسار صورة رفعها التاجر من لوحة التحكم لهذا المتجر (`/uploads/banners/{store_id}/...`) أو `""`. لا يمكن رفع الصور عبر الواجهة البرمجية حالياً، لذلك يحتاج `banner` أو `image-with-text` إلى هذا الرفع أولاً.

## تغيير التخطيط[​](#تغيير-التخطيط "رابط مباشر إلى تغيير التخطيط")

كل كتابة ما عدا `PUT` تحتاج إلى ترويسة `Idempotency-Key` (انظر [حدود معدّل الطلبات](https://dzbuild.dev/ar/ar/rate-limits.md)).

```
POST /v1/store/home-layout/sections HTTP/1.1

Host: api.dzbuild.app

Authorization: Bearer dzpk_live_xxxxxxxx

Idempotency-Key: hs-add-64

Content-Type: application/json



{"type": "category-products", "settings": {"category": 64}, "position": 0}
```

يُرجع الاستدعاء `201` مع القسم الجديد والتخطيط كاملاً:

```
{

  "data": {

    "section": {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},

    "sections": [

      {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 412, "type": "category-products", "settings": {"category": 57, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true}

    ],

    "version": "e27a90c4b1f36d05",

    "change_id": 90231,

    "rendered": true

  },

  "meta": { "request_id": "3b7d0e5a9c14f862", "api_version": "v1" }

}
```

| العملية                     | الجسم                               | ملاحظات                                                                                                                                                                                                             |
| --------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST .../sections`         | `{type, settings?, position?}`      | الإعدادات غير المرسلة تأخذ القيم الافتراضية. `position` بقيمة 0 هو الأعلى، وبدونه يُضاف القسم في النهاية.                                                                                                           |
| `PATCH .../sections/{id}`   | `{settings?, is_active?, replace?}` | تُدمج الإعدادات فوق المخزّنة. `replace: true` يُرجع غير المرسلة إلى قيمها الافتراضية. `is_active: false` يُخفي القسم.                                                                                               |
| `DELETE .../sections/{id}`  | لا شيء                              | يُرجع `deleted: true` و`id` القسم.                                                                                                                                                                                  |
| `POST .../reorder`          | `{ids}`                             | كل أرقام أقسام الصفحة مرة واحدة بالضبط، ومعها المخفية.                                                                                                                                                              |
| `PUT /v1/store/home-layout` | `{sections, version?}`              | القائمة كاملة، 25 عنصراً على الأكثر. العنصر الذي يحمل `id` يُبقي ذلك القسم، والعنصر الذي بلا `id` ينشئ قسماً، والقسم غير المذكور يُحذف. `settings` هنا هو الكائن كاملاً: الإعداد المتروك يعود إلى قيمته الافتراضية. |

كل كتابة تُرجع التخطيط كاملاً بترتيب العرض مع `version` الجديدة، و`change_id` (بقيمة `null` عندما لا يتغيّر شيء)، و`rendered`. احتفظ بهذه الاستجابة. عبر `api.dzbuild.app` تُخزَّن استجابة `GET` الناجحة 30 ثانية لكل رمز وسلسلة استعلام، لذلك قد تُرجع `GET` المرسلة مباشرة بعد كتابة التخطيطَ السابق لها. أضف سلسلة استعلام من عندك إذا احتجت إلى قراءة جديدة.

لتتأكد أن أحداً لم يغيّر الصفحة بين قراءتك وكتابتك، أرسل `version` التي قرأتها مع `PUT`. إذا تغيّر التخطيط، يُرجع الاستدعاء `409 write_conflict` ولا يكتب شيئاً؛ ويحمل `error` عندها `sections` و`version` الحاليتين لتعيد المحاولة انطلاقاً منهما.

## التراجع[​](#التراجع "رابط مباشر إلى التراجع")

لا تستطيع رموز التثبيت استدعاء `/v1/changes` ولا `POST /v1/changes/{id}/undo`: تُرجعان `403` مع `Apps cannot use this endpoint`. ومع ذلك تُسجَّل كل كتابة، فيستطيع التاجر التراجع عنها من صفحة تطبيقك في لوحة التحكم. للتراجع داخل تطبيقك، احتفظ بـ `sections` التي قرأتها قبل التغيير وأرسلها من جديد مع `PUT`. القسم الذي حذفته يعود برقم جديد.

## الحدود[​](#الحدود "رابط مباشر إلى الحدود")

* 25 قسماً في الصفحة الرئيسية، و`cap` على الأكثر حسب خطة المتجر. الأقسام المخفية تُحسب. المتجر الذي تجاوز حدّه بعد نزول خطته يُبقي أقسامه، والكتابة التي تترك أقساماً أكثر من الحدّ وأكثر مما كانت تُرجع `403 plan_required`.
* لكل نوع `limit` في `types`، وهو 12 لـ `category-products`.
* 8 كيلوبايت من الإعدادات لكل قسم بعد الترميز، و1 ميغابايت لكل جسم طلب.
* 30 كتابة في الدقيقة و5 في الوقت نفسه لكل متجر، فوق ميزانية تثبيتك وميزانية المتجر. انظر [حدود معدّل الطلبات](https://dzbuild.dev/ar/ar/rate-limits.md).

## الردود ورموز الأخطاء[​](#الردود-ورموز-الأخطاء "رابط مباشر إلى الردود ورموز الأخطاء")

| الحالة | الرمز                                   | المعنى                                                                                                                                                                                               |
| ------ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  |                                         | قراءة أو تغيير أو حذف أو إعادة ترتيب أو استبدال.                                                                                                                                                     |
| `201`  |                                         | أُضيف القسم.                                                                                                                                                                                         |
| `400`  | `bad_request`                           | الجسم ليس كائن `JSON`، أو حقل من نوع خاطئ، أو رقم المسار ليس رقماً موجباً، أو `Idempotency-Key` غائب مع `POST` أو `PATCH` أو `DELETE`.                                                               |
| `403`  | `forbidden`                             | ينقص الرمزَ `store:read` أو `store:write`.                                                                                                                                                           |
| `403`  | `plan_required`                         | الكتابة تترك أقساماً أكثر مما تسمح به خطة المتجر. يحمل `error` قيمتي `plan` و`cap`.                                                                                                                  |
| `404`  | `section_not_found`                     | لا يوجد قسم بهذا الرقم في الصفحة الرئيسية للمتجر.                                                                                                                                                    |
| `409`  | `write_conflict`                        | غيّرت كتابة أخرى التخطيط قبلك، أو `version` المرسلة مع `PUT` ليست الحالية. عندما يحمل `error` قيمتي `sections` و`version` أعد المحاولة انطلاقاً منهما، وإلا فاقرأ من جديد. أعد المحاولة بمفتاح جديد. |
| `413`  | `payload_too_large`                     | الجسم أكبر من 1 ميغابايت.                                                                                                                                                                            |
| `422`  | `invalid_settings`                      | رُفضت قيمة. تذكر `error.fields` الإعدادات المرفوضة، مثل `settings.category`؛ ومع `PUT` إعدادات أول قسم مرفوض فقط، مثل `sections.2.settings.layout`. وتذكرها الرسالة أيضاً.                           |
| `422`  | `invalid_section_type`                  | النوع غير موجود أو لا يمكن إضافته في هذا القالب.                                                                                                                                                     |
| `422`  | `limit_reached`                         | أكثر من 25 قسماً، أو أكثر من `limit` لنوع واحد.                                                                                                                                                      |
| `422`  | `invalid_order`                         | `ids` في إعادة الترتيب ينقصها قسم أو تكرر قسماً.                                                                                                                                                     |
| `422`  | `no_changes`                            | `PATCH` بلا `settings` ولا `is_active`.                                                                                                                                                              |
| `429`  | `rate_limited` أو `too_many_concurrent` | نفدت ميزانية دقيقة، أو هناك 5 كتابات على تخطيط الصفحة الرئيسية تعمل للمتجر. انتظر `retry_after` ثانية.                                                                                               |

انظر [الأخطاء](https://dzbuild.dev/ar/ar/errors.md) للرموز التي قد يتلقاها أي استدعاء، مثل `app_uninstalled`.
