

{% doc %}
  Renders product recommendations.
  {section.id} - identifies the parent section for the Section Rendering API

  https://shopify.dev/docs/api/section-rendering-api
{% enddoc %}

<script
  src="{{ 'product-recommendations.js' | asset_url }}"
  type="module"
></script>

{% stylesheet %}
  .block-resource-list {
    display: flex;
    flex-direction: column;
    row-gap: var(--gap);
    min-width: 0;
    min-height: 0;
  }

  .resource-list--carousel-mobile {
    display: block;

    @media screen and (width >= 750px) {
      display: none;
    }
  }

  .resource-list {
    --resource-list-mobile-gap-max: 12px;
    --resource-list-column-gap: min(var(--resource-list-column-gap-desktop), var(--resource-list-mobile-gap-max));
    --resource-list-row-gap: min(var(--resource-list-row-gap-desktop), var(--resource-list-mobile-gap-max));

    width: 100%;

    @media screen and (width >= 750px) {
      --resource-list-column-gap: var(--resource-list-column-gap-desktop);
      --resource-list-row-gap: var(--resource-list-row-gap-desktop);
    }
  }

  .block-resource-list {
    container-type: inline-size;
    container-name: resource-list;
  }

  .resource-list--grid {
    display: grid;
    column-gap: var(--resource-list-column-gap);
    row-gap: var(--resource-list-row-gap);

    @container resource-list (width < 750px) {
      grid-template-columns: var(--resource-list-columns-mobile);
    }

    @container resource-list (width >= 750px) {
      grid-template-columns: repeat(var(--resource-list-columns-per-row), 1fr);

      &:has(.resource-list__item:first-child:nth-last-child(n + 9)) {
        --resource-list-columns-per-row: 5;
      }

      &:has(.resource-list__item:first-child:nth-last-child(n + 7):nth-last-child(-n + 8)) {
        --resource-list-columns-per-row: 4;
      }

      &:has(.resource-list__item:first-child:nth-last-child(6)) {
        --resource-list-columns-per-row: 3;
      }

      &:has(.resource-list__item:first-child:nth-last-child(5)) {
        --resource-list-columns-per-row: 5;
      }

      &:has(.resource-list__item:first-child:nth-last-child(-n + 4)) {
        --resource-list-columns-per-row: 4;
      }
    }

    @container resource-list (width >= 1200px) {
      &:has(.resource-list__item:first-child:nth-last-child(6)) {
        --resource-list-columns-per-row: 6;
      }
    }
  }

  .resource-list__item {
    color: var(--color-foreground);
    text-decoration: none;
  }

  .product-recommendations-wrapper {
    width: 100%;
  }

  .product-recommendations-wrapper:has(product-recommendations[data-shopify-editor-preview]) {
    width: 100vw;
  }

  .product-recommendations {
    display: block;
  }

  .product-recommendations__skeleton-item {
    aspect-ratio: 3 / 4;
    background-color: var(--color-foreground);
    opacity: var(--skeleton-opacity);
    border-radius: 4px;
  }
{% endstylesheet %}

{% liquid
  case block.settings.layout_type
    when 'grid'
      assign classes = 'resource-list--grid'
    when 'carousel'
      assign classes = 'resource-list--carousel'
  endcase
%}

{% comment %}
  [data-section-id] {section.id} - used to fetch the product recommendations from the Section Rendering API
{% endcomment %}

<product-recommendations
  id="product-recommendations-{{ block.id }}"
  class="product-recommendations"
  data-url="{{ routes.product_recommendations_url }}?limit={{ block.settings.max_products }}"
  data-section-id="{{ section.id }}"
  data-product-id="{{ block.settings.product.id }}"
  data-intent="{{ block.settings.recommendation_type }}"
  data-recommendations-performed="{{ recommendations.performed }}"
  {% if request.visual_preview_mode %}
    data-shopify-editor-preview
  {% endif %}
  data-testid="product-recommendations-block"
  {{ block.shopify_attributes }}
