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

# Настройка пользовательского шаблона в Upcart

> В этой статье описаны ключевые props, доступные для настройки шаблонов Upcart, что помогает персонализировать корзину, сохраняя основную функциональность.

<div id="important-notice">
  ## ⚠️ **Важное уведомление**
</div>

Пользовательские шаблоны требуют продвинутых технических знаний HTML, CSS, JavaScript и React. Прежде чем продолжить, убедитесь, что у вас достаточно опыта разработки или есть доступ к квалифицированному разработчику Shopify. **Наша команда поддержки не оказывает помощь в разработке, отладке или устранении неполадок пользовательских шаблонов.** Технические вопросы следует адресовать эксперту Shopify или квалифицированному разработчику.

***

<div id="code-editor-features">
  ## Возможности редактора кода
</div>

Редактор кода пользовательских шаблонов включает встроенные инструменты, которые помогают проще писать корректные шаблоны.

<div id="typescript-intellisense">
  ### TypeScript IntelliSense
</div>

Редактор понимает TypeScript, поэтому по мере ввода вы получаете подсказки автодополнения, проверку типов и встроенную документацию для всех доступных `props`. Подсказки типов props — это IntelliSense только для редактора, помогающий писать шаблоны: они не являются частью шаблона и никогда не выполняются на вашей витрине.

<div id="editable-template-body">
  ### Редактируемое тело шаблона
</div>

Редактор показывает только редактируемое JSX-тело вашего шаблона — заблокированных строк нет. Обрамляющая функция-обёртка добавляется автоматически на этапе сборки и никогда не отображается в редакторе.

Используйте **Reset to default** в любой момент, чтобы восстановить исходный шаблон, если ваши правки нарушили структуру шаблона.

***

<div id="general-section">
  ## Раздел General
</div>

<div id="header">
  ## Заголовок (Header)
</div>

Модуль Header позволяет настроить шапку корзины с собственным дизайном, сохраняя основную функциональность корзины, такую как отображение количества товаров и кнопка закрытия.

<div id="available-props-full-template">
  ### **Доступные props — Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-drawer-header-title.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=7c679bee70bf5ff8a61657d83158e986" alt="Шапка корзины-drawer с заголовком Cart, количеством товаров и кнопкой закрытия" width="400" data-path="images/upcart/custom-template-cart-drawer-header-title.png" />

`cartQuantity`

* **Тип**: `string`

* **Описание**: текущее количество товаров в корзине, отформатированное как строка

* **Использование**: отображение количества товаров в корзине в вашем пользовательском дизайне шапки

```
<h2>Shopping Cart ({props.cartQuantity})</h2>
```

`closeHandler`

* **Тип**: `() => void`

* **Описание**: функция обратного вызова, закрывающая корзину при срабатывании

* **Использование**: привяжите к кнопкам, значкам или другим интерактивным элементам для закрытия корзины

```
<button  
  onClick={props.closeHandler}  
  aria-label="Close cart"  
>×</button>
```

`titleComponent`

* **Тип**: `React.ReactElement | null`

* **Описание**: предварительно отрендеренный компонент заголовка шапки корзины с корректными стилями и переводами

* **Использование**: отображение заголовка корзины в соответствии с конфигурацией настроек корзины

```
<div>{props.titleComponent}</div>
```

***

<div id="body-section">
  ## Раздел Body
</div>

<div id="announcements">
  ## Объявления
</div>

Модуль Announcements позволяет настроить отображение объявлений с собственным дизайном, сохраняя основную функциональность объявлений, такую как управление таймером и условная видимость.

<div id="available-props-full-template-2">
  ### Доступные props — **Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-announcement-bar-countdown.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=2c7d03e71ebf5bec3b5d3bddff3447b3" alt="Панель объявлений корзины с таймером обратного отсчёта, резервирующим товары покупателя" width="400" data-path="images/upcart/custom-template-cart-announcement-bar-countdown.png" />

`announcementTemplate`

* **Тип**: `string`

* **Описание**: HTML-содержимое сообщения объявления

* **Использование**: отображение сообщения объявления в ваших пользовательских реализациях

```
<div dangerouslySetInnerHTML={{ __html: props.announcementTemplate }} />
```

`timer`

* **Тип**: `string`

* **Описание**: текущее значение таймера, отформатированное как строка

* **Использование**: отображение таймера обратного отсчёта в пользовательских реализациях объявлений

```
<div>Time remaining: {props.timer}</div>
```

`shouldUseTimer`

* **Тип**: `boolean`

* **Описание**: указывает, включена ли функциональность таймера для этого объявления

* **Использование**: условный рендеринг содержимого и элементов управления, связанных с таймером

```
<div>  
  {props.shouldUseTimer && (  
    <span>{props.timer}</span>   
  )}  
</div>
```

`isTimerExpiredAndShouldHide`

* **Тип**: `boolean`

* **Описание**: указывает, истёк ли таймер и должно ли объявление быть скрыто

* **Использование**: управление видимостью всего объявления в зависимости от состояния таймера

```
<div>  
  {!props.isTimerExpiredAndShouldHide && (  
    <div>{props.timer}</div>  
  )}  
</div>
```

<div id="tiered-rewards">
  ## Многоуровневые вознаграждения
</div>

Модуль Rewards позволяет настроить отображение прогресса вознаграждений с собственным дизайном, сохраняя основную функциональность вознаграждений, такую как отслеживание этапов, визуализация прогресса и сообщения о вознаграждениях.

<div id="available-props-full-template-3">
  ### Доступные props — **Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-tiered-rewards-progress-bar.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=78f30082b982815d333f8de09225d884" alt="Индикатор прогресса многоуровневых вознаграждений со значками этапов бесплатной доставки и товара" width="400" data-path="images/upcart/custom-template-tiered-rewards-progress-bar.png" />

