> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# عرض بيانات الحقول الوصفية على أسطر السلة

> حالة استخدام لـ Cart SDK باستخدام registerCartEnricher لجلب الحقول الوصفية من Shopify Storefront API إلى كل سطر في السلة، ثم عرضها.

تعرف السلة ما تخبرها به Ajax API الخاصة بـ Shopify: العناوين والأسعار والكميات والخصائص. لكنها لا تعرف حقولك الوصفية (metafields). يجلب **مُثري السلة (cart enricher)** حقول منتج أو متغير إضافية من Storefront API ويرفقها بكل سطر مطابق، بحيث يمكنك عرض تقدير للتسليم، أو تحذير "يُشحن على حدة"، أو قائمة مكونات، أو أي شيء آخر تخزّنه على المنتج.

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

<div id="register-the-enricher">
  ## تسجيل المُثري
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'delivery',
  onType: 'Product',
  fragment: `
    deliveryWindow: metafield(namespace: "custom", key: "delivery_window") { value }
    shipsSeparately: metafield(namespace: "custom", key: "ships_separately") { value }
  `,
});
```

ثلاثة حقول:

| الحقل      | الوصف                                                                                             |
| ---------- | ------------------------------------------------------------------------------------------------- |
| `id`       | مساحة اسم للنتيجة؛ تصل إلى `line.metadata[id]`. يجب أن يكون فريدًا؛ يُتجاهل تسجيل ثانٍ بنفس `id`. |
| `onType`   | `'Product'` أو `'ProductVariant'`. وهو أيضًا مفتاح الربط، أي معرّف المنتج مقابل معرّف المتغير.    |
| `fragment` | تحديد حقول GraphQL (بدون أقواس خارجية) يُدرج في استعلام Storefront. يجب أن تتوازن الأقواس.        |

كلما حُمّلت السلة أو تغيّرت، تجلب Aftersell جزءك (fragment) لكل منتج أو متغير في السلة. الجلب **غير حاجب**: تُعرض السلة فورًا ويُعاد إطلاق `cart_updated` بمجرد وصول البيانات. الجزء البطيء أو الفاشل لا يؤخّر السلة ولا يعطّلها أبدًا.

<div id="read-the-data">
  ## قراءة البيانات
</div>

نظرًا لأن الإثراء غير متزامن، يكون `line.metadata.delivery` قيمته `undefined` حتى يتحقق أول جلب. احرس القراءة دائمًا.

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (state) => {
  state.items.forEach((line) => {
    const deliveryWindow = line.metadata.delivery?.deliveryWindow?.value;
    if (!deliveryWindow) return; // not fetched yet

    console.log(line.title, 'arrives in', deliveryWindow);
  });
});
```

<div id="render-it-in-the-cart">
  ## عرضها في السلة
</div>

يضع الإثراء البيانات على السطر؛ وترسمها [كتلة التعليمات البرمجية المخصصة](/ar/aftersell/cart/custom-code-blocks) في وضع React. أضف الكتلة ككتلة فرعية ضمن **Cart items** بحيث تُعرض مرة لكل سطر وتستقبل ذلك السطر كـ `props.line`:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomCode(props) {
  const data = props.line?.metadata?.delivery;
  const window_ = data?.deliveryWindow?.value;

  if (!window_) return null;

  return (
    <div className="cart-external-custom-code_html" style={{ fontSize: '12px', opacity: 0.7 }}>
      Arrives in {window_}
    </div>
  );
}
```

<Warning>
  تعود القيم المُثراة من Storefront API **كما هي وبدون تعقيم**. اعرضها كنص، كما في الأعلى، وليس أبدًا باستخدام `dangerouslySetInnerHTML` أو بكتابة HTML خام.
</Warning>

<div id="variant-level-data">
  ## بيانات على مستوى المتغير
</div>

عيّن `onType: 'ProductVariant'` عندما يكون الحقل الوصفي على المتغير وليس على المنتج:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'pricing',
  onType: 'ProductVariant',
  fragment: `
    anchorPrice: metafield(namespace: "custom", key: "anchor_price") { value }
    subscriberPrice: metafield(namespace: "custom", key: "subscriber_price") { value }
  `,
});
```

<div id="more-than-metafields">
  ## أكثر من الحقول الوصفية
</div>

يُدرج الجزء في استعلام Storefront API، لذا فإن أي شيء تكشفه الواجهة على `Product` أو `ProductVariant` يعمل، وليس الحقول الوصفية فقط:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerCartEnricher({
  id: 'productInfo',
  onType: 'Product',
  fragment: `
    tags
    vendor
    productType
    availableForSale
  `,
});
```

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Then: warn about anything from a drop-ship vendor.
window.aftersell.cart.events.on('cart_updated', (state) => {
  const hasDropship = state.items.some((line) => {
    const tags = line.metadata.productInfo?.tags;
    return tags?.includes('dropship');
  });
});
```

<div id="things-to-get-right">
  ## أمور يجب ضبطها بشكل صحيح
</div>

* **احرس كل قراءة.** القيمة الافتراضية لـ `metadata` هي `{}` ومساحة اسمك تكون `undefined` حتى يتحقق الجلب. تُعرض السلة قبل وصول البيانات، دائمًا.
* **كل `id` هو مساحة اسم خاصة به.** تتعايش عدة مُثريات دون تصادم، بما في ذلك تلك التي تسجلها تطبيقات أخرى.
* **يجب أن تكون الحقول الوصفية مرئية لـ Storefront.** الحقل الوصفي غير المكشوف لـ Storefront API يعيد `null`. تحقق من التعريف في لوحة إدارة Shopify إذا لم تحصل على شيء.
* **أبقِ الجزء صغيرًا.** فهو يعمل لكل منتج في السلة، عند كل تغيير في السلة. اطلب الحقول التي تستخدمها، وليس كل شيء.
* **سجّل وقت الإعداد.** إنه خُطاف، لذا فمكانه أعلى نص Initialization البرمجي.
* **يجب أن تتوازن الأقواس.** لا أقواس خارجية حول الجزء، لكن أي تحديد متداخل يحتاج إلى زوجه المطابق. الجزء غير المتوازن يُرفض.

<div id="where-to-go-next">
  ## إلى أين تذهب بعد ذلك
</div>

* **[`registerCartEnricher`](/ar/aftersell/cart/sdk-hooks#registercartenricher)**: المرجع الكامل للخُطاف.
* **[كتل التعليمات البرمجية المخصصة](/ar/aftersell/cart/custom-code-blocks)**: عرض البيانات.
* **[كائن السلة](/ar/aftersell/cart/sdk-cart-object)**: مكان `metadata` على السطر.