>
  <div
    class="
      color-{{ section.settings.color_scheme }}
      block-resource-list
      spacing-style
      gap-style
    "
    style="
      {%  render 'spacing-style', settings: block.settings %}
      {%  render 'gap-style', value: block.settings.gap %}
      --resource-list-column-gap-desktop: {{ block.settings.columns_gap }}px;
      --resource-list-row-gap-desktop: {{ block.settings.rows_gap }}px;
      --resource-list-columns-mobile: repeat(auto-fill, minmax(9.25rem, 1fr));'
    "
  >
    <div class="section-resource-list__content">
      {% content_for 'blocks' %}
    </div>

    {%- if recommendations.performed or block.settings.product == blank -%}
      {% liquid
        assign products = recommendations.products

        if block.settings.product == blank
          if request.design_mode or request.visual_preview_mode
            # Onboarding mode: Show placeholder products
            for i in (1..block.settings.max_products)
              assign products = products | append: ', '
              assign products = products | split: ','
            endfor
          endif
        elsif recommendations.performed and recommendations.products_count == 0
          # No recommendations found, pull from catalog
          if block.settings.recommendation_type == 'related'
            assign products = collections.all.products | reject: 'id', block.settings.product.id
          elsif block.settings.recommendation_type == 'complementary'
            # Do not recommend the All collection as complementary products
            assign products = null
          endif
        else
          assign products = recommendations.products
        endif
      %}
      {% capture list_items %}
        {% for product in products limit: block.settings.max_products %}
          <div class="resource-list__item">
            {% content_for 'block',
              type: 'product-card',
              id: 'static-product-card',
              closest.product: product
            %}
          </div>
          {% if block.settings.layout_type == 'carousel' or block.settings.carousel_on_mobile %}
            {% unless forloop.last %}
              <!--@list/split-->
            {% endunless %}
          {% endif %}
        {% endfor %}
      {% endcapture %}

      {% liquid
        # Create an array from the list items to be used in the carousel
        assign slide_content = list_items | strip
        assign slides = slide_content | split: '<!--@list/split-->'
      %}

      <div
        class="
          resource-list resource-list--{{ block.id }}
          {% if block.settings.carousel_on_mobile and block.settings.layout_type != 'carousel' %}
            hidden--mobile
          {% endif %}
          {{ classes }}
        "
        {% if block.settings.layout_type == 'grid' %}
          data-testid="resource-list-grid"
        {% endif %}
        data-has-recommendations="{% if products.size > 0 %}true{% else %}false{% endif %}"
      >
        {% case block.settings.layout_type %}
          {% when 'grid' %}
            {{ list_items }}
          {% when 'carousel' %}
            {% render 'resource-list-carousel',
              ref: 'resourceListCarousel',
              slides: slides,
              slide_count: recommendations.products.size,
              settings: block.settings
            %}
        {% endcase %}
      </div>

      {% if block.settings.carousel_on_mobile and block.settings.layout_type != 'carousel' %}
        {% liquid
          assign mobile_carousel_gap = block.settings.columns_gap
        %}
        <div
          class="
            resource-list resource-list--{{ block.id }}
            hidden--desktop
            force-full-width
          "
          style="--resource-list-gap: {{ mobile_carousel_gap }}px;"
        >
          {% render 'resource-list-carousel',
            ref: 'resourceListCarouselMobile',
            slides: slides,
            slide_count: recommendations.products.size,
            settings: block.settings
          %}
        </div>
      {% endif %}
    {%- else -%}
      <div class="resource-list resource-list--grid">
        {% for i in (1..2) %}
          <div
            class="resource-list__item product-recommendations__skeleton-item"
            aria-label="{{ 'accessibility.loading_product_recommendations' | t }}"
          ></div>
        {% endfor %}
      </div>
    {%- endif -%}
  </div>
</product-recommendations>

