Rust discount function (one automatic discount evaluating all offers in priority order, parity with the Odoo engine), React Router admin with Polaris, theme app extension and app proxy pages, webhooks incl. GDPR, managed-pricing limits, and a Docker Compose stack (Postgres + Caddy HTTPS) for a single VPS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
87 lines
3.5 KiB
Plaintext
87 lines
3.5 KiB
Plaintext
{% doc %}
|
|
Offer card (F19): image or a 2x2 grid of product pictures, badge, name, deal, and for fixed bundles the
|
|
bundle price, the struck-through regular price and the number of items; end date; link to the bundle page.
|
|
Fixed-bundle prices come from live product prices (all_products, presentment currency); bundle-offers.js
|
|
recomputes $-off / bundle-price deals when the customer shops in another currency.
|
|
|
|
@param {object} offer - An offer from the app's storefront data
|
|
@param {string} [heading_tag] - h2 or h3 (default h3)
|
|
@example
|
|
{% render 'bo-card', offer: offer %}
|
|
{% enddoc %}
|
|
{%- liquid
|
|
assign url = '/apps/bundles/' | append: offer.h
|
|
assign tag = heading_tag | default: 'h3'
|
|
assign locale = request.locale.iso_code
|
|
assign name = offer.n
|
|
assign badge = offer.b
|
|
if offer.i[locale].n != blank
|
|
assign name = offer.i[locale].n
|
|
endif
|
|
if offer.i[locale].b != blank
|
|
assign badge = offer.i[locale].b
|
|
endif
|
|
|
|
assign regular = 0
|
|
if offer.t == 'fixed'
|
|
for line in offer.l
|
|
assign p = all_products[line.h]
|
|
if p.id
|
|
assign price = p.price
|
|
if line.v != ''
|
|
for variant in p.variants
|
|
assign vid = variant.id | append: ''
|
|
if vid == line.v
|
|
assign price = variant.price
|
|
endif
|
|
endfor
|
|
endif
|
|
assign line_total = price | times: line.q
|
|
assign regular = regular | plus: line_total
|
|
endif
|
|
endfor
|
|
assign dv_cents = offer.dv | times: 100
|
|
case offer.dt
|
|
when 'percent'
|
|
assign saving = regular | times: offer.dv | divided_by: 100.0 | round
|
|
when 'amount'
|
|
assign saving = dv_cents | at_most: regular
|
|
else
|
|
assign saving = regular | minus: dv_cents | at_least: 0
|
|
endcase
|
|
assign bundle = regular | minus: saving
|
|
endif
|
|
-%}
|
|
<article class="bo-card">
|
|
<a class="bo-card__media" href="{{ url }}" tabindex="-1" aria-hidden="true">
|
|
{%- if offer.img != blank -%}
|
|
<img src="{{ offer.img }}" alt="" loading="lazy" width="800" height="600">
|
|
{%- elsif offer.th.size > 0 -%}
|
|
<span class="bo-card__thumbs bo-card__thumbs--{{ offer.th.size | at_most: 4 }}">
|
|
{%- for src in offer.th limit: 4 -%}<img src="{{ src }}" alt="" loading="lazy" width="200" height="200">{%- endfor -%}
|
|
</span>
|
|
{%- endif -%}
|
|
</a>
|
|
{%- if badge != blank -%}<p class="bo-stub"><span>{{ badge }}</span></p>{%- endif -%}
|
|
<div class="bo-card__body">
|
|
<{{ tag }} class="bo-card__title"><a href="{{ url }}">{{ name }}</a></{{ tag }}>
|
|
<p class="bo-card__deal">{% render 'bo-summary', offer: offer %}</p>
|
|
{%- if offer.t == 'fixed' and regular > 0 -%}
|
|
<p class="bo-card__prices" data-bo-fixed data-regular="{{ regular }}" data-dt="{{ offer.dt }}" data-dv="{{ offer.dv }}">
|
|
<span class="bo-visually-hidden">{{ 'bundle_offers.card.bundle_price' | t }}</span>
|
|
<span class="bo-card__now" data-bo-bundle>{{ bundle | money }}</span>
|
|
{%- if saving > 0 -%}
|
|
<span class="bo-visually-hidden">{{ 'bundle_offers.card.regular_price' | t }}</span>
|
|
<s class="bo-card__was" data-bo-regular>{{ regular | money }}</s>
|
|
{%- endif -%}
|
|
<span class="bo-card__count">{{ 'bundle_offers.card.items' | t: count: offer.ni }}</span>
|
|
</p>
|
|
{%- endif -%}
|
|
{%- if offer.e != blank -%}
|
|
{%- assign ends = offer.e | time_tag: format: 'date' -%}
|
|
<p class="bo-card__ends">{{ 'bundle_offers.card.ends_html' | t: date: ends }}</p>
|
|
{%- endif -%}
|
|
<a class="bo-button" href="{{ url }}">{{ 'bundle_offers.card.shop' | t }}</a>
|
|
</div>
|
|
</article>
|