Files
wc-bootstrap/templates/cart/cart.html.twig

172 lines
8.9 KiB
Twig
Raw Permalink Normal View History

Implement Phase 4 & 5: cart and checkout templates (Bootstrap 5, HPOS) Phase 4 - Cart (9 templates): - cart: 8+4 column layout, table-responsive items, coupon input-group - cart-empty: centered empty state with cart-x icon - cart-item-data: inline dl for variation details - cart-totals: card with list-group-flush rows, sticky sidebar - cart-shipping: form-check radio per shipping method - cross-sells: product loop grid section - mini-cart: offcanvas-compatible item list with remove buttons - proceed-to-checkout-button: btn-primary btn-lg w-100 - shipping-calculator: collapsible form with form-select/form-control Phase 5 - Checkout (12 templates): - form-checkout: 7+5 column layout, sticky order review sidebar - form-billing: card with field wrapper, optional account creation - form-shipping: card with ship-to-different-address collapse toggle - form-coupon: collapsible input-group with alert-info toggle - form-login: collapsible login reusing global/form-login.html.twig - review-order: card with table-sm, tfoot subtotal/shipping/total - payment: list-group of payment gateways with radio selection - payment-method: form-check with description collapse - terms: form-check checkbox with T&C link - thankyou: HPOS compatible, alert-success + order details list-group - order-received: confirmation message - cart-errors: alert-danger with return-to-cart button All order data accessed via WC_Order methods (HPOS compatible). CSS additions: cart thumbnail sizing, checkout form field overrides, payment box transitions, dark mode focus states. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 10:33:49 +01:00
{#
# Cart Page (Bootstrap 5 Override)
#
# Main cart page with items table and totals sidebar.
# Layout: col-lg-8 (items) + col-lg-4 (totals).
#
# Expected context:
# cart_items - Array from WC()->cart->get_cart(), each with:
# .key - Cart item key
# .product - WC_Product object
# .product_id - Product ID
# .product_name - Filtered product name
# .permalink - Product URL
# .quantity - Quantity
# .subtotal - Line subtotal HTML
# .price - Unit price HTML
# .thumbnail - Product thumbnail HTML
# .item_data_html - Variation data HTML
# .remove_url - Remove item URL
# .visible - Whether item is visible
# .css_class - Item CSS class
#
# WooCommerce PHP equivalent: cart/cart.php
#
# @package WcBootstrap
# @since 0.1.0
#}
{{ do_action('woocommerce_before_cart') }}
<div class="row g-4">
{# Cart items table #}
<div class="col-lg-8">
<form class="woocommerce-cart-form" action="{{ wc_get_cart_url()|esc_url }}" method="post">
{{ do_action('woocommerce_before_cart_table') }}
<div class="table-responsive">
<table class="table align-middle shop_table shop_table_responsive cart woocommerce-cart-form__contents">
<thead class="table-light">
<tr>
<th class="product-thumbnail" scope="col" style="width: 80px;">
<span class="visually-hidden">{{ __('Thumbnail') }}</span>
</th>
<th class="product-name" scope="col">{{ __('Product') }}</th>
<th class="product-price" scope="col">{{ __('Price') }}</th>
<th class="product-quantity" scope="col" style="width: 160px;">{{ __('Quantity') }}</th>
<th class="product-subtotal" scope="col">{{ __('Subtotal') }}</th>
<th class="product-remove" scope="col" style="width: 50px;">
<span class="visually-hidden">{{ __('Remove') }}</span>
</th>
</tr>
</thead>
<tbody>
{{ do_action('woocommerce_before_cart_contents') }}
{% if cart_items is defined %}
{% for item in cart_items %}
{% if item.visible is not defined or item.visible %}
<tr class="woocommerce-cart-form__cart-item {{ item.css_class|default('') }}">
<td class="product-thumbnail">
{% if item.permalink %}
<a href="{{ item.permalink|esc_url }}">{{ item.thumbnail|raw }}</a>
{% else %}
{{ item.thumbnail|raw }}
{% endif %}
</td>
<td class="product-name" data-title="{{ __('Product') }}">
{% if item.permalink %}
<a href="{{ item.permalink|esc_url }}" class="text-decoration-none">
{{ item.product_name|esc_html }}
</a>
{% else %}
{{ item.product_name|esc_html }}
{% endif %}
{{ item.item_data_html|default('')|raw }}
</td>
<td class="product-price" data-title="{{ __('Price') }}">
{{ item.price|raw }}
</td>
<td class="product-quantity" data-title="{{ __('Quantity') }}">
{% include 'global/quantity-input.html.twig' with {
input_id: 'quantity_' ~ item.key,
input_name: 'cart[' ~ item.key ~ '][qty]',
input_value: item.quantity,
min_value: 0,
max_value: item.product.get_max_purchase_quantity()|default(0),
step: 1,
placeholder: '',
inputmode: 'numeric',
classes: 'qty',
readonly: false,
type: 'number',
args: { product_name: item.product_name }
} %}
</td>
<td class="product-subtotal" data-title="{{ __('Subtotal') }}">
{{ item.subtotal|raw }}
</td>
<td class="product-remove">
<a href="{{ item.remove_url|esc_url }}"
class="btn btn-sm btn-outline-danger remove"
aria-label="{{ __('Remove this item') }}"
data-product_id="{{ item.product_id }}"
data-product_sku="{{ item.product.get_sku()|default('')|esc_attr }}">
<i class="bi bi-x-lg" aria-hidden="true"></i>
</a>
</td>
</tr>
{% endif %}
{% endfor %}
{% endif %}
{{ do_action('woocommerce_cart_contents') }}
<tr>
<td colspan="6" class="actions">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2">
{% if wc_coupons_enabled() %}
<div class="coupon input-group" style="max-width: 350px;">
<label class="visually-hidden" for="coupon_code">{{ __('Coupon:') }}</label>
<input type="text"
name="coupon_code"
class="form-control"
id="coupon_code"
placeholder="{{ __('Coupon code') }}" />
<button type="submit"
class="btn btn-outline-secondary"
name="apply_coupon"
value="{{ __('Apply coupon') }}">
{{ __('Apply coupon') }}
</button>
{{ do_action('woocommerce_cart_coupon') }}
</div>
{% endif %}
<button type="submit"
class="btn btn-outline-primary"
name="update_cart"
value="{{ __('Update cart') }}">
{{ __('Update cart') }}
</button>
{{ do_action('woocommerce_cart_actions') }}
{{ wp_nonce_field('woocommerce-cart', 'woocommerce-cart-nonce') }}
</div>
</td>
</tr>
{{ do_action('woocommerce_after_cart_contents') }}
</tbody>
</table>
</div>
{{ do_action('woocommerce_after_cart_table') }}
</form>
</div>
{# Cart totals sidebar #}
<div class="col-lg-4">
<div class="cart-collaterals">
{{ do_action('woocommerce_cart_collaterals') }}
</div>
</div>
</div>
{{ do_action('woocommerce_after_cart') }}