`rewardsMessageHtml`

* **Тип**: `string`

* **Описание**: HTML-содержимое сообщения о вознаграждениях

* **Использование**: отображение сообщения о вознаграждениях с расширенным форматированием в пользовательских реализациях

```
<div dangerouslySetInnerHTML={{ __html: props.rewardsMessageHtml }} />
```

`milestonesCompleted`

* **Тип**: `number`

* **Описание**: количество достигнутых этапов

* **Использование**: отображение количества достигнутых этапов или вычисление процента выполнения

```
<div>  
  {Math.round((props.milestonesCompleted / props.milestonesData.milestonesToRender.length) * 100)}% Complete  
</div>
```

`milestonesData`

* Тип:

  ```
  {  
    milestonesToRender: {  
      id: string;  
      label: string;  
      icon: React.ReactElement;  
      isCompleted: boolean;  
      positionPercent: number;  
    }[];  
    progressPercent: number;  
    showMilestones: boolean;  
    settings: {  
      iconContainerSize: string;  
      iconAlignment: string;  
      labelAlignment: string;  
      hideLabel: boolean;  
    };  
  }
  ```

* **Описание**: полная конфигурация этапов и данные прогресса для системы вознаграждений

* **Использование**: доступ к информации об этапах, проценту прогресса и настройкам отображения

* **Свойства**:

  * `milestonesToRender`: массив объектов этапов со статусом выполнения и позиционированием
  * `progressPercent`: текущий прогресс в процентах (0–100)
  * `showMilestones`: отображать ли маркеры этапов
  * `settings`: визуальная конфигурация отображения этапов

<div id="discounts">
  ## Скидки
</div>

Модуль Discounts поддерживает пользовательские шаблоны, чтобы вы могли разработать собственное отображение, сохраняя основную функциональность, такую как управление правилами, видимость раздела и представление вознаграждений. Внутренний идентификатор типа модуля для пользовательских шаблонов — `TRIGGERED_REWARDS` для обратной совместимости с существующим кодом пользовательских шаблонов.

<div id="available-props-full-template-4">
  ### **Доступные props — Full template**
</div>

`rules`

* **Тип**:

  ```
  {  
    id: string;  
    title: string;  
    description: string;  
    conditionsMet: boolean;  
  }[]
  ```

* **Описание**: массив правил Discount, которые в данный момент включены

* **Использование**: отображение доступных вознаграждений, их названий, описаний и того, выполнены ли условия каждого правила

* **Свойства**:

  * `id`: уникальный идентификатор правила вознаграждения
  * `title`: название правила Discount
  * `description`: описание правила вознаграждения
  * `conditionsMet`: выполнены ли в данный момент условия правила содержимым корзины. Используйте для построения UX-паттернов «вы разблокировали X» и «потратьте ещё \$Y, чтобы разблокировать X»

```
<div>
  {props.rules.map((rule) => (
    <div key={rule.id}>
      <h3>{rule.title}</h3>
      <p>{rule.conditionsMet ? "Reward unlocked!" : rule.description}</p>
    </div>
  ))}
</div>
```

`showSection`

* **Тип**: `boolean`

* **Описание**: указывает, должен ли отображаться раздел Discounts

* **Использование**: управление видимостью всего модуля Discounts

```
<div>  
  {props.showSection && (  
    <div>  
      <h2>Available Rewards...</h2>  
    </div>  
  )}  
</div>
```

`onToggleSection`

* **Тип**: `() => void`

* **Описание**: функция обратного вызова, переключающая состояние видимости раздела Discounts

* **Использование**: привяжите к кнопкам или интерактивным элементам, чтобы позволить пользователям показывать/скрывать раздел вознаграждений

```
<button type="button" onClick={props.onToggleSection}>  
  {props.showSection ? "Hide Rewards" : "Show Available Rewards"}  
</button>
```

<div id="recommendations">
  ## Рекомендации
</div>

Модуль Recommendation позволяет настроить отображение товаров-апселлов с собственным дизайном, сохраняя основную функциональность электронной коммерции, такую как выбор варианта, добавление в корзину и отображение информации о товаре.

<div id="available-props-recommendation-tile-template">
  ### **Доступные props — Recommendation tile template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-recommendation-tile-snowboard-product.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=7db82e0496937fa8ee8eea180edb3530" alt="Плитка рекомендации со сноубордом, ценой и кнопкой Add" width="400" data-path="images/upcart/custom-template-recommendation-tile-snowboard-product.png" />

