product/flash-sale

Trang tổng hợp các sản phẩm đang flash sale.

Ngoài những biến dưới đây, slot này còn nhận toàn bộ biến toàn cục.

Biến của trang

Biến Kiểu Mô tả Từ phiên bản
sales FlashSale[] Các đợt flash sale đang chạy. 1.0
products Product[] Sản phẩm đang giảm giá, kèm trường flash. 1.0
has_more boolean Còn trang tiếp theo hay không. 1.0
next_cursor string | null Con trỏ để tải trang kế; null khi đã hết. 1.0
cursor string | null Con trỏ của trang đang xem. 1.0
page_title string Tiêu đề SEO của trang. 1.0

Mã đầy đủ

Toàn bộ tệp product/flash-sale.html của bộ giao diện mặc định. Chép về templates/<bộ giao diện của bạn>/product/flash-sale.html rồi sửa theo ý muốn.

<div class="container page-content flash-hub">
  <nav class="breadcrumb">
    <a href="/">Trang chủ</a> / <span>Flash Sale</span>
  </nav>

  <div class="flash-hub__header">
    <h1 class="flash-hub__title">⚡ Flash Sale</h1>
    {% if sales.size > 0 and sales[0].ends_at %}
      <div class="flash-hub__countdown" data-flash-ends="{{ sales[0].ends_at }}">
        Kết thúc sau <strong class="flash-countdown-value">--:--:--</strong>
      </div>
    {% endif %}
  </div>

  {% if products.size > 0 %}
    <div class="product-grid">
      {% for product in products %}
        <div class="product-card product-card--flash">
          {% if product.url %}<a href="{{ product.url }}" class="product-card__img-link">{% else %}<span class="product-card__img-link">{% endif %}
            {% if product.cover_image_url %}
              <img src="{{ product.cover_image_url }}" alt="{{ product.title }}"
                   class="product-card__img" loading="lazy">
            {% else %}
              <div class="product-card__img-placeholder"></div>
            {% endif %}
            <span class="product-card__badge product-card__badge--flash">⚡ Flash</span>
          {% if product.url %}</a>{% else %}</span>{% endif %}
          <div class="product-card__body">
            {% if product.url %}
              <a href="{{ product.url }}" class="product-card__name">{{ product.title }}</a>
            {% else %}
              <span class="product-card__name">{{ product.title }}</span>
            {% endif %}
            <div class="product-card__price">
              <span class="price price--flash">{{ product.flash.deal_price | money }}</span>
              <span class="price price--original">{{ product.price | money }}</span>
            </div>
            {% if product.flash.ends_at %}
              <div class="product-card__countdown" data-flash-ends="{{ product.flash.ends_at }}">
                Còn <strong class="flash-countdown-value">--:--:--</strong>
              </div>
            {% endif %}
            {% if product.flash.remaining %}
              <div class="product-card__remaining">Còn {{ product.flash.remaining }} suất</div>
            {% endif %}
            <button type="button" class="btn btn--outline btn--sm btn--block quick-add"
                    data-product-slug="{{ product.slug }}">
              Thêm vào giỏ
            </button>
          </div>
        </div>
      {% endfor %}
    </div>

    {% if has_more %}
      <div class="load-more">
        <a href="?cursor={{ next_cursor | url_encode }}" class="btn btn--outline">Xem thêm</a>
      </div>
    {% endif %}
  {% else %}
    <div class="empty-state">
      <p>Hiện chưa có chương trình flash sale nào đang diễn ra.</p>
      <a href="/san-pham" class="btn btn--outline">Xem tất cả sản phẩm</a>
    </div>
  {% endif %}
</div>

<script>
(function () {
  function pad(n) { return String(n).padStart(2, '0'); }
  function tick() {
    var now = Date.now();
    document.querySelectorAll('[data-flash-ends]').forEach(function (el) {
      var raw = el.getAttribute('data-flash-ends');
      if (!raw) return;
      var end = Date.parse(raw.replace(' ', 'T') + 'Z');
      var diff = Math.floor((end - now) / 1000);
      var out = el.querySelector('.flash-countdown-value');
      if (!out) return;
      if (diff <= 0) { out.textContent = '00:00:00'; return; }
      var h = Math.floor(diff / 3600), m = Math.floor((diff % 3600) / 60), s = diff % 60;
      out.textContent = pad(h) + ':' + pad(m) + ':' + pad(s);
    });
  }
  tick();
  setInterval(tick, 1000);
})();
</script>