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

# Automatycznie dodawaj darmowy prezent przy progu

> Przypadek użycia Cart SDK, który dodaje darmowy prezent, gdy suma koszyka przekroczy próg, i usuwa go, gdy suma spadnie poniżej.

Obserwuj sumę koszyka i utrzymuj darmowy prezent w synchronizacji z nią: dodaj prezent, gdy kupujący przekroczy próg wydatków, i usuń go, gdy spadnie z powrotem poniżej.

<Note>
  Dla wersji konfigurowanej przez sprzedawcę, z progami, regułami per rynek i paskiem postępu, użyj bloku [Rewards](/pl/aftersell/cart/rewards-block), bez kodu. Ten sposób jest na sytuacje, gdy Twojej reguły blok nie potrafi wyrazić.
</Note>

<div id="the-snippet">
  ## Fragment kodu
</div>

Wklej w **Cart settings → Custom script → Initialization** i ustaw dwie stałe:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const FREE_GIFT_VARIANT_ID = 1234567890; // the gift product's variant id
const THRESHOLD_CENTS = 5000;            // $50.00, since totals are in cents

function reconcileGift(state) {
  const gift = state.items.find((line) => line.variantId === FREE_GIFT_VARIANT_ID);
  const qualifies = state.totalPrice >= THRESHOLD_CENTS;

  if (qualifies && !gift) {
    window.aftersell.cart.actions.addItem(FREE_GIFT_VARIANT_ID, 1);
  } else if (!qualifies && gift) {
    window.aftersell.cart.actions.removeItem(gift.key);
  }
}

window.aftersell.cart.events.on('cart_loaded', reconcileGift);
window.aftersell.cart.events.on('cart_updated', reconcileGift);
```

<div id="how-it-works">
  ## Jak to działa
</div>

**`reconcileGift`** opisuje stan, w jakim koszyk *powinien* się znajdować, a następnie wykonuje najwyżej jedną zmianę, aby go osiągnąć:

* Kwalifikuje się, a prezentu nie ma → [`addItem`](/pl/aftersell/cart/sdk-actions#additemvariantid-quantity) go dodaje.
* Nie kwalifikuje się, a prezent jest → [`removeItem`](/pl/aftersell/cart/sdk-actions#removeitemkey) usuwa go po `key` pozycji.
* W przeciwnym razie → nic nie rób.

Działa zarówno na [`cart_loaded`](/pl/aftersell/cart/sdk-events#cart_loaded) (dzięki czemu koszyk, który kwalifikuje się już przy załadowaniu strony, dostaje prezent), jak i na [`cart_updated`](/pl/aftersell/cart/sdk-events#cart_updated) (dzięki czemu reaguje na każdą późniejszą zmianę). Ponieważ `cart_loaded` jest odtwarzane dla spóźnionych subskrybentów, działa to niezależnie od tego, kiedy uruchomi się Twój skrypt.

<Warning>
  **To zabezpieczenia `!gift` / `gift` powstrzymują zapętlenie.** Dodanie prezentu wywołuje `cart_updated`, które ponownie uruchamia `reconcileGift`, a drugi przebieg zastaje prezent już obecny, więc nic nie robi. Usuń zabezpieczenia, a dostaniesz nieskończoną pętlę. Zobacz [dwie zasady](/pl/aftersell/cart/sdk-events#the-two-rules).
</Warning>

Zwróć uwagę, że dodanie prezentu **podnosi sumę koszyka**, więc próg blisko ceny produktu może oscylować: dodanie prezentu za \$0 jest bezpieczne, ale prezent z ceną mógłby sam przepchnąć koszyk powyżej progu. Utrzymuj prezent darmowym albo porównuj z sumą, która go wyklucza.

<div id="adapting-it">
  ## Dostosowanie
</div>

**Warunkuj liczbą produktów zamiast wydatków:**

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const qualifies = state.itemCount >= 3;
```

**Warunkuj obecnością konkretnego produktu w koszyku:**

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const qualifies = state.items.some((line) => line.productId === TRIGGER_PRODUCT_ID);
```

**Tylko w wybranych krajach.** Odczytaj [`context`](/pl/aftersell/cart/sdk-overview#context), dostępny przed załadowaniem koszyka:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const ELIGIBLE = ['US', 'CA'];

// Only register the handlers for eligible countries.
if (ELIGIBLE.includes(window.aftersell.cart.context.customer_country)) {
  window.aftersell.cart.events.on('cart_loaded', reconcileGift);
  window.aftersell.cart.events.on('cart_updated', reconcileGift);
}
```

**Wyklucz prezent z progu**, aby nie mógł sam siebie podtrzymywać:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
const subtotalWithoutGift = state.items.reduce(
  (sum, line) => (line.variantId === FREE_GIFT_VARIANT_ID ? sum : sum + line.finalLinePrice),
  0
);
const qualifies = subtotalWithoutGift >= THRESHOLD_CENTS;
```

**Oznacz prezent, aby wyglądał jak prezent.** [Transformacja pozycji](/pl/aftersell/cart/sdk-hooks#registerlinetransform) może zmienić tytuł pozycji, tytuł wariantu, stan ukrycia i właściwości wewnętrzne — więc zmień etykietę:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.variantId === FREE_GIFT_VARIANT_ID) {
    line.setTitle('Free gift 🎁');
  }
});
```

<Note>
  Transformacja pozycji **nie potrafi ukryć kontrolek ilości pozycji** — jej jedyne settery to `setTitle`, `setVariantTitle`, `setHidden` i `setInternalProperties`. Jeśli kupujący zmieni ilość prezentu, skoryguj ją zamiast tego z obsługi `cart_updated`.
</Note>

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

* **[Blok Rewards](/pl/aftersell/cart/rewards-block)**: wersja bez kodu, z progami.
* **[Actions](/pl/aftersell/cart/sdk-actions)**: `addItem`, `removeItem` i pozostałe.
* **[Events](/pl/aftersell/cart/sdk-events)**: dlaczego zabezpieczenia mają znaczenie.
