Files
Debutify-7/snippets/product-list-item.liquid
2026-11-01 19:05:05 +08:00

426 lines
18 KiB
Plaintext

{%- liquid
if empty_state
assign product_link = '/admin/products'
assign vendor = 'home_page.onboarding.product_vendor' | t
assign title = 'home_page.onboarding.product_title' | t
assign compare_at_price = 2999
assign price = 1999
else
assign variant = product.first_available_variant
assign product_link = product.url | within: collection
assign vendor = product.vendor
assign title = product.title
assign compare_at_price = product.compare_at_price
assign price = product.price
endif
# start yagi app code
assign product_price_min = product.price_min
unless empty_state
assign active_discount = true
assign empty_array = "" | split: ""
assign dormant_discounts = shop.metafields.app--168074346497.dormant_discounts.value | default: empty_array
assign target_discount_id = product.metafields.app--168074346497.applied_discount_id.value
for dormant_discount in dormant_discounts
if dormant_discount == target_discount_id
assign active_discount = false
endif
endfor
if active_discount
assign price = product.metafields.app--168074346497.min_auto_discounted_price.value | default: product.price
assign compare_at_price = product.compare_at_price
if product.metafields.app--168074346497.discount_percentage.value > 0.01
assign deducted_percentage = 1.0 | minus: product.metafields.app--168074346497.discount_percentage.value
assign price = product.price | divided_by: 100.0 | times: deducted_percentage | times: 100.0 | ceil
assign product_price_min = price
assign compare_at_price = product.price
if product.compare_at_price > compare_at_price
assign compare_at_price = product.compare_at_price
endif
endif
endif
endunless
# end yagi app code
assign is_on_sale = false
assign is_sold_out = true
if compare_at_price > price
assign is_on_sale = true
endif
if product.available or empty_state
assign is_sold_out = false
endif
assign has_hover_image = false
assign has_touch_image = false
if settings.dbtfy_show_second_image_on_hover_show_on_hover and product.media.size > 1
assign has_hover_image = true
assign hover_image = product.media[1].preview_image
endif
if settings.dbtfy_show_second_image_on_hover_enable_touch_screen and product.media.size > 1
assign has_touch_image = true
endif
if product.media.size > 1
assign has_hover_image = true
assign hover_image = product.media[1].preview_image
endif
assign variant = product.selected_or_first_available_variant
capture product_collections
for collection in product.collections
echo collection.handle
unless forloop.last
echo ","
endunless
endfor
endcapture
assign has_color_swatches = false
if settings.dbtfy_color_swatches_grid_options != blank
if product.available and product.variants.size > 1
assign has_color_swatches = true
endif
endif
assign hover_animation = settings.dbtfy_show_second_image_on_hover_hover_animation
case hover_animation
when 'fade'
assign hover_animation_class = 'animation-fade'
when 'none'
assign hover_animation_class = 'animation-none'
when 'zoom'
assign hover_animation_class = 'animation-zoom'
endcase
assign enable_hover_carousel = settings.dbtfy_show_second_image_on_hover_enable_carousel
-%}
<div class="product-item product-item--list{% if has_hover_image %} product-item--has-hover-image{% endif %}{% if has_touch_image %} product-item--has-touch-screen-image{% endif %}{% if is_sold_out %} product-item--sold-out{% endif %}{% if is_sold_out %} product-item--sold-out{% endif %}{% if empty_state %} product-item--empty-state{% endif %}"
data-product-item-list
data-product-handle="{{ product.handle }}"
data-product-id="{{ product.id }}"
data-product-collections="{{ product_collections }}"
{% unless visible %}hidden{% endunless %}>
<div class="product-item__content-wrapper p-0">
<div class="row row-md--sm">
<div class="col-4">
<div class="product-item__image-wrapper">
<style hidden>
{% if enable_hover_carousel and has_hover_image %}
@media (min-width: 768px) {
.product-item__image--hover,
.product-item__image--touch {
display: none !important;
}
}
{% endif %}
</style>
{%- capture hover_media_carousel -%}
{%- if product.media.size > 0 -%}
<div class="product__gallery product__gallery--slider product__gallery--slider-mobile"
data-product-gallery
style="display:none;">
<div class="slick row row--sm mt-0 gy-3 product__media-group{% unless is_stacked_layout %} product__media-group--single-xr{% endunless %}"
data-product-media-group>
{%- assign first_media = true -%}
{%- for media in product.media -%}
{%- liquid
assign is_featured = false
if media == featured_media
assign is_featured = true
endif
capture thumbnail_alt
if media.media_type == 'video' or media.media_type == 'external_video'
echo 'products.product.video_thumbnail_alt' | t: imageAlt: media.alt | escape
elsif media.media_type == 'model'
echo 'products.product.model_thumbnail_alt' | t: imageAlt: media.alt | escape
else
echo 'products.product.gallery_thumbnail_alt' | t: imageAlt: media.alt | escape
endif
endcapture
-%}
<div class="product__media-flex-wrapper" data-product-media-flex-wrapper>
<div class="product__media-flex">
{%- render 'media',
media: media,
id: id,
loop: enable_video_looping,
is_featured: is_featured,
images_loading_type: images_loading_type,
product: product,
lazy_load: false,
index: forloop.index0,
size: image_size
-%}
{%- liquid
if is_stacked_layout
assign xr_id = false
if first_media and has_first_3d_model
assign xr_id = first_3d_model.id
elsif media.media_type == 'model'
assign xr_id = media.id
endif
if xr_id
render 'xr-button', model_id: xr_id, multi: true
endif
assign first_media = false
endif
-%}
</div>
</div>
{%- endfor -%}
</div>
</div>
{%- endif -%}
{%- endcapture -%}
<a href="{{ product_link }}" aria-label="Click to view {{ product.title }} product">
{%- assign media = product.media.first -%}
{%- if media != blank -%}
<div class="product-item__image media-wrapper media-wrapper--product media-wrapper--{{ image_size }} {{ hover_animation_class }}{% if image_size != blank %} padding-top-unset{% endif %}" {% if image_size != blank %} style="padding-top:{{ 1 | divided_by: media.preview_image.aspect_ratio | times: 100 }}%;"{% endif %}>
{%- liquid
assign products_per_row_desktop = products_per_row_desktop | times: 1
assign height_ratio_desktop = 100 | divided_by: products_per_row_desktop
assign height_ratio_mobile = 100 | divided_by: products_per_row_mobile
assign width_ratio_desktop = 100.0 | divided_by: height_ratio_desktop
assign maximum_image_width_desktop = settings.page_container_width | divided_by: width_ratio_desktop
-%}
{%- capture sizes -%}(max-width: 768px) 100vw, 50vw{% endcapture %}
{{- media.preview_image | image_url: width: media.preview_image.width | image_tag: loading: images_loading_type, sizes: sizes, widths: '300,400,500,600,700,800,1000,1200,1400,1600,1800,2000,2200,2400,2600', class: 'media' -}}
</div>
{%- if enable_hover_carousel -%}
{{- hover_media_carousel -}}
{%- endif -%}
{%- if has_hover_image or has_touch_image -%}
<div class="product-item__image product-item__image--hover product-item__image--touch media-wrapper {{ hover_animation_class }}{% if image_size != blank %} media-wrapper--{{ image_size }} padding-top-unset{% else %} media-wrapper--product{% endif %}"{% if image_size != blank %} style="padding-top:{{ 1 | divided_by: media.preview_image.aspect_ratio | times: 100 }}%;"{% endif %}>
{%- liquid
assign products_per_row_desktop = products_per_row_desktop | times: 1
assign height_ratio_desktop = 100 | divided_by: products_per_row_desktop
assign height_ratio_mobile = 100 | divided_by: products_per_row_mobile
assign width_ratio_desktop = 100.0 | divided_by: height_ratio_desktop
assign maximum_image_width_desktop = settings.page_container_width | divided_by: width_ratio_desktop
-%}
{%- capture sizes -%}(max-width: 768px) {{ height_ratio_mobile }}vw, min({{ maximum_image_width_desktop | ceil }}px, {{ height_ratio_desktop }}vw){% endcapture %}
{{- hover_image | image_url: width: hover_image.width | image_tag: loading: images_loading_type, sizes: sizes, widths: '300,400,500,600,700,800,1000,1200,1400,1600,1800,2000,2200,2400,2600', class: 'media' -}}
</div>
{%- endif -%}
{%- else -%}
{{- 'product-' | append: current | placeholder_svg_tag: 'placeholder-svg' -}}
{%- endif -%}
</a>
{%- unless product_grid_badge_placement == 'none' -%}
<div class="badge-wrapper badge--{{ product_grid_badge_placement }}">
{%- if is_sold_out and show_sold_out_badge -%}
<div class="badge">
<span class="{{ settings.icon }}" translate="no">watch_later</span>
<span>
{{ 'products.product.sold_out_html' | t }}
</span>
</div>
{%- elsif is_on_sale and show_sales_badge -%}
{%- capture discount_price -%}
{%- if settings.sale_type == 'amount' -%}
{%- assign discount_price = compare_at_price | minus: price -%}
<span class="money dbtfy-discount-saved-badge__value">{{ discount_price | money }}</span>
{%- elsif settings.sale_type == 'percentage' -%}
{%- assign discount_price = compare_at_price | minus: price | times: 100 | divided_by: compare_at_price -%}
<span class="dbtfy-discount-saved-badge__value">{{ discount_price }}%</span>
{%- endif -%}
{%- endcapture -%}
<span class="dbtfy-discount-saved-badge badge" hidden>
<span class="{{ settings.icon }}" translate="no">local_offer</span>
<span>
{{- 'products.general.save_html' | t: saved_amount: discount_price -}}
</span>
</span>
{%- endif -%}
{%- if custom_badge_label != blank -%}
<div style="background-color: {{ badge_background_color }}; color: {{ badge_text_color }};" class="badge">
{%- if custom_badge_icon -%}
<span class="{{ settings.icon }}" translate="no">{{ custom_badge_icon }}</span>
{%- endif -%}
<span>
{{- custom_badge_label -}}
</span>
</div>
{%- endif -%}
</div>
{%- endunless -%}
{%- unless empty_state -%}
{%- unless add_remove_button -%}
<div class="badge badge--icons{% if product_grid_badge_placement == 'top-right' %} badge--top-left{% else %} badge--top-right{% endif %}">
{%- liquid
render 'dbtfy-wish-list', product: product
render 'dbtfy-quick-compare', product: product, type: 'grid'
if enable_quick_view
render 'dbtfy-quick-view', product: product
endif
-%}
</div>
{%- endunless -%}
{%- endunless -%}
</div>
</div>
<div class="col-8 product-item__content">
<div class="row gy-2 {{ product_text_alignment }}">
{%- unless empty_state -%}
{%- if product != blank -%}
{%- if show_product_vendor -%}
<p>
<span class="{{ settings.icon }} icon" translate="no">store_mall_directory</span>
{{- vendor -}}
</p>
{%- endif -%}
<a href="{{ product_link }}">
<p class="h6{% if settings.product_grid_truncate_title %} text-ellipsis{% endif %}">{{ title }}</p>
</a>
{%- if show_product_rating -%}
{%- unless empty_state -%}
<div class="product-item__reviews">
{%- render 'review-badge', product: product, position: 'product_grid' -%}
</div>
{%- endunless -%}
{%- endif -%}
<div class="product-item__description">
{%- if product.description contains '[split_description]' -%}
<p>{{ product.description | strip_html | replace: '&nbsp;', ' ' | split: '[split_description]' | first }}</p>
{%- else -%}
<p>{{ product.description | strip_html | replace: '&nbsp;', ' ' | truncate: 300 }}</p>
{%- endif -%}
</div>
{%- endif -%}
{%- else -%}
{%- if show_product_vendor -%}
<p>
<span class="{{ settings.icon }} icon" translate="no">store_mall_directory</span>
{{- vendor -}}
</p>
{%- endif -%}
<a href="{{ product_link }}">
<p class="h6{% if settings.product_grid_truncate_title %} text-ellipsis{% endif %}">{{ title }}</p>
</a>
{%- endunless -%}
{%- if show_product_price -%}
<div class="product-item__price-wrapper">
<span class="gx-2 gy-1 row row-cols-auto text-accent {{ product_text_alignment }}">
<span class="price price--regular{% if is_on_sale %} price--sale text-sale{% endif %}" aria-label="{{ 'products.general.regular_price' | t }}">
{%- if product.price_varies and empty_state == false -%}
<span class="money">{{ product_price_min | money }} +</span>
{%- else -%}
<span class="money">{{ price | money }}</span>
{%- endif -%}
</span>
<span class="price price--compare text-strike text-muted"
{% unless is_on_sale %}hidden{% endunless %}
aria-label="{{ 'products.general.regular_price' | t }}">
{%- if is_on_sale -%}
<span class="money">{{ compare_at_price | money }}</span>
{%- else -%}
<span class="money"></span>
{%- endif -%}
</span>
</span>
{%- if variant.available and variant.unit_price_measurement -%}
{%- capture unit_price_separator -%}
<span aria-hidden="true">/</span><span class="visually-hidden">&nbsp;{{ 'general.accessibility.unit_price_separator' | t }}&nbsp;</span>
{%- endcapture -%}
{%- capture unit_price_base_unit -%}
<span>
{%- if variant.unit_price_measurement.reference_value != 1 -%}
{{- variant.unit_price_measurement.reference_value -}}
{%- endif -%}
{{ variant.unit_price_measurement.reference_unit }}
</span>
{%- endcapture -%}
<span>
<span class="visually-hidden">{{ 'products.general.unit_price' | t }}</span>
<span>{{ variant.unit_price | money }}</span>{{- unit_price_separator -}}{{- unit_price_base_unit -}}
</span>
{%- endif -%}
</div>
{%- endif -%}
{%- liquid
unless empty_state
if has_color_swatches and show_color_swatches
render 'dbtfy-color-swatches', product: product, type: 'list', product_text_alignment: product_text_alignment
endif
render 'dbtfy-collection-addtocart', product: product, sold_out: is_sold_out, layout: 'list'
endunless
-%}
{%- if add_remove_button -%}
<p>
<button type="button" class="dbtfy-wish-list__button dbtfy-wish-list__button--remove" data-product-handle="{{ product.handle }}">
<span class="{{ settings.icon }}" translate="no">delete</span>
<span class="d-none d-md-inline-block">
{{ 'cart.general.remove' | t }}
</span>
</button>
</p>
{%- endif -%}
</div>
</div>
</div>
</div>
</div>