*Шаблон плитки рекомендации использует [тот же интерфейс props, что и шаблон плитки апселла](#available-props-upsell-tile-template) в модуле Upsells. Все доступные props, типы и примеры использования задокументированы в разделе модуля Upsells ниже.*

<div id="cart-items">
  ## Товары корзины
</div>

Модуль Cart Items позволяет настроить отображение товаров корзины с собственным дизайном, сохраняя основную функциональность электронной коммерции. Этот модуль предоставляет несколько типов шаблонов, каждый со своими props для разных аспектов отображения товаров корзины.

<Note>
  **Отображение индикатора загрузки при добавлении в корзину или обновлении корзины:** стандартный модуль Cart Items не предоставляет встроенный спиннер «добавление в корзину». Если вы хотите показывать состояние загрузки, пока товар добавляется или выполняется операция с корзиной, используйте шаблон Product tile и читайте props `isLoading` и `loadingOperation` (задокументированы ниже) для условного рендеринга спиннера или оверлея. Пользовательские шаблоны требуют опыта разработки — см. уведомление в начале этой страницы.
</Note>

<div id="available-props-product-tile-template">
  ### **Доступные props — Product tile template**
</div>

**Примечание:** включение шаблона *Product Tile* переопределит все остальные шаблоны этого модуля, включая **Variant template**, **Properties template**, **Bundle template** и **Price template**.\
Если вы хотите использовать пользовательский код в любом из этих шаблонов, вы ***обязаны*** *выключить шаблон Product Tile.*

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-product-tile-variant.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=3d2efc06b542f7c59cc86ad3fe611a0e" alt="Плитка товара в корзине с изображением, вариантом, ценой со скидкой, селектором количества и кнопкой подписки" width="400" data-path="images/upcart/custom-template-cart-product-tile-variant.png" />

`title`

* **Тип**: `string`

* **Описание**: название товара

* **Использование**: отображение основного названия товара в позициях корзины

`variant`

* **Тип**: `React.ReactNode`

* **Описание**: предварительно отрендеренный компонент информации о варианте

* **Использование**: отображение деталей варианта как React-компонента

`properties`

* **Тип**: `React.ReactNode`

* **Описание**: предварительно отрендеренный компонент свойств товара

* **Использование**: отображение свойств товара и информации о подписке как React-компонента

`bundle`

* **Тип**: `React.ReactNode`

* **Описание**: предварительно отрендеренный компонент деталей комплекта

* **Использование**: отображение информации о комплекте как React-компонента

`compareAtPrice`

* **Тип**: `string | undefined`

* **Описание**: отформатированная цена до скидки (первоначальная цена)

* **Использование**: отображение первоначальной цены для товаров со скидкой

`price`

* **Тип**: `string`

* **Описание**: отформатированная текущая цена

* **Использование**: отображение текущей цены позиции

`savings`

* **Тип**: `string | undefined`

* **Описание**: отформатированная сумма экономии

* **Использование**: отображение того, сколько экономит покупатель

`imageUrl`

* **Тип**: `string | undefined`

* **Описание**: URL изображения товара

* **Использование**: отображение изображения товара

`productUrl`

* **Тип**: `string | undefined`

* **Описание**: URL страницы товара

* **Использование**: ссылка на страницу товара

`quantity`

* **Тип**: `number`

* **Описание**: текущее количество позиции в корзине

* **Использование**: отображение и управление количеством позиции

`showQuantitySelector`

* **Тип**: `boolean`

* **Описание**: показывать ли элементы управления количеством

* **Использование**: условное отображение селектора количества

`discountCodes`

* **Тип**: `string[] | undefined`

* **Описание**: массив применённых кодов скидок для этой позиции

* **Использование**: отображение скидок для конкретной позиции

`subscription`

* **Тип**:

  ```
  {  
    subscriptionUpgradeData: {  
      buttonText: string;  
      defaultSellingPlanId: number;  
    } | null;  
    sellingPlansData: {  
      sellingPlanGroups: {  
        name: string;  
        selling_plans: {  
          id: number;  
          name: string;  
        }[];  
      }[] | null;  
      activeSellingPlanId: string;  
      oneTimePurchaseText: string | null;  
    } | null;  
    upgradeSellingPlan: (item: CartItem, sellingPlanId: number) => void;  
    changeSellingPlan: (item: CartItem, value: string) => void;  
    getSellingPlanGroupText: (groupName: string, planName: string) => string;  
  }
  ```

* **Описание**: полный объект управления подписками с данными об апгрейде, планами продаж и функциями-обработчиками

* **Использование**: управление функциональностью подписок

* Объект subscription содержит:

  * **subscriptionUpgradeData**: информация об апгрейде (null, если апгрейд недоступен)

    * `buttonText`: текст кнопки апгрейда
    * `defaultSellingPlanId`: ID плана продаж по умолчанию для апгрейдов
  * **sellingPlansData**: доступные варианты планов продаж (null, если планов нет)

    * `sellingPlanGroups`: массив групп планов с их планами продаж
    * `activeSellingPlanId`: ID выбранного в данный момент плана продаж
    * `oneTimePurchaseText`: текст варианта разовой покупки (null, если недоступен)
  * **upgradeSellingPlan**: функция для апгрейда до конкретного плана продаж
  * **changeSellingPlan**: функция для смены текущего плана продаж
  * **getSellingPlanGroupText**: вспомогательная функция для форматирования отображаемого текста плана продаж

`onIncrease`

* **Тип**: `() => void`

* **Описание**: функция увеличения количества позиции

* **Использование**: обработка действий увеличения количества

`onDecrease`

* **Тип**: `() => void`

* **Описание**: функция уменьшения количества позиции

* **Использование**: обработка действий уменьшения количества

`onDeleteProduct`

* **Тип**: `() => void`

* **Описание**: функция удаления позиции из корзины

* **Использование**: обработка удаления позиции

`onQuantityChange`

* **Тип**: `(quantity: string) => void`

* **Описание**: функция обработки прямого ввода количества

* **Использование**: обработка ручных изменений количества

`handleInputChange`

* **Тип**: `(e: React.ChangeEvent<HTMLInputElement>) => void`

* **Описание**: обработчик изменения поля ввода количества

* **Использование**: обработка изменений в поле ввода количества

`replaceItemWithVariant`

* **Тип**: `(variantId: string) => Promise<{ success: boolean }>`

* **Описание**: функция замены позиции другим вариантом

* **Использование**: обработка переключения вариантов

`isLoading`

* **Тип**: `boolean`

* **Описание**: состояние загрузки для операций с корзиной

* **Использование**: отображение индикаторов загрузки

`loadingOperation`

* **Тип**: `'increase' | 'decrease' | 'inputChange' | 'remove' | 'subscription' | undefined`

* **Описание**: конкретная операция, выполняющаяся в данный момент

* **Использование**: отображение состояний загрузки для конкретных операций

`setLoadingOperation`

* **Тип**: `(op: "increase" | "decrease" | "inputChange" | "remove" | "subscription" | undefined) => void`

* **Описание**: функция установки состояния операции загрузки

* **Использование**: управление состояниями загрузки для разных операций

`rawItem`

* **Тип**: `CartItem` (см. тип `CartItem` [ниже](#cartitem-object-properties))

* **Описание**: необработанные данные позиции корзины со всей информацией

<div id="available-props-variant-template">
  ### **Доступные props — Variant template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-item-variant-line.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=c1220e3bf77d9b091c82d0f0b7709034" alt="Строка варианта позиции корзины с выбранным размером Medium" width="150" data-path="images/upcart/custom-template-cart-item-variant-line.png" />

`item`

* **Тип**: `CartItem` (см. тип `CartItem` [ниже](#cartitem-object-properties))

* **Описание**: необработанные данные позиции корзины с информацией о варианте

* **Использование**: доступ к деталям варианта из позиции корзины

<div id="available-props-properties-template">
  ### **Доступные props — Properties template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-item-property-line.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=2ce7abe36cf542d62e9fc7e2092e7009" alt="Строка свойства позиции корзины с заметкой подарочного сообщения" width="220" data-path="images/upcart/custom-template-cart-item-property-line.png" />

`productProperties`

* **Тип**: `{ key: string; value: string; isUrl?: boolean; }[]`

* **Описание**: массив свойств товара (пользовательские поля, свойства позиции заказа)

`subscriptionLabel`

* **Тип**: `string | undefined`

* **Описание**: подпись для информации о подписке

<div id="available-props-bundle-template">
  ### **Доступные props — Bundle template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-expanded-bundle-components.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=9a04c17667ea4af9cef303b96c079f37" alt="Развёрнутый комплект с тремя входящими в него компонентами и их вариантами" width="200" data-path="images/upcart/custom-template-expanded-bundle-components.png" />

`getSizedImageUrl`

* **Тип**: `getSizedImageUrl: ({ src, width, height }: SizedImageParams) => string`

* **Описание**: вспомогательная функция для получения URL изображений нужного размера

`item`

* **Тип**:

  ```
  {  
    itemComponents: {  
      quantity: number;  
      image: {  
        url: string;  
        height: number | null;  
        width: number | null;  
        alt: string;  
      };  
      product: {  
        title: string;  
        has_only_default_variant: boolean;  
      };  
      variantTitle: string;  
    }[];  
    variantTitle: string | undefined;  
    hasComponents: boolean;  
  }
  ```

* **Описание**: информация о позиции-комплекте, включая компоненты. `itemComponents` — массив объектов компонентов; переберите его через map, чтобы отрендерить каждый компонент комплекта.

`showDetailsText`

* **Тип**: `string | undefined`

* **Описание**: текст действия «показать детали»

* **Использование**: отображение текста кнопки разворачивания

`hideDetailsText`

* **Тип**: `string | undefined`

* **Описание**: текст действия «скрыть детали»

`isExpanded`

* **Тип**: `boolean`

* **Описание**: развёрнуты ли детали комплекта

`toggleCollapsible`

* **Тип**: `() => void`

* **Описание**: функция переключения видимости деталей комплекта

* **Использование**: обработка действий разворачивания/сворачивания

`chevronDownIconComponent`

* **Тип**: `React.ReactElement`

* **Описание**: предварительно отрендеренный значок-шеврон для разворачивания/сворачивания

* **Использование**: отображение единообразного индикатора разворачивания/сворачивания

<div id="available-props-price-template">
  ### **Доступные props — Price template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-price-strikethrough.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=34deca3e39b1aabbafae6ed19d209450" alt="Цена в корзине с зачёркнутой первоначальной ценой, ценой со скидкой и экономией" width="250" data-path="images/upcart/custom-template-cart-price-strikethrough.png" />

`compareAtPrice`

* **Тип**: `string | undefined`

* **Описание**: отформатированная цена до скидки (первоначальная цена)

* **Использование**: отображение первоначальной цены для товаров со скидкой

`price`

* **Тип**: `string`

* **Описание**: отформатированная текущая цена

* **Использование**: отображение текущей цены позиции

`savings`

* **Тип**: `string | undefined`

* **Описание**: отформатированная сумма экономии

* **Использование**: отображение того, сколько экономит покупатель

<div id="cartitem-object-properties">
  ### **Свойства объекта CartItem**
</div>

Объект `CartItem` содержит всю подробную информацию о позиции корзины. Этот объект доступен как props.rawItem в шаблоне Product Tile и props.item в шаблоне Variant.

<div id="core-identification">
  #### **Основная идентификация**
</div>

* `key (string)` — уникальный идентификатор этой позиции корзины.

* `id (number)` — ID варианта (устаревшее поле, используйте variant\_id)

* `variant_id (number)` — ID варианта Shopify для этой позиции

* `product_id (number)` — ID товара Shopify

* `lineIdxFrom1 (number)` — индекс этой позиции (начиная с 1) в исходной корзине до изменений

<div id="product-information">
  #### **Информация о товаре**
</div>

* `title (string)` — название позиции (обычно название варианта)

* `product_title (string)` — основное название товара

* `handle (string)` — URL-идентификатор товара (например, "camp-stool")

* `vendor (string)` — производитель/бренд товара

* `product_type (string)` — категория/тип товара для целей налогообложения

* `sku (string)` — идентификатор SKU (складская единица)

* `product_description (string)` — полное описание товара

* `product_has_only_default_variant (boolean)` — есть ли у товара только один вариант

<div id="pricing-all-prices-in-cents">
  #### **Цены (все цены в центах)**
</div>

* `quantity (number)` — количество данной позиции в корзине

* `price (number)` — цена за единицу до скидок

* `original_price (number)` — то же, что price

* `discounted_price (number)` — цена за единицу после скидок на уровне товара

* `compare_at_price (number | null)` — цена до скидки (MSRP). Примечание: это поле добавляется Upcart, а не предоставляется cart API Shopify

* `final_line_price (number)` — общая цена после скидок на уровне товара (quantity × discounted\_price)

* `original_line_price (number)` — общая цена до скидок (quantity × price)

* `line_price (number)` — общая цена после всех скидок

* `final_price (number)` — **устарело** — цена за единицу после скидок на товар (не учитывает количество)

* `total_discount (number)` — то же, что line\_level\_total\_discount

* `line_level_total_discount (number)` — общая сумма скидки, применённой к этой позиции

<div id="media-urls">
  #### **Медиа и URL**
</div>

* `image (string)` — URL основного изображения товара

* `url (string)` — относительный URL страницы товара (например, "/products/camp-stool?variant=42789611372803")

* `featured_image (object | null)` — детали избранного изображения:

  * `alt (string)` — альтернативный текст изображения
  * `aspect_ratio (number)` — соотношение сторон изображения
  * `height (number)` — высота изображения в пикселях
  * `url (string)` — URL изображения
  * `width (number)` — ширина изображения в пикселях

<div id="variants-options">
  #### **Варианты и опции**
</div>

* `variant_title (string | null)` — название варианта (например, "Large / Red")

* `variant_options (string[])` — массив значений опций варианта

* `options_with_values (Array)` — подробная информация об опциях:

  * `name (string)` — название опции (например, "Size")
  * `value (string)` — значение опции (например, "Large")

* `untranslated_product_title (string | undefined)` — исходное название товара до перевода (только в ответах на изменение корзины)

* `untranslated_variant_title (string | undefined)` — исходное название варианта до перевода (только в ответах на изменение корзины)

<div id="custom-properties-metadata">
  #### **Пользовательские свойства и метаданные**
</div>

* `properties (Record<string, any> | null)` — пользовательские свойства позиции или `null`, если у позиции их нет — проверяйте перед чтением ключа. Свойства, ключи которых начинаются с `__`, всегда скрыты от покупателей; ключи, начинающиеся с одиночного `_`, тоже скрываются, если включена настройка корзины **Hide properties starting with single underscore "\_"**.

* `gift_card (boolean)` — является ли эта позиция подарочной картой

* `taxable (boolean)` — облагается ли эта позиция налогом

* `requires_shipping (boolean)` — требует ли эта позиция доставки

* `grams (number)` — вес позиции в граммах

<div id="discounts-promotions">
  #### **Скидки и акции**
</div>

* `discounts (Array)` — упрощённая информация о скидках:

  * `amount (number)` — сумма скидки в центах
  * `title (string)` — название скидки

* `line_level_discount_allocations (Array)` — подробная информация о распределении скидок:

  * `amount (number)` — сумма скидки в центах
  * `discount_application (object)` — полные детали применения скидки:

    * `allocation_method (string)` — способ распределения скидки
    * `created_at (string)` — когда была создана скидка
    * `description (string | null)` — описание скидки
    * `key (string)` — ключевой идентификатор скидки
    * `target_selection (string)` — на что нацелена скидка
    * `target_type (string)` — тип цели
    * `title (string)` — название скидки
    * `total_allocated_amount (number)` — общая распределённая сумма
    * `type ('discount_code' | '')` — тип скидки (пустая строка для автоматических скидок)
    * `value (string)` — значение скидки
    * `value_type (string)` — способ применения значения

<div id="bundle-products">
  #### **Товары-комплекты**
</div>

* `has_components (boolean | undefined)` — является ли эта позиция комплектом, содержащим другие товары (только в ответах GET корзины)

* `item_components (Array | null | undefined)` — детали компонентов комплекта:

  * `quantity (number)` — количество данного компонента
  * `image (object)` — изображение компонента:

    * `url (string)` — URL изображения
    * `height (number | null)` — высота изображения
    * `width (number | null)` — ширина изображения
    * `alt (string)` — альтернативный текст

* `product (object)` — информация о товаре-компоненте:

  * `title (string)` — название товара
  * `has_only_default_variant (boolean)` — есть ли у товара только вариант по умолчанию

* `variantTitle (string)` — название варианта компонента

<div id="business-rules">
  #### **Бизнес-правила**
</div>

* `quantity_rule (object | undefined)` — ограничения количества (только в ответах GET корзины):

  * `min (number)` — минимально допустимое количество
  * `max (number | null)` — максимально допустимое количество (null = без ограничения)
  * `increment (number)` — шаг изменения количества

<div id="subscription-information">
  #### **Информация о подписке**
</div>

* `selling_plan_allocation (object | undefined)` — детали подписки/плана продаж:

  * `price (number)` — цена подписки в центах
  * `compare_at_price (number | null)` — цена подписки до скидки
  * `per_delivery_price (number)` — цена за доставку
  * `selling_plan (object)` — детали плана продаж:

    * `id (number)` — ID плана продаж
    * `name (string)` — название плана
    * `description (string)` — описание плана
    * `options (Array)` — опции плана:

      * `name (string)` — название опции
      * `position (number)` — позиция опции
      * `value (string)` — значение опции
    * `recurring_deliveries (boolean)` — предусматривает ли план регулярные доставки

<div id="integration-metadata">
  #### **Метаданные интеграций**
</div>

* `__appIntegrated (object | undefined)` — данные интеграции стороннего приложения:

  * `app ('stay.ai')` — идентификатор интегрированного приложения
  * `bundleRole ('parent' | 'child')` — роль в структуре комплекта

<div id="upsells">
  ## Апселлы
</div>

Модуль Upsells позволяет настроить отображение товаров-апселлов с собственным дизайном, сохраняя основную функциональность электронной коммерции, такую как выбор варианта, добавление в корзину и отображение информации о товаре.

<div id="available-props-upsell-tile-template">
  ### **Доступные props — Upsell tile template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-upsell-tile-product-sale.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=276d261e795de83ca0882f4cd713ec61" alt="Плитка апселла с товаром по акционной цене, выпадающим списком вариантов и кнопкой Add" width="400" data-path="images/upcart/custom-template-upsell-tile-product-sale.png" />

`itemUrl`

* **Тип**: `string`

* **Описание**: URL страницы товара

* **Использование**: создание ссылок на страницу товара для улучшенной навигации пользователей

```
<a href={props.itemUrl} className="product-link">  
  <img src={props.imageUrl} alt={props.altText} />  
</a>
```

`imageUrl`

* **Тип**: `string | undefined`

* **Описание**: URL изображения товара

* **Использование**: отображение изображений товаров в пользовательских реализациях апселлов

* **Резервный вариант**: корректно обрабатывайте значения undefined с помощью изображений-заглушек

`description`

* **Тип**: `string`

* **Описание**: описание товара

* **Использование**: отображение описания товара в пользовательских реализациях апселлов

`altText`

* **Тип**: `string`

* **Описание**: альтернативный текст изображения товара для доступности

* **Использование**: поддержка программ чтения с экрана и улучшение соответствия требованиям доступности

```
<img   
  src={props.imageUrl}   
  alt={props.altText}  
  className="product-image"  
/>
```

`productId`

* **Тип**: `string`

* **Описание**: уникальный идентификатор товара

* **Использование**: отслеживание товаров, аналитика или использование в функциональности добавления в корзину

`productTitle`

* **Тип**: `string`

* **Описание**: название товара

* **Использование**: отображение названия товара в пользовательских реализациях апселлов

```
<div>  
  <h3>{props.productTitle}</h3>  
</div>
```

`oldPrice` и `newPrice`

* **Тип**: `string | null` (oldPrice), `string` (newPrice)

* **Описание**: отформатированные цена до скидки и текущая цена

* **Использование**: отображение информации о ценах с индикаторами распродажи

`isSingleVariant`

* **Тип**: `boolean`

* **Описание**: указывает, есть ли у товара только один вариант

* **Использование**: условный рендеринг элементов UI выбора варианта

`productOptions`

* **Тип**: `{ name: string; position: 1 | 2 | 3; values: string[]; }[]`

* **Описание**: полная конфигурация опций товара, включая все доступные варианты выбора

* **Использование**: доступ к подробной информации об опциях товара для продвинутого UI выбора вариантов

`variantOptions`

* **Тип**: `{ label: string; value: string }[]`

* **Описание**: доступные варианты товара

* **Использование**: создание выпадающих списков или кнопок выбора варианта

* **Структура**: каждая опция содержит отображаемую подпись и уникальный идентификатор значения

`selectedVariantId` и `selectedVariantLabel`

* **Тип**: string (selectedVariantId), string | undefined (selectedVariantLabel)

* **Описание**: ID выбранного в данный момент варианта и его отображаемая подпись

* **Использование**: отслеживание и отображение информации о выбранном варианте

`onVariantChange`

* **Тип**: `(variantId: string) => void`

* **Описание**: функция обработки изменения выбора варианта

* **Использование**: обновление выбранного варианта при выборе пользователем

`onAddClick`

* **Тип**: `(productId: string, variantId?: string) => void`

* **Описание**: функция обработки добавления товара в корзину

* **Использование**: реализация функциональности добавления в корзину с корректной идентификацией товара и варианта

```
<button   
  onClick={() => props.onAddClick(props.productId, props.selectedVariantId)}  
  disabled={props.addLoading}  
>  
  {props.addLoading ? 'Adding...' : props.addButtonText}  
</button>
```

`rating` и `reviewCount`

* **Тип**: `number | undefined` (rating), `string | undefined` (reviewCount)

* **Описание**: рейтинг товара и отформатированный текст количества отзывов

* **Использование**: отображение социального доказательства и индикаторов качества товара

`addLoading` и `addButtonText`

* **Тип**: `boolean` (addLoading), `string` (addButtonText)

* **Описание**: состояние загрузки действия добавления в корзину и текст кнопки

* **Использование**: обратная связь для пользователя во время операций с корзиной и настройка текста кнопки

`cartItemsCount`

* **Тип**: `number`

* **Описание**: текущее количество товаров в корзине

* **Использование**: отображение статуса корзины или реализация логики на основе корзины

<div id="additional-notes">
  ## Дополнительные заметки
</div>

Модуль Notes позволяет настроить функциональность заметок корзины с собственным дизайном, сохраняя основные возможности заметок, такие как разворачиваемые разделы, обработка текстового ввода и состояния загрузки.

<div id="available-props-full-template-5">
  ### **Доступные props — Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-notes-section-expandable.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=ce3f2a79f875029e6358c2227cd024d9" alt="Раздел заметок корзины с разворачиваемым текстовым полем для особых указаний" width="400" data-path="images/upcart/custom-template-cart-notes-section-expandable.png" />

`cartNote`

* **Тип**: `string`

* **Описание**: текущее содержимое заметки корзины, введённое покупателем

* **Использование**: отображение и управление текстом заметки корзины в пользовательских реализациях

```
<textarea  
  value={props.cartNote}  
  ...  
/>
```

`notesPlaceholder`

* **Тип**: `string`

* **Описание**: текст-заполнитель для поля ввода заметок

* **Использование**: подсказка покупателям о том, что указывать в заметках

```
<textarea  
  placeholder={props.notesPlaceholder}  
  ...  
/>
```

`notesTitle`

* **Тип**: `string`

* **Описание**: текст заголовка раздела заметок

* **Использование**: отображение заголовка раздела в пользовательских реализациях заметок

```
<h3 className="notes-title" dangerouslySetInnerHTML={{ __html: props.notesTitle }} />
```

`chevronDownIconComponent`

* **Тип**: `React.ReactElement`

* **Описание**: предварительно отрендеренный компонент значка-шеврона для функциональности разворачивания/сворачивания

* **Использование**: отображение единообразных индикаторов разворачивания/сворачивания в пользовательских реализациях

`loadingIndicatorComponent`

* **Тип**: `React.ReactElement | null`

* **Описание**: предварительно отрендеренный компонент индикатора загрузки для асинхронных операций

* **Использование**: отображение состояний загрузки во время операций сохранения заметки

`handleCartNoteChange`

* **Тип**: `(newCartNote: string) => void`

* **Описание**: функция обработки изменений содержимого заметки корзины

* **Использование**: обновление заметки корзины при изменении текста пользователем

`isExpanded`

* **Тип**: `boolean`

* **Описание**: указывает, развёрнут ли в данный момент раздел заметок

* **Использование**: управление видимостью области ввода заметок

`toggleCollapsible`

* **Тип**: `() => void`

* **Описание**: функция переключения развёрнутого/свёрнутого состояния раздела заметок

* **Использование**: привяжите к кнопкам или интерактивным элементам для управления видимостью раздела

***

<div id="footer-section">
  ## Раздел Footer
</div>

<div id="add-ons">
  ## Дополнения
</div>

Модуль Addons позволяет настроить отображение товаров-дополнений с собственным дизайном, сохраняя основную функциональность электронной коммерции, такую как отображение информации о товаре, ценообразование, переключатели и форматирование валюты.

<div id="available-props-full-template-6">
  ### **Доступные props — Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-add-on-product-row-gift-card.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=8a705eec52fbe1e24420467f92978829" alt="Строка товара-дополнения с подарочной картой, ценой и переключателем включения" width="400" data-path="images/upcart/custom-template-add-on-product-row-gift-card.png" />

`addonProduct`

* **Тип**:

  ```
  {  
    product: {  
      id: number;  
      title: string;  
      description: string;  
    };  
    variant: {  
      id: number;  
      price: number;  
      compare_at_price: number | null;  
    };  
    image: {  
      src: string;  
      alt: string;  
    };  
  }
  ```

* **Описание**: полная информация о товаре-дополнении, включая детали товара, цены варианта и данные изображения

* **Использование**: доступ ко всей информации о товаре, необходимой для отображения товаров-дополнений

* **Структура**: содержит вложенные объекты product, variant и image с исчерпывающими данными о товаре

  * **Свойства объекта Product** `addonProduct.product`

    * **id**: уникальный числовой идентификатор товара
    * **title**: отображаемое название товара-дополнения
    * **description**: HTML-описание товара
  * **Свойства объекта Variant**

    * **id**: уникальный числовой идентификатор варианта
    * **price**: текущая цена в центах
    * **compare\_at\_price**: первоначальная цена в центах (null, если цены для сравнения нет)
  * **Свойства объекта Image**

    * **src**: URL изображения товара
    * **alt**: альтернативный текст изображения (для доступности)

`toggle`

* **Тип**:

  ```
  {  
    state: 'enabled' | 'disabled' | 'loading';  
    handleEnable: () => void;  
    handleDisable: () => void;  
  } | null
  ```

* **Описание**: состояние переключателя и обработчики для включения/отключения дополнения

* **Использование**: реализация интерактивного переключателя для выбора дополнения

* **Состояния**: три возможных состояния — enabled, disabled и loading

* **Обработчики**: отдельные функции для действий включения и отключения

`moneyFormat`

* **Тип**: `string`

* **Описание**: строка формата валюты, используемая для форматирования цен

* **Использование**: передавайте в функцию formatMoney для единообразного отображения валюты

`formatMoney`

* **Тип**:

  ```
  (options: {  
    cents: string | number;  
    format?: string;  
    shouldRemoveHTML?: boolean;  
  }) => string
  ```

* **Описание**: вспомогательная функция для форматирования денежных значений

* **Использование**: единообразное форматирование цен в соответствии с настройками валюты магазина

* **Параметры**: принимает значение в центах, необязательную строку формата и опцию удаления HTML

<div id="discount-codes">
  ## Коды скидок
</div>

Модуль Discount Code позволяет настроить функциональность ввода кода скидки с собственным дизайном, сохраняя основные возможности электронной коммерции, такие как валидация кода, отправка формы и обратная связь для пользователя.

<div id="available-props-full-template-7">
  ### **Доступные props — Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-discount-code-input-field.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=9e8eb5e08805c18b26a3338707a9909a" alt="Поле ввода кода скидки с кнопкой Apply" width="400" data-path="images/upcart/custom-template-discount-code-input-field.png" />

`indicator`

* **Тип**: `'validating' | 'invalid' | 'none'`

* **Описание**: текущее состояние валидации поля ввода кода скидки

* **Использование**: отображение соответствующей обратной связи в UI в зависимости от статуса валидации

* **Состояния**:

  * `validating`: код обрабатывается/проверяется
  * `invalid`: валидация кода не прошла
  * `none`: нет состояния валидации (по умолчанию/ожидание)

`discountCodeInput`

* **Тип**: `string`

* **Описание**: текущее значение поля ввода кода скидки

* **Использование**: отображение и управление текстом кода скидки, введённым пользователем

```
<input  
  type="text"  
  value={props.discountCodeInput}  
  onChange={(e) => props.setDiscountCodeInput(e.target.value)}  
  ...  
/>
```

`discountCodePlaceholder`

* **Тип**: `string`

* **Описание**: текст-заполнитель для поля ввода кода скидки

* **Использование**: подсказка пользователям о том, что вводить в поле

`discountCodeButtonText`

* **Тип**: `string`

* **Описание**: текст, отображаемый на кнопке применения/отправки

* **Использование**: настройка текста кнопки отправки кода скидки

`setDiscountCodeInput`

* **Тип**: `(value: string | ((prev: string) => string)) => void`

* **Описание**: функция обновления значения поля ввода кода скидки

* **Использование**: обработка изменений пользовательского ввода в поле кода скидки

`handleSubmit`

* **Тип**: `(e: React.FormEvent<HTMLFormElement>) => void`

* **Описание**: функция обработки отправки формы для применения кода скидки

* **Использование**: обработка валидации и применения кода скидки

* **Событие**: обрабатывает события отправки формы

```
<form onSubmit={props.handleSubmit} >  
  <div className="input-group">  
    <input  
      type="text"  
      value={props.discountCodeInput}  
      onChange={(e) => props.setDiscountCodeInput(e.target.value)}  
      placeholder={props.discountCodePlaceholder}  
    />   
    <button   
      type="submit"  
      disabled={props.indicator === 'validating' || !props.discountCodeInput.trim()}  
    >  
      {props.discountCodeButtonText}  
    </button>  
  </div>  
</form>
```

<div id="cart-summary">
  ## Сводка корзины
</div>

Модуль Cart Summary позволяет настроить отображение сводки корзины и скидок с собственным дизайном, сохраняя основную функциональность электронной коммерции, такую как управление скидками, расчёт экономии и прозрачность цен.

<div id="available-props-full-template-8">
  ### **Доступные props — Full template**
</div>

<img src="https://mintcdn.com/aftersell/uxKAdY-e0h16xa48/images/upcart/custom-template-cart-summary-discount-row.png?fit=max&auto=format&n=uxKAdY-e0h16xa48&q=85&s=492e00824117bf0b93bf0c3a1402050f" alt="Строка скидки в сводке корзины с применённым кодом скидки и суммой" width="400" data-path="images/upcart/custom-template-cart-summary-discount-row.png" />

`totalSavingsText`

* **Тип**: `string`

* **Описание**: текстовая подпись раздела общей экономии

* **Использование**: отображение подписи экономии в пользовательских реализациях сводки корзины

`discountApplications`

* **Тип**:

  ```
  {  
    key: string;  
    title: string;  
    type: 'discount_code' | '';  
  }[]
  ```

* **Описание**: массив применённых кодов скидок и автоматических скидок

* **Использование**: отображение всех активных скидок с их названиями и типами

* **Структура**: каждая скидка содержит уникальный ключ, отображаемое название и идентификатор типа

`cartTotalDiscount`

* **Тип**: `number`

* **Описание**: общая сумма скидки в центах

* **Использование**: доступ к необработанному значению скидки для расчётов или пользовательского форматирования

`showCartTotalDiscount`

* **Тип**: `boolean`

* **Описание**: указывает, должна ли отображаться общая скидка. Помечен как устаревший в пользу `showTotalSavings`, но см. примечание ниже — внутри пользовательского шаблона это по-прежнему тот prop, который у вас есть.

* **Использование**: условный рендеринг информации о скидке в зависимости от настроек

`formattedCartTotalDiscount`

* **Тип**: `string`

* **Описание**: предварительно отформатированная HTML-строка общей суммы скидки. Помечен как устаревший в пользу `formattedTotalSavings`, но см. примечание ниже.

* **Использование**: отображение корректно отформатированной суммы скидки с символами валюты

<Warning>
  **`showTotalSavings` и `formattedTotalSavings` недоступны внутри пользовательского шаблона.** Они существуют во внутреннем контексте модуля, но шаблону Cart summary передаются только `showCartTotalDiscount` и `formattedCartTotalDiscount` — чтение новой пары возвращает `undefined`. Используйте два указанных выше и учтите, что они показывают только сумму скидки; они не следуют настройке **Show compare-at price savings in footer total**.
</Warning>

`isRemovingDiscount`

* **Тип**: `boolean`

* **Описание**: указывает, выполняется ли операция удаления скидки

* **Использование**: отображение состояний загрузки во время удаления скидки

`handleRemoveDiscount`

* **Тип**: `() => Promise<void>`

* **Описание**: функция обработки удаления кода скидки

* **Использование**: удаление применённых кодов скидок из корзины

`totalCompareAtPrice`

* **Тип**: `number`

* **Описание**: суммарная цена до скидки (по всем товарам в корзине)

* **Использование**: расчёт и отображение экономии или информации о первоначальных ценах

`totalAfterAllDiscounts`

* **Тип**: `number`

* **Описание**: итоговая сумма корзины в центах после применения всех скидок

* **Использование**: отображение итоговой цены, которую заплатят покупатели

`originalTotalPrice`

* **Тип**: `number`

* **Описание**: первоначальная сумма корзины в центах до любых скидок

* **Использование**: отображение первоначальных цен для прозрачности и расчёта экономии

`cartItemCount`

* **Тип**: `number`

* **Описание**: общее количество товаров в корзине

* **Использование**: отображение информации о количестве товаров в сводках корзины

<div id="trust-badges">
  ## Значки доверия
</div>

Модуль Trust Badges позволяет настроить отображение значков доверия с собственным дизайном, сохраняя основную функциональность укрепления доверия, такую как условная видимость значков и корректная обработка изображений.

<div id="available-props-full-template-9">
  ### **Доступные props — Full template**
</div>

`showBadge`

* **Тип**: `boolean`

* **Описание**: указывает, должен ли отображаться значок доверия

* **Использование**: управление видимостью значков доверия в зависимости от настроек модуля

`badgeUrl`

* **Тип**: `string`

* **Описание**: URL изображения значка доверия для отображения

* **Использование**: URL-источник изображения значка доверия в пользовательских реализациях