{% schema %}
{
  "name": "t:names.product_recommendations",
  "class": "product-recommendations-wrapper",
  "blocks": [
    {
      "type": "@theme"
    },
    {
      "type": "@app"
    }
  ],
  "settings": [
    {
      "type": "product",
      "id": "product",
      "label": "t:settings.product"
    },
    {
      "type": "select",
      "id": "recommendation_type",
      "label": "t:settings.type",
      "options": [
        {
          "value": "related",
          "label": "t:options.related"
        },
        {
          "value": "complementary",
          "label": "t:options.complementary"
        }
      ],
      "default": "related"
    },
    {
      "type": "paragraph",
      "content": "t:content.complementary_products"
    },
    {
      "type": "header",
      "content": "t:content.cards_layout"
    },
    {
      "type": "select",
      "id": "layout_type",
      "label": "t:settings.layout_style",
      "options": [
        {
          "value": "grid",
          "label": "t:options.grid"
        },
        {
          "value": "carousel",
          "label": "t:options.carousel"
        }
      ],
      "default": "grid"
    },
    {
      "type": "checkbox",
      "id": "carousel_on_mobile",
      "label": "t:settings.carousel_on_mobile",
      "default": true,
      "visible_if": "{{ block.settings.layout_type == 'grid' }}"
    },
    {
      "type": "range",
      "id": "max_products",
      "label": "t:settings.product_count",
      "min": 2,
      "max": 10,
      "step": 1,
      "default": 4
    },
    {
      "type": "range",
      "id": "columns_gap",
      "label": "t:settings.horizontal_gap",
      "min": 0,
      "max": 100,
      "step": 1,
      "unit": "px",
      "default": 16,
      "visible_if": "{{ block.settings.layout_type == 'grid' or block.settings.layout_type == 'carousel' }}"
    },
    {
      "type": "range",
      "id": "rows_gap",
      "label": "t:settings.vertical_gap",
      "min": 0,
      "max": 100,
      "step": 1,
      "unit": "px",
      "default": 16,
      "visible_if": "{{ block.settings.layout_type == 'grid' }}"
    },
    {
      "type": "header",
      "content": "t:content.carousel_navigation",
      "visible_if": "{{ block.settings.layout_type == 'carousel' or block.settings.carousel_on_mobile == true }}"
    },
    {
      "type": "select",
      "id": "icons_style",
      "label": "t:settings.icon",
      "options": [
        {
          "value": "arrow",
          "label": "t:options.arrows"
        },
        {
          "value": "chevron",
          "label": "t:options.chevrons"
        },
        {
          "value": "arrows_large",
          "label": "t:options.arrows_large"
        },
        {
          "value": "chevron_large",
          "label": "t:options.chevron_large"
        },
        {
          "value": "none",
          "label": "t:options.none"
        }
      ],
      "default": "arrow",
      "visible_if": "{{ block.settings.layout_type == 'carousel' or block.settings.carousel_on_mobile == true }}"
    },
    {
      "type": "select",
      "id": "icons_shape",
      "label": "t:settings.icon_background",
      "options": [
        {
          "value": "none",
          "label": "t:options.none"
        },
        {
          "value": "circle",
          "label": "t:options.circle"
        },
        {
          "value": "square",
          "label": "t:options.square"
        }
      ],
      "default": "none",
      "visible_if": "{{ block.settings.icons_style != 'none' and block.settings.layout_type == 'carousel' or block.settings.carousel_on_mobile == true }}"
    },
    {
      "type": "header",
      "content": "t:content.layout"
    },
    {
      "type": "range",
      "id": "gap",
      "label": "t:settings.gap",
      "min": 0,
      "max": 100,
      "step": 1,
      "unit": "px",
      "default": 12
    },
    {
      "type": "color_scheme",
      "id": "color_scheme",
      "label": "t:settings.color_scheme",
      "default": "scheme-1"
    },
    {
      "type": "header",
      "content": "t:content.padding"
    },
    {
      "type": "range",
      "id": "padding-block-start",
      "label": "t:settings.top",
      "min": 0,
      "max": 100,
      "step": 1,
      "unit": "px",
      "default": 0
    },
    {
      "type": "range",
      "id": "padding-block-end",
      "label": "t:settings.bottom",
      "min": 0,
      "max": 100,
      "step": 1,
      "unit": "px",
      "default": 0
    }
  ],
  "presets": [
    {
      "name": "t:names.product_recommendations",
      "category": "t:categories.product",
      "settings": {
        "product": "{{ closest.product }}",
        "recommendation_type": "related"
      },
      "blocks": {
        "heading": {
          "type": "text",
          "settings": {
            "text": "<h4>You may also like</h4>"
          }
        },
        "static-product-card": {
          "type": "product-card",
          "static": true,
          "settings": {
            "product": "{{ closest.product }}"
          },
          "blocks": {
            "product-card-gallery": {
              "type": "_product-card-gallery",
              "settings": {
                "product": "{{ closest.product }}"
              }
            },
            "group": {
              "type": "group",
              "settings": {
                "content_direction": "column",
                "gap": 4
              },
              "blocks": {
                "text": {
                  "type": "product-title",
                  "settings": {
                    "product": "{{ closest.product }}",
                    "type_preset": "paragraph"
                  }
                },
                "price": {
                  "type": "price",
                  "settings": {
                    "product": "{{ closest.product }}",
                    "show_tax_info": false
                  }
                },
                "swatches": {
                  "type": "swatches",
                  "settings": {
                    "product": "{{ closest.product }}"
                  }
                }
              },
              "block_order": ["text", "price", "swatches"]
            }
          },
          "block_order": ["product-card-gallery", "group"]
        }
      },
      "block_order": ["heading"]
    }
  ]
}
{% endschema %}
