> ## 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.

# Pokazuj dane metafields na pozycjach koszyka

> Przypadek użycia Cart SDK wykorzystujący registerCartEnricher do pobierania metafields z Shopify Storefront API na każdą pozycję koszyka i ich renderowania.

Koszyk wie to, co mówi mu Ajax API Shopify: tytuły, ceny, ilości, właściwości. Nie zna Twoich metafields. **Cart enricher** pobiera dodatkowe pola produktu lub wariantu ze Storefront API i dołącza je do każdej pasującej pozycji, dzięki czemu możesz pokazać szacowany czas dostawy, ostrzeżenie „wysyłane osobno”, listę składników lub cokolwiek innego przechowywanego na produkcie.

Typowe zastosowania: okna dostawy per produkt, odznaki alergenów lub składników, niestandardowa flaga „niski stan magazynowy”, mnożniki punktów lojalnościowych, ceny tylko dla subskrybentów.

<div id="register-the-enricher">
  ## Zarejestruj 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 }
  `,
});
```

Trzy pola:

| Pole       | Opis                                                                                                                             |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | Przestrzeń nazw dla wyniku; ląduje w `line.metadata[id]`. Musi być unikalne; druga rejestracja z tym samym `id` jest ignorowana. |
| `onType`   | `'Product'` lub `'ProductVariant'`. Także klucz łączenia, czyli ID produktu vs. ID wariantu.                                     |
| `fragment` | Selekcja pól GraphQL (bez zewnętrznych nawiasów klamrowych) wklejana do zapytania Storefront. Nawiasy muszą się bilansować.      |

Za każdym razem, gdy koszyk się ładuje lub zmienia, Aftersell pobiera Twój fragment dla każdego produktu lub wariantu w koszyku. Pobieranie jest **nieblokujące**: koszyk renderuje się natychmiast i ponownie emituje `cart_updated`, gdy dane dotrą. Wolny lub zawodzący fragment nigdy nie opóźnia ani nie psuje koszyka.

<div id="read-the-data">
  ## Odczytaj dane
</div>

Ponieważ wzbogacanie jest asynchroniczne, `line.metadata.delivery` ma wartość `undefined`, dopóki pierwsze pobranie się nie rozwiąże. Zawsze zabezpieczaj odczyt.

```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">
  ## Wyrenderuj to w koszyku
</div>

Wzbogacanie umieszcza dane na pozycji; [blok Custom code](/pl/aftersell/cart/custom-code-blocks) w trybie React je rysuje. Dodaj blok jako **pod-blok Cart items**, aby renderował się raz na pozycję i otrzymywał tę pozycję jako `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>
  Wzbogacone wartości wracają ze Storefront API **w stanie surowym i bez sanityzacji**. Renderuj je jako tekst, jak powyżej, i nigdy przez `dangerouslySetInnerHTML` ani przez zapisywanie surowego HTML.
</Warning>

<div id="variant-level-data">
  ## Dane na poziomie wariantu
</div>

Ustaw `onType: 'ProductVariant'`, gdy metafield znajduje się na wariancie, a nie na produkcie:

```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">
  ## Więcej niż metafields
</div>

Fragment jest wklejany do zapytania Storefront API, więc działa wszystko, co API udostępnia na `Product` lub `ProductVariant`, nie tylko metafields:

```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">
  ## Rzeczy, które trzeba zrobić dobrze
</div>

* **Zabezpieczaj każdy odczyt.** `metadata` domyślnie to `{}`, a Twoja przestrzeń nazw ma wartość `undefined`, dopóki pobranie się nie rozwiąże. Koszyk zawsze renderuje się przed nadejściem danych.
* **Każde `id` to własna przestrzeń nazw.** Wiele enricherów współistnieje bez kolizji, w tym te zarejestrowane przez inne aplikacje.
* **Metafields muszą być widoczne dla Storefront.** Metafield nieudostępniony Storefront API zwraca `null`. Jeśli nic nie wraca, sprawdź definicję w panelu Shopify.
* **Utrzymuj fragment mały.** Działa dla każdego produktu w koszyku, przy każdej zmianie koszyka. Proś o pola, których używasz, a nie o wszystko.
* **Rejestruj w czasie konfiguracji.** To hook, więc jego miejsce jest na początku skryptu Initialization.
* **Nawiasy muszą się bilansować.** Bez zewnętrznych nawiasów wokół fragmentu, ale każda zagnieżdżona selekcja potrzebuje własnej dopasowanej pary. Niezbilansowany fragment jest odrzucany.

<div id="where-to-go-next">
  ## Co dalej
</div>

* **[`registerCartEnricher`](/pl/aftersell/cart/sdk-hooks#registercartenricher)**: pełne odniesienie do hooka.
* **[Bloki Custom code](/pl/aftersell/cart/custom-code-blocks)**: renderowanie danych.
* **[Obiekt koszyka](/pl/aftersell/cart/sdk-cart-object)**: gdzie na pozycji znajduje się `metadata`.
