You've already forked wc-bootstrap
Implement Phase 6 & 7: My Account and Order Details templates (Bootstrap 5, HPOS)
Phase 6 - My Account (15 templates): - Account layout with sidebar navigation (list-group) and content area - Orders table with status badges, pagination, and responsive design - View order with order notes as list-group items - Address cards with edit/add buttons - Login/Register side-by-side card layout - Account edit, password change, downloads, payment methods forms - Lost/reset password forms and confirmation Phase 7 - Order Details (5 templates): - Order details table with items, totals, and customer note - Line item rows with refund quantity display - Customer billing/shipping address cards - Order tracking form - Order again button All order templates use WC_Order object methods only (HPOS compatible). Bootstrap 5 components: cards, tables, list-groups, badges, forms, alerts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
40
PLAN.md
40
PLAN.md
@@ -600,29 +600,29 @@ Track completion per file. Mark with `[x]` when done.
|
||||
|
||||
### Phase 6 -- My Account
|
||||
|
||||
- [ ] `myaccount/my-account.html.twig`
|
||||
- [ ] `myaccount/navigation.html.twig`
|
||||
- [ ] `myaccount/dashboard.html.twig`
|
||||
- [ ] `myaccount/orders.html.twig`
|
||||
- [ ] `myaccount/view-order.html.twig`
|
||||
- [ ] `myaccount/my-address.html.twig`
|
||||
- [ ] `myaccount/form-edit-address.html.twig`
|
||||
- [ ] `myaccount/form-edit-account.html.twig`
|
||||
- [ ] `myaccount/downloads.html.twig`
|
||||
- [ ] `myaccount/payment-methods.html.twig`
|
||||
- [ ] `myaccount/form-add-payment-method.html.twig`
|
||||
- [ ] `myaccount/form-login.html.twig`
|
||||
- [ ] `myaccount/form-lost-password.html.twig`
|
||||
- [ ] `myaccount/form-reset-password.html.twig`
|
||||
- [ ] `myaccount/lost-password-confirmation.html.twig`
|
||||
- [x] `myaccount/my-account.html.twig`
|
||||
- [x] `myaccount/navigation.html.twig`
|
||||
- [x] `myaccount/dashboard.html.twig`
|
||||
- [x] `myaccount/orders.html.twig`
|
||||
- [x] `myaccount/view-order.html.twig`
|
||||
- [x] `myaccount/my-address.html.twig`
|
||||
- [x] `myaccount/form-edit-address.html.twig`
|
||||
- [x] `myaccount/form-edit-account.html.twig`
|
||||
- [x] `myaccount/downloads.html.twig`
|
||||
- [x] `myaccount/payment-methods.html.twig`
|
||||
- [x] `myaccount/form-add-payment-method.html.twig`
|
||||
- [x] `myaccount/form-login.html.twig`
|
||||
- [x] `myaccount/form-lost-password.html.twig`
|
||||
- [x] `myaccount/form-reset-password.html.twig`
|
||||
- [x] `myaccount/lost-password-confirmation.html.twig`
|
||||
|
||||
### Phase 7 -- Order Details
|
||||
|
||||
- [ ] `order/order-details.html.twig`
|
||||
- [ ] `order/order-details-item.html.twig`
|
||||
- [ ] `order/order-details-customer.html.twig`
|
||||
- [ ] `order/form-tracking.html.twig`
|
||||
- [ ] `order/order-again.html.twig`
|
||||
- [x] `order/order-details.html.twig`
|
||||
- [x] `order/order-details-item.html.twig`
|
||||
- [x] `order/order-details-customer.html.twig`
|
||||
- [x] `order/form-tracking.html.twig`
|
||||
- [x] `order/order-again.html.twig`
|
||||
|
||||
### Phase 8 -- Emails
|
||||
|
||||
|
||||
@@ -276,3 +276,72 @@ header.sticky-top.is-stuck {
|
||||
.wp-block-navigation__container {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
My Account
|
||||
Navigation and layout for the My Account area.
|
||||
========================================================================== */
|
||||
|
||||
.woocommerce-MyAccount-navigation .list-group-item.active {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Order status marks */
|
||||
.woocommerce-order-details mark {
|
||||
background: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* View-order notes */
|
||||
.woocommerce-OrderUpdate-description p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Address cards */
|
||||
.woocommerce-Address address {
|
||||
font-style: normal;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* My Account forms — apply Bootstrap form-control styles */
|
||||
.woocommerce-MyAccount-content .form-row input.input-text,
|
||||
.woocommerce-MyAccount-content .form-row textarea,
|
||||
.woocommerce-MyAccount-content .form-row select {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: var(--bs-body-color);
|
||||
background-color: var(--bs-body-bg);
|
||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||
border-radius: var(--bs-border-radius);
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.woocommerce-MyAccount-content .form-row input.input-text:focus,
|
||||
.woocommerce-MyAccount-content .form-row textarea:focus,
|
||||
.woocommerce-MyAccount-content .form-row select:focus {
|
||||
border-color: #86b7fe;
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Order Details
|
||||
Styling for the order details and tracking pages.
|
||||
========================================================================== */
|
||||
|
||||
.woocommerce-order-details .table tfoot th {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.woocommerce-order-details .table tfoot tr:last-child th,
|
||||
.woocommerce-order-details .table tfoot tr:last-child td {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
40
templates/myaccount/dashboard.html.twig
Normal file
40
templates/myaccount/dashboard.html.twig
Normal file
@@ -0,0 +1,40 @@
|
||||
{#
|
||||
# My Account Dashboard (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows the welcome screen on the account dashboard.
|
||||
#
|
||||
# Expected context:
|
||||
# current_user - WP_User object
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/dashboard.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
<p>
|
||||
{{ __('Hello %1$s (not %1$s? <a href="%2$s">Log out</a>)')|format(
|
||||
'<strong>' ~ current_user.display_name|esc_html ~ '</strong>',
|
||||
wc_logout_url()|esc_url
|
||||
)|wp_kses_post }}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% if wc_shipping_enabled() %}
|
||||
{{ __('From your account dashboard you can view your <a href="%1$s">recent orders</a>, manage your <a href="%2$s">shipping and billing addresses</a>, and <a href="%3$s">edit your password and account details</a>.')|format(
|
||||
wc_get_endpoint_url('orders')|esc_url,
|
||||
wc_get_endpoint_url('edit-address')|esc_url,
|
||||
wc_get_endpoint_url('edit-account')|esc_url
|
||||
)|wp_kses_post }}
|
||||
{% else %}
|
||||
{{ __('From your account dashboard you can view your <a href="%1$s">recent orders</a>, manage your <a href="%2$s">billing address</a>, and <a href="%3$s">edit your password and account details</a>.')|format(
|
||||
wc_get_endpoint_url('orders')|esc_url,
|
||||
wc_get_endpoint_url('edit-address')|esc_url,
|
||||
wc_get_endpoint_url('edit-account')|esc_url
|
||||
)|wp_kses_post }}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{{ do_action('woocommerce_account_dashboard') }}
|
||||
{{ do_action('woocommerce_before_my_account') }}
|
||||
{{ do_action('woocommerce_after_my_account') }}
|
||||
31
templates/myaccount/downloads.html.twig
Normal file
31
templates/myaccount/downloads.html.twig
Normal file
@@ -0,0 +1,31 @@
|
||||
{#
|
||||
# My Account Downloads (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows downloads on the account page.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/downloads.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set downloads = fn('WC').customer.get_downloadable_products() %}
|
||||
{% set has_downloads = downloads is not empty %}
|
||||
|
||||
{{ do_action('woocommerce_before_account_downloads', has_downloads) }}
|
||||
|
||||
{% if has_downloads %}
|
||||
{{ do_action('woocommerce_before_available_downloads') }}
|
||||
{{ do_action('woocommerce_available_downloads', downloads) }}
|
||||
{{ do_action('woocommerce_after_available_downloads') }}
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle me-2" aria-hidden="true"></i>
|
||||
{{ __('No downloads available yet.') }}
|
||||
<a href="{{ apply_filters('woocommerce_return_to_shop_redirect', wc_get_page_permalink('shop'))|esc_url }}" class="alert-link">
|
||||
{{ __('Browse products') }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_after_account_downloads', has_downloads) }}
|
||||
66
templates/myaccount/form-add-payment-method.html.twig
Normal file
66
templates/myaccount/form-add-payment-method.html.twig
Normal file
@@ -0,0 +1,66 @@
|
||||
{#
|
||||
# Add Payment Method Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Form to add a new payment method to the account.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-add-payment-method.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set available_gateways = fn('WC').payment_gateways.get_available_payment_gateways() %}
|
||||
|
||||
{% if available_gateways is not empty %}
|
||||
<form id="add_payment_method" method="post">
|
||||
<div id="payment" class="woocommerce-Payment">
|
||||
<ul class="list-group mb-4">
|
||||
{% for gateway in available_gateways %}
|
||||
<li class="list-group-item payment_method_{{ gateway.id|esc_attr }}">
|
||||
<div class="form-check">
|
||||
<input type="radio"
|
||||
class="form-check-input input-radio"
|
||||
id="payment_method_{{ gateway.id|esc_attr }}"
|
||||
name="payment_method"
|
||||
value="{{ gateway.id|esc_attr }}"
|
||||
{% if gateway.chosen %}checked{% endif %} />
|
||||
<label class="form-check-label d-flex align-items-center gap-2"
|
||||
for="payment_method_{{ gateway.id|esc_attr }}">
|
||||
<span>{{ gateway.get_title()|wp_kses_post }}</span>
|
||||
{{ gateway.get_icon()|raw }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{% if gateway.has_fields() or gateway.get_description() %}
|
||||
<div class="payment_box payment_method_{{ gateway.id|esc_attr }} mt-2 ps-4{% if not gateway.chosen|default(false) %} d-none{% endif %}">
|
||||
{% if gateway.get_description() %}
|
||||
<p class="small text-body-secondary mb-2">{{ gateway.get_description()|wp_kses_post }}</p>
|
||||
{% endif %}
|
||||
{{ gateway.payment_fields() }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{{ do_action('woocommerce_add_payment_method_form_bottom') }}
|
||||
|
||||
<div class="mt-3">
|
||||
{{ wp_nonce_field('woocommerce-add-payment-method', 'woocommerce-add-payment-method-nonce') }}
|
||||
<button type="submit"
|
||||
class="btn btn-primary"
|
||||
id="place_order"
|
||||
value="{{ __('Add payment method') }}">
|
||||
<i class="bi bi-plus-lg me-1" aria-hidden="true"></i>
|
||||
{{ __('Add payment method') }}
|
||||
</button>
|
||||
<input type="hidden" name="woocommerce_add_payment_method" id="woocommerce_add_payment_method" value="1" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle me-2" aria-hidden="true"></i>
|
||||
{{ __('New payment methods can only be added during checkout. Please contact us if you require assistance.') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
138
templates/myaccount/form-edit-account.html.twig
Normal file
138
templates/myaccount/form-edit-account.html.twig
Normal file
@@ -0,0 +1,138 @@
|
||||
{#
|
||||
# Edit Account Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Account details editing form with Bootstrap form styling.
|
||||
#
|
||||
# Expected context:
|
||||
# user - WP_User object
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-edit-account.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_edit_account_form') }}
|
||||
|
||||
<form class="woocommerce-EditAccountForm edit-account" action="" method="post" {{ do_action('woocommerce_edit_account_form_tag') }}>
|
||||
|
||||
{{ do_action('woocommerce_edit_account_form_start') }}
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-sm-6">
|
||||
<label for="account_first_name" class="form-label">
|
||||
{{ __('First name') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="account_first_name"
|
||||
id="account_first_name"
|
||||
autocomplete="given-name"
|
||||
value="{{ user.first_name|esc_attr }}"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="account_last_name" class="form-label">
|
||||
{{ __('Last name') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="account_last_name"
|
||||
id="account_last_name"
|
||||
autocomplete="family-name"
|
||||
value="{{ user.last_name|esc_attr }}"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="account_display_name" class="form-label">
|
||||
{{ __('Display name') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="account_display_name"
|
||||
id="account_display_name"
|
||||
aria-describedby="account_display_name_description"
|
||||
value="{{ user.display_name|esc_attr }}"
|
||||
required
|
||||
aria-required="true" />
|
||||
<div id="account_display_name_description" class="form-text">
|
||||
{{ __('This will be how your name will be displayed in the account section and in reviews') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="account_email" class="form-label">
|
||||
{{ __('Email address') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="email"
|
||||
class="form-control"
|
||||
name="account_email"
|
||||
id="account_email"
|
||||
autocomplete="email"
|
||||
value="{{ user.user_email|esc_attr }}"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_edit_account_form_fields') }}
|
||||
|
||||
<fieldset class="mb-3">
|
||||
<legend class="h5 border-bottom pb-2 mb-3">{{ __('Password change') }}</legend>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_current" class="form-label">
|
||||
{{ __('Current password (leave blank to leave unchanged)') }}
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password_current"
|
||||
id="password_current"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_1" class="form-label">
|
||||
{{ __('New password (leave blank to leave unchanged)') }}
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password_1"
|
||||
id="password_1"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password_2" class="form-label">
|
||||
{{ __('Confirm new password') }}
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password_2"
|
||||
id="password_2"
|
||||
autocomplete="off" />
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{ do_action('woocommerce_edit_account_form') }}
|
||||
|
||||
<div class="mt-3">
|
||||
{{ wp_nonce_field('save_account_details', 'save-account-details-nonce') }}
|
||||
<button type="submit" class="btn btn-primary" name="save_account_details" value="{{ __('Save changes') }}">
|
||||
<i class="bi bi-check-lg me-1" aria-hidden="true"></i>
|
||||
{{ __('Save changes') }}
|
||||
</button>
|
||||
<input type="hidden" name="action" value="save_account_details" />
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_edit_account_form_end') }}
|
||||
</form>
|
||||
|
||||
{{ do_action('woocommerce_after_edit_account_form') }}
|
||||
49
templates/myaccount/form-edit-address.html.twig
Normal file
49
templates/myaccount/form-edit-address.html.twig
Normal file
@@ -0,0 +1,49 @@
|
||||
{#
|
||||
# Edit Address Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Address editing form with Bootstrap form styling.
|
||||
#
|
||||
# Expected context:
|
||||
# load_address - Address type ('billing' or 'shipping'), or empty
|
||||
# address - Array of address fields
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-edit-address.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set page_title = load_address == 'billing' ? __('Billing address') : __('Shipping address') %}
|
||||
|
||||
{{ do_action('woocommerce_before_edit_account_address_form') }}
|
||||
|
||||
{% if not load_address %}
|
||||
{% include 'myaccount/my-address.html.twig' %}
|
||||
{% else %}
|
||||
<form method="post" novalidate>
|
||||
<h2 class="h4 mb-4">{{ apply_filters('woocommerce_my_account_edit_address_title', page_title, load_address) }}</h2>
|
||||
|
||||
<div class="woocommerce-address-fields">
|
||||
{{ do_action('woocommerce_before_edit_address_form_' ~ load_address) }}
|
||||
|
||||
<div class="woocommerce-address-fields__field-wrapper">
|
||||
{% for key, field in address %}
|
||||
{{ woocommerce_form_field(key, field, wc_get_post_data_by_key(key, field.value)) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_after_edit_address_form_' ~ load_address) }}
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-primary" name="save_address" value="{{ __('Save address') }}">
|
||||
<i class="bi bi-check-lg me-1" aria-hidden="true"></i>
|
||||
{{ __('Save address') }}
|
||||
</button>
|
||||
{{ wp_nonce_field('woocommerce-edit_address', 'woocommerce-edit-address-nonce') }}
|
||||
<input type="hidden" name="action" value="edit_address" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_after_edit_account_address_form') }}
|
||||
169
templates/myaccount/form-login.html.twig
Normal file
169
templates/myaccount/form-login.html.twig
Normal file
@@ -0,0 +1,169 @@
|
||||
{#
|
||||
# My Account Login / Register Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Login and optional registration form for the My Account page.
|
||||
# This is distinct from global/form-login.html.twig (inline checkout login).
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-login.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_customer_login_form') }}
|
||||
|
||||
{% set registration_enabled = get_option('woocommerce_enable_myaccount_registration') == 'yes' %}
|
||||
|
||||
<div class="row g-4" id="customer_login">
|
||||
<div class="{{ registration_enabled ? 'col-lg-6' : 'col-12' }}">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h2 class="h5 mb-0">{{ __('Login') }}</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="woocommerce-form woocommerce-form-login login" method="post" novalidate>
|
||||
|
||||
{{ do_action('woocommerce_login_form_start') }}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">
|
||||
{{ __('Username or email address') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="username"
|
||||
id="username"
|
||||
autocomplete="username"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">
|
||||
{{ __('Password') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
id="password"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_login_form') }}
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
name="rememberme"
|
||||
id="rememberme"
|
||||
value="forever" />
|
||||
<label class="form-check-label" for="rememberme">
|
||||
{{ __('Remember me') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{{ wp_nonce_field('woocommerce-login', 'woocommerce-login-nonce') }}
|
||||
|
||||
<button type="submit"
|
||||
class="btn btn-primary"
|
||||
name="login"
|
||||
value="{{ __('Log in') }}">
|
||||
{{ __('Log in') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="mb-0">
|
||||
<a href="{{ wp_lostpassword_url()|esc_url }}">{{ __('Lost your password?') }}</a>
|
||||
</p>
|
||||
|
||||
{{ do_action('woocommerce_login_form_end') }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if registration_enabled %}
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h2 class="h5 mb-0">{{ __('Register') }}</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="woocommerce-form woocommerce-form-register register" {{ do_action('woocommerce_register_form_tag') }}>
|
||||
|
||||
{{ do_action('woocommerce_register_form_start') }}
|
||||
|
||||
{% if get_option('woocommerce_registration_generate_username') == 'no' %}
|
||||
<div class="mb-3">
|
||||
<label for="reg_username" class="form-label">
|
||||
{{ __('Username') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="username"
|
||||
id="reg_username"
|
||||
autocomplete="username"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="reg_email" class="form-label">
|
||||
{{ __('Email address') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="email"
|
||||
class="form-control"
|
||||
name="email"
|
||||
id="reg_email"
|
||||
autocomplete="email"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
|
||||
{% if get_option('woocommerce_registration_generate_password') == 'no' %}
|
||||
<div class="mb-3">
|
||||
<label for="reg_password" class="form-label">
|
||||
{{ __('Password') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
id="reg_password"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-body-secondary mb-3">{{ __('A link to set a new password will be sent to your email address.') }}</p>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_register_form') }}
|
||||
|
||||
<div class="mt-3">
|
||||
{{ wp_nonce_field('woocommerce-register', 'woocommerce-register-nonce') }}
|
||||
<button type="submit"
|
||||
class="btn btn-primary"
|
||||
name="register"
|
||||
value="{{ __('Register') }}">
|
||||
{{ __('Register') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_register_form_end') }}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_after_customer_login_form') }}
|
||||
47
templates/myaccount/form-lost-password.html.twig
Normal file
47
templates/myaccount/form-lost-password.html.twig
Normal file
@@ -0,0 +1,47 @@
|
||||
{#
|
||||
# Lost Password Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Form to request a password reset email.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-lost-password.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_lost_password_form') }}
|
||||
|
||||
<form method="post" class="woocommerce-ResetPassword lost_reset_password">
|
||||
|
||||
<p class="mb-3">
|
||||
{{ apply_filters('woocommerce_lost_password_message', __('Lost your password? Please enter your username or email address. You will receive a link to create a new password via email.')) }}
|
||||
</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="user_login" class="form-label">
|
||||
{{ __('Username or email') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="user_login"
|
||||
id="user_login"
|
||||
autocomplete="username"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_lostpassword_form') }}
|
||||
|
||||
<div class="mt-3">
|
||||
<input type="hidden" name="wc_reset_password" value="true" />
|
||||
<button type="submit" class="btn btn-primary" value="{{ __('Reset password') }}">
|
||||
{{ __('Reset password') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ wp_nonce_field('lost_password', 'woocommerce-lost-password-nonce') }}
|
||||
|
||||
</form>
|
||||
|
||||
{{ do_action('woocommerce_after_lost_password_form') }}
|
||||
68
templates/myaccount/form-reset-password.html.twig
Normal file
68
templates/myaccount/form-reset-password.html.twig
Normal file
@@ -0,0 +1,68 @@
|
||||
{#
|
||||
# Reset Password Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Form to set a new password after clicking the reset link.
|
||||
#
|
||||
# Expected context:
|
||||
# args - Array with 'key' and 'login' values
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/form-reset-password.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_reset_password_form') }}
|
||||
|
||||
<form method="post" class="woocommerce-ResetPassword lost_reset_password">
|
||||
|
||||
<p class="mb-3">
|
||||
{{ apply_filters('woocommerce_reset_password_message', __('Enter a new password below.')) }}
|
||||
</p>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-sm-6">
|
||||
<label for="password_1" class="form-label">
|
||||
{{ __('New password') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password_1"
|
||||
id="password_1"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="password_2" class="form-label">
|
||||
{{ __('Re-enter new password') }} <span class="text-danger" aria-hidden="true">*</span>
|
||||
<span class="visually-hidden">{{ __('Required') }}</span>
|
||||
</label>
|
||||
<input type="password"
|
||||
class="form-control"
|
||||
name="password_2"
|
||||
id="password_2"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
aria-required="true" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="reset_key" value="{{ args.key|esc_attr }}" />
|
||||
<input type="hidden" name="reset_login" value="{{ args.login|esc_attr }}" />
|
||||
|
||||
{{ do_action('woocommerce_resetpassword_form') }}
|
||||
|
||||
<div class="mt-3">
|
||||
<input type="hidden" name="wc_reset_password" value="true" />
|
||||
<button type="submit" class="btn btn-primary" value="{{ __('Save') }}">
|
||||
{{ __('Save') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ wp_nonce_field('reset_password', 'woocommerce-reset-password-nonce') }}
|
||||
|
||||
</form>
|
||||
|
||||
{{ do_action('woocommerce_after_reset_password_form') }}
|
||||
23
templates/myaccount/lost-password-confirmation.html.twig
Normal file
23
templates/myaccount/lost-password-confirmation.html.twig
Normal file
@@ -0,0 +1,23 @@
|
||||
{#
|
||||
# Lost Password Confirmation (Bootstrap 5 Override)
|
||||
#
|
||||
# Confirmation text after password reset email has been sent.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/lost-password-confirmation.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
<div class="alert alert-success mb-4" role="alert">
|
||||
<i class="bi bi-check-circle me-2" aria-hidden="true"></i>
|
||||
{{ __('Password reset email has been sent.') }}
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_before_lost_password_confirmation_message') }}
|
||||
|
||||
<p>
|
||||
{{ apply_filters('woocommerce_lost_password_confirmation_message', __('A password reset email has been sent to the email address on file for your account, but may take several minutes to show up in your inbox. Please wait at least 10 minutes before attempting another reset.')) }}
|
||||
</p>
|
||||
|
||||
{{ do_action('woocommerce_after_lost_password_confirmation_message') }}
|
||||
27
templates/myaccount/my-account.html.twig
Normal file
27
templates/myaccount/my-account.html.twig
Normal file
@@ -0,0 +1,27 @@
|
||||
{#
|
||||
# My Account Page (Bootstrap 5 Override)
|
||||
#
|
||||
# Main wrapper for the My Account area. Renders sidebar navigation
|
||||
# and the current endpoint content.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/my-account.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_my_account') }}
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-3">
|
||||
{% include 'myaccount/navigation.html.twig' %}
|
||||
</div>
|
||||
|
||||
<div class="col-lg-9">
|
||||
<div class="woocommerce-MyAccount-content">
|
||||
{{ do_action('woocommerce_account_content') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_after_my_account') }}
|
||||
57
templates/myaccount/my-address.html.twig
Normal file
57
templates/myaccount/my-address.html.twig
Normal file
@@ -0,0 +1,57 @@
|
||||
{#
|
||||
# My Addresses (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows billing and shipping addresses as Bootstrap cards.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/my-address.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set customer_id = get_current_user_id() %}
|
||||
|
||||
{% if not wc_ship_to_billing_address_only() and wc_shipping_enabled() %}
|
||||
{% set get_addresses = apply_filters('woocommerce_my_account_get_addresses', {
|
||||
billing: __('Billing address'),
|
||||
shipping: __('Shipping address')
|
||||
}, customer_id) %}
|
||||
{% else %}
|
||||
{% set get_addresses = apply_filters('woocommerce_my_account_get_addresses', {
|
||||
billing: __('Billing address')
|
||||
}, customer_id) %}
|
||||
{% endif %}
|
||||
|
||||
<p class="text-body-secondary mb-4">
|
||||
{{ apply_filters('woocommerce_my_account_my_address_description', __('The following addresses will be used on the checkout page by default.')) }}
|
||||
</p>
|
||||
|
||||
<div class="row g-4">
|
||||
{% for name, address_title in get_addresses %}
|
||||
{% set address = wc_get_account_formatted_address(name) %}
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h3 class="h6 mb-0">{{ address_title|esc_html }}</h3>
|
||||
<a href="{{ wc_get_endpoint_url('edit-address', name)|esc_url }}" class="btn btn-sm btn-outline-primary">
|
||||
{% if address %}
|
||||
<i class="bi bi-pencil me-1" aria-hidden="true"></i>{{ __('Edit') }}
|
||||
{% else %}
|
||||
<i class="bi bi-plus me-1" aria-hidden="true"></i>{{ __('Add') }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<address class="mb-0">
|
||||
{% if address %}
|
||||
{{ address|wp_kses_post }}
|
||||
{% else %}
|
||||
<span class="text-body-secondary">{{ __('You have not set up this type of address yet.') }}</span>
|
||||
{% endif %}
|
||||
</address>
|
||||
{{ do_action('woocommerce_my_account_after_my_address', name) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
23
templates/myaccount/navigation.html.twig
Normal file
23
templates/myaccount/navigation.html.twig
Normal file
@@ -0,0 +1,23 @@
|
||||
{#
|
||||
# My Account Navigation (Bootstrap 5 Override)
|
||||
#
|
||||
# Renders the sidebar navigation for the My Account area
|
||||
# using Bootstrap list-group component.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/navigation.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
<nav class="woocommerce-MyAccount-navigation" aria-label="{{ __('Account navigation') }}">
|
||||
<div class="list-group">
|
||||
{% for endpoint, label in wc_get_account_menu_items() %}
|
||||
<a href="{{ wc_get_account_endpoint_url(endpoint)|esc_url }}"
|
||||
class="list-group-item list-group-item-action{% if wc_get_account_menu_item_classes(endpoint) matches '/is-active/' %} active{% endif %}"
|
||||
{% if wc_get_account_menu_item_classes(endpoint) matches '/is-active/' %}aria-current="page"{% endif %}>
|
||||
{{ label|esc_html }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</nav>
|
||||
126
templates/myaccount/orders.html.twig
Normal file
126
templates/myaccount/orders.html.twig
Normal file
@@ -0,0 +1,126 @@
|
||||
{#
|
||||
# My Account Orders (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows orders table on the account page with Bootstrap table styling.
|
||||
# HPOS compatible: uses WC_Order methods only.
|
||||
#
|
||||
# Expected context:
|
||||
# has_orders - boolean
|
||||
# customer_orders - object with .orders array and .max_num_pages
|
||||
# current_page - current pagination page number
|
||||
# wp_button_class - WP theme button class
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/orders.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{{ do_action('woocommerce_before_account_orders', has_orders) }}
|
||||
|
||||
{% if has_orders %}
|
||||
<div class="table-responsive">
|
||||
<table class="woocommerce-orders-table table table-hover align-middle mb-4">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
{% for column_id, column_name in wc_get_account_orders_columns() %}
|
||||
<th scope="col">{{ column_name|esc_html }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for customer_order in customer_orders.orders %}
|
||||
{% set order = wc_get_order(customer_order) %}
|
||||
{% set item_count = order.get_item_count() - order.get_item_count_refunded() %}
|
||||
<tr>
|
||||
{% for column_id, column_name in wc_get_account_orders_columns() %}
|
||||
{% if column_id == 'order-number' %}
|
||||
<th scope="row" data-title="{{ column_name|esc_attr }}">
|
||||
<a href="{{ order.get_view_order_url()|esc_url }}"
|
||||
aria-label="{{ __('View order number %s')|format(order.get_order_number()) }}">
|
||||
#{{ order.get_order_number()|esc_html }}
|
||||
</a>
|
||||
</th>
|
||||
{% elseif column_id == 'order-date' %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
<time datetime="{{ order.get_date_created().date('c')|esc_attr }}">
|
||||
{{ wc_format_datetime(order.get_date_created())|esc_html }}
|
||||
</time>
|
||||
</td>
|
||||
{% elseif column_id == 'order-status' %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
{% set status = order.get_status() %}
|
||||
{% if status == 'completed' %}
|
||||
<span class="badge text-bg-success">{{ wc_get_order_status_name(status)|esc_html }}</span>
|
||||
{% elseif status == 'processing' %}
|
||||
<span class="badge text-bg-primary">{{ wc_get_order_status_name(status)|esc_html }}</span>
|
||||
{% elseif status == 'on-hold' %}
|
||||
<span class="badge text-bg-warning">{{ wc_get_order_status_name(status)|esc_html }}</span>
|
||||
{% elseif status == 'cancelled' or status == 'failed' or status == 'refunded' %}
|
||||
<span class="badge text-bg-danger">{{ wc_get_order_status_name(status)|esc_html }}</span>
|
||||
{% else %}
|
||||
<span class="badge text-bg-secondary">{{ wc_get_order_status_name(status)|esc_html }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% elseif column_id == 'order-total' %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
{{ _n('%1$s for %2$s item', '%1$s for %2$s items', item_count)|format(order.get_formatted_order_total(), item_count)|wp_kses_post }}
|
||||
</td>
|
||||
{% elseif column_id == 'order-actions' %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
{% set actions = wc_get_account_orders_actions(order) %}
|
||||
{% if actions is not empty %}
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
{% for key, action in actions %}
|
||||
<a href="{{ action.url|esc_url }}"
|
||||
class="btn btn-outline-primary {{ key }}"
|
||||
aria-label="{{ action['aria-label']|default(__('%1$s order number %2$s')|format(action.name, order.get_order_number())) }}">
|
||||
{{ action.name|esc_html }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
{{ do_action('woocommerce_my_account_my_orders_column_' ~ column_id, order) }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_before_account_orders_pagination') }}
|
||||
|
||||
{% if customer_orders.max_num_pages > 1 %}
|
||||
<nav aria-label="{{ __('Order pagination') }}">
|
||||
<ul class="pagination justify-content-center">
|
||||
<li class="page-item{% if current_page == 1 %} disabled{% endif %}">
|
||||
<a class="page-link" href="{{ wc_get_endpoint_url('orders', current_page - 1)|esc_url }}"
|
||||
{% if current_page == 1 %}tabindex="-1" aria-disabled="true"{% endif %}>
|
||||
{{ __('Previous') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item{% if current_page == customer_orders.max_num_pages %} disabled{% endif %}">
|
||||
<a class="page-link" href="{{ wc_get_endpoint_url('orders', current_page + 1)|esc_url }}"
|
||||
{% if current_page == customer_orders.max_num_pages %}tabindex="-1" aria-disabled="true"{% endif %}>
|
||||
{{ __('Next') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle me-2" aria-hidden="true"></i>
|
||||
{{ __('No order has been made yet.') }}
|
||||
<a href="{{ apply_filters('woocommerce_return_to_shop_redirect', wc_get_page_permalink('shop'))|esc_url }}" class="alert-link">
|
||||
{{ __('Browse products') }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_after_account_orders', has_orders) }}
|
||||
78
templates/myaccount/payment-methods.html.twig
Normal file
78
templates/myaccount/payment-methods.html.twig
Normal file
@@ -0,0 +1,78 @@
|
||||
{#
|
||||
# Payment Methods (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows saved payment methods on the account page.
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/payment-methods.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set saved_methods = wc_get_customer_saved_methods_list(get_current_user_id()) %}
|
||||
{% set has_methods = saved_methods is not empty %}
|
||||
|
||||
{{ do_action('woocommerce_before_account_payment_methods', has_methods) }}
|
||||
|
||||
{% if has_methods %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-4">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
{% for column_id, column_name in wc_get_account_payment_methods_columns() %}
|
||||
<th>{{ column_name|esc_html }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for type, methods in saved_methods %}
|
||||
{% for method in methods %}
|
||||
<tr class="{% if method.is_default|default(false) %}table-active{% endif %}">
|
||||
{% for column_id, column_name in wc_get_account_payment_methods_columns() %}
|
||||
<td data-title="{{ column_name|esc_attr }}">
|
||||
{% if column_id == 'method' %}
|
||||
{% if method.method.last4 is defined and method.method.last4 %}
|
||||
{{ __('%1$s ending in %2$s')|format(wc_get_credit_card_type_label(method.method.brand)|esc_html, method.method.last4|esc_html) }}
|
||||
{% else %}
|
||||
{{ wc_get_credit_card_type_label(method.method.brand)|esc_html }}
|
||||
{% endif %}
|
||||
{% if method.is_default|default(false) %}
|
||||
<span class="badge text-bg-primary ms-1">{{ __('Default') }}</span>
|
||||
{% endif %}
|
||||
{% elseif column_id == 'expires' %}
|
||||
{{ method.expires|esc_html }}
|
||||
{% elseif column_id == 'actions' %}
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
{% for key, action in method.actions %}
|
||||
<a href="{{ action.url|esc_url }}"
|
||||
class="btn btn-outline-primary {{ key }}">
|
||||
{{ action.name|esc_html }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ do_action('woocommerce_account_payment_methods_column_' ~ column_id, method) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle me-2" aria-hidden="true"></i>
|
||||
{{ __('No saved methods found.') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_after_account_payment_methods', has_methods) }}
|
||||
|
||||
{% if fn('WC').payment_gateways.get_available_payment_gateways() is not empty %}
|
||||
<a href="{{ wc_get_endpoint_url('add-payment-method')|esc_url }}" class="btn btn-outline-primary">
|
||||
<i class="bi bi-plus-lg me-1" aria-hidden="true"></i>
|
||||
{{ __('Add payment method') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
45
templates/myaccount/view-order.html.twig
Normal file
45
templates/myaccount/view-order.html.twig
Normal file
@@ -0,0 +1,45 @@
|
||||
{#
|
||||
# View Order (Bootstrap 5 Override)
|
||||
#
|
||||
# Shows details of a specific order on the account page.
|
||||
# HPOS compatible: uses WC_Order methods only.
|
||||
#
|
||||
# Expected context:
|
||||
# order_id - Order ID
|
||||
# order - WC_Order object
|
||||
#
|
||||
# WooCommerce PHP equivalent: myaccount/view-order.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set notes = order.get_customer_order_notes() %}
|
||||
|
||||
<p>
|
||||
{{ __('Order #%1$s was placed on %2$s and is currently %3$s.')|format(
|
||||
'<mark class="order-number">' ~ order.get_order_number() ~ '</mark>',
|
||||
'<mark class="order-date">' ~ wc_format_datetime(order.get_date_created()) ~ '</mark>',
|
||||
'<mark class="order-status">' ~ wc_get_order_status_name(order.get_status()) ~ '</mark>'
|
||||
)|wp_kses_post }}
|
||||
</p>
|
||||
|
||||
{% if notes %}
|
||||
<h2 class="h5 mt-4 mb-3">{{ __('Order updates') }}</h2>
|
||||
<div class="list-group mb-4">
|
||||
{% for note in notes %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<small class="text-body-secondary">
|
||||
{{ date_i18n(__('l jS \\o\\f F Y, h:ia'), strtotime(note.comment_date)) }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
{{ wpautop(wptexturize(note.comment_content))|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_view_order', order_id) }}
|
||||
52
templates/order/form-tracking.html.twig
Normal file
52
templates/order/form-tracking.html.twig
Normal file
@@ -0,0 +1,52 @@
|
||||
{#
|
||||
# Order Tracking Form (Bootstrap 5 Override)
|
||||
#
|
||||
# Form to look up an order by ID and billing email.
|
||||
#
|
||||
# WooCommerce PHP equivalent: order/form-tracking.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
<form action="{{ get_permalink()|esc_url }}" method="post" class="woocommerce-form woocommerce-form-track-order track_order">
|
||||
|
||||
{{ do_action('woocommerce_order_tracking_form_start') }}
|
||||
|
||||
<p class="mb-3">
|
||||
{{ __('To track your order please enter your Order ID in the box below and press the "Track" button. This was given to you on your receipt and in the confirmation email you should have received.') }}
|
||||
</p>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-sm-6">
|
||||
<label for="orderid" class="form-label">{{ __('Order ID') }}</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
name="orderid"
|
||||
id="orderid"
|
||||
placeholder="{{ __('Found in your order confirmation email.') }}" />
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label for="order_email" class="form-label">{{ __('Billing email') }}</label>
|
||||
<input type="email"
|
||||
class="form-control"
|
||||
name="order_email"
|
||||
id="order_email"
|
||||
placeholder="{{ __('Email you used during checkout.') }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_order_tracking_form') }}
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-primary" name="track" value="{{ __('Track') }}">
|
||||
<i class="bi bi-search me-1" aria-hidden="true"></i>
|
||||
{{ __('Track') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ wp_nonce_field('woocommerce-order_tracking', 'woocommerce-order-tracking-nonce') }}
|
||||
|
||||
{{ do_action('woocommerce_order_tracking_form_end') }}
|
||||
|
||||
</form>
|
||||
20
templates/order/order-again.html.twig
Normal file
20
templates/order/order-again.html.twig
Normal file
@@ -0,0 +1,20 @@
|
||||
{#
|
||||
# Order Again Button (Bootstrap 5 Override)
|
||||
#
|
||||
# Renders a button to reorder a previous order.
|
||||
#
|
||||
# Expected context:
|
||||
# order_again_url - URL to reorder
|
||||
#
|
||||
# WooCommerce PHP equivalent: order/order-again.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
<p class="order-again mt-3">
|
||||
<a href="{{ order_again_url|esc_url }}" class="btn btn-outline-primary">
|
||||
<i class="bi bi-arrow-repeat me-1" aria-hidden="true"></i>
|
||||
{{ __('Order again') }}
|
||||
</a>
|
||||
</p>
|
||||
75
templates/order/order-details-customer.html.twig
Normal file
75
templates/order/order-details-customer.html.twig
Normal file
@@ -0,0 +1,75 @@
|
||||
{#
|
||||
# Order Details Customer (Bootstrap 5 Override)
|
||||
#
|
||||
# Displays billing and shipping addresses for a completed order.
|
||||
# HPOS compatible: uses WC_Order methods only.
|
||||
#
|
||||
# Expected context:
|
||||
# order - WC_Order object
|
||||
#
|
||||
# WooCommerce PHP equivalent: order/order-details-customer.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set show_shipping = not wc_ship_to_billing_address_only() and order.needs_shipping_address() %}
|
||||
|
||||
<section class="woocommerce-customer-details mt-4">
|
||||
<div class="row g-4">
|
||||
<div class="{{ show_shipping ? 'col-md-6' : 'col-12' }}">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h3 class="h6 mb-0">{{ __('Billing address') }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<address class="mb-0">
|
||||
{{ order.get_formatted_billing_address(__('N/A'))|wp_kses_post }}
|
||||
|
||||
{% if order.get_billing_phone() %}
|
||||
<p class="woocommerce-customer-details--phone mt-2 mb-0">
|
||||
<i class="bi bi-telephone me-1" aria-hidden="true"></i>
|
||||
{{ order.get_billing_phone()|esc_html }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if order.get_billing_email() %}
|
||||
<p class="woocommerce-customer-details--email mt-1 mb-0">
|
||||
<i class="bi bi-envelope me-1" aria-hidden="true"></i>
|
||||
{{ order.get_billing_email()|esc_html }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_order_details_after_customer_address', 'billing', order) }}
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if show_shipping %}
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h3 class="h6 mb-0">{{ __('Shipping address') }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<address class="mb-0">
|
||||
{{ order.get_formatted_shipping_address(__('N/A'))|wp_kses_post }}
|
||||
|
||||
{% if order.get_shipping_phone() %}
|
||||
<p class="woocommerce-customer-details--phone mt-2 mb-0">
|
||||
<i class="bi bi-telephone me-1" aria-hidden="true"></i>
|
||||
{{ order.get_shipping_phone()|esc_html }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{{ do_action('woocommerce_order_details_after_customer_address', 'shipping', order) }}
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_order_details_after_customer_details', order) }}
|
||||
</section>
|
||||
63
templates/order/order-details-item.html.twig
Normal file
63
templates/order/order-details-item.html.twig
Normal file
@@ -0,0 +1,63 @@
|
||||
{#
|
||||
# Order Details Item (Bootstrap 5 Override)
|
||||
#
|
||||
# Renders a single line item row within the order details table.
|
||||
# HPOS compatible: uses WC_Order methods only.
|
||||
#
|
||||
# Expected context:
|
||||
# order - WC_Order object
|
||||
# item_id - Item ID
|
||||
# item - WC_Order_Item_Product object
|
||||
# show_purchase_note - Whether to show purchase note
|
||||
# purchase_note - Purchase note text
|
||||
# product - WC_Product object or null
|
||||
#
|
||||
# WooCommerce PHP equivalent: order/order-details-item.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% if not apply_filters('woocommerce_order_item_visible', true, item) %}
|
||||
{% do return() %}
|
||||
{% endif %}
|
||||
|
||||
{% set is_visible = product and product.is_visible() %}
|
||||
{% set product_permalink = apply_filters('woocommerce_order_item_permalink', is_visible ? product.get_permalink(item) : '', item, order) %}
|
||||
|
||||
<tr class="{{ apply_filters('woocommerce_order_item_class', 'woocommerce-table__line-item order_item', item, order) }}">
|
||||
<td class="product-name">
|
||||
{% if product_permalink %}
|
||||
<a href="{{ product_permalink|esc_url }}">{{ item.get_name()|esc_html }}</a>
|
||||
{% else %}
|
||||
{{ item.get_name()|esc_html }}
|
||||
{% endif %}
|
||||
|
||||
{% set qty = item.get_quantity() %}
|
||||
{% set refunded_qty = order.get_qty_refunded_for_item(item_id) %}
|
||||
|
||||
<strong class="product-quantity">
|
||||
{% if refunded_qty %}
|
||||
× <del>{{ qty }}</del> <ins>{{ qty - (refunded_qty * -1) }}</ins>
|
||||
{% else %}
|
||||
× {{ qty }}
|
||||
{% endif %}
|
||||
</strong>
|
||||
|
||||
{{ do_action('woocommerce_order_item_meta_start', item_id, item, order, false) }}
|
||||
{{ wc_display_item_meta(item) }}
|
||||
{{ do_action('woocommerce_order_item_meta_end', item_id, item, order, false) }}
|
||||
</td>
|
||||
|
||||
<td class="product-total text-end">
|
||||
{{ order.get_formatted_line_subtotal(item)|raw }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if show_purchase_note and purchase_note %}
|
||||
<tr class="product-purchase-note">
|
||||
<td colspan="2">
|
||||
{{ purchase_note|wp_kses_post|wpautop }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
91
templates/order/order-details.html.twig
Normal file
91
templates/order/order-details.html.twig
Normal file
@@ -0,0 +1,91 @@
|
||||
{#
|
||||
# Order Details (Bootstrap 5 Override)
|
||||
#
|
||||
# Renders the full order details table with items, totals, and customer info.
|
||||
# HPOS compatible: uses WC_Order methods only.
|
||||
#
|
||||
# Expected context:
|
||||
# order_id - Order ID
|
||||
# show_downloads - Whether to show downloads table
|
||||
#
|
||||
# WooCommerce PHP equivalent: order/order-details.php
|
||||
#
|
||||
# @package WcBootstrap
|
||||
# @since 0.1.0
|
||||
#}
|
||||
|
||||
{% set order = wc_get_order(order_id) %}
|
||||
|
||||
{% if not order %}
|
||||
{% do return() %}
|
||||
{% endif %}
|
||||
|
||||
{% set order_items = order.get_items(apply_filters('woocommerce_purchase_order_item_types', 'line_item')) %}
|
||||
{% set show_purchase_note = order.has_status(apply_filters('woocommerce_purchase_note_order_statuses', ['completed', 'processing'])) %}
|
||||
{% set show_customer_details = order.get_user_id() == get_current_user_id() %}
|
||||
|
||||
{% if show_downloads is defined and show_downloads %}
|
||||
{% set downloads = order.get_downloadable_items() %}
|
||||
{% if downloads is not empty %}
|
||||
{{ wc_get_template('order/order-downloads.php', { downloads: downloads, show_title: true }) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<section class="woocommerce-order-details">
|
||||
{{ do_action('woocommerce_order_details_before_order_table', order) }}
|
||||
|
||||
<h2 class="h5 mb-3">{{ __('Order details') }}</h2>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>{{ __('Product') }}</th>
|
||||
<th class="text-end">{{ __('Total') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{ do_action('woocommerce_order_details_before_order_table_items', order) }}
|
||||
|
||||
{% for item_id, item in order_items %}
|
||||
{% set product = item.get_product() %}
|
||||
{% include 'order/order-details-item.html.twig' with {
|
||||
order: order,
|
||||
item_id: item_id,
|
||||
item: item,
|
||||
show_purchase_note: show_purchase_note,
|
||||
purchase_note: product ? product.get_purchase_note() : '',
|
||||
product: product
|
||||
} %}
|
||||
{% endfor %}
|
||||
|
||||
{{ do_action('woocommerce_order_details_after_order_table_items', order) }}
|
||||
</tbody>
|
||||
|
||||
<tfoot>
|
||||
{% for key, total in order.get_order_item_totals() %}
|
||||
<tr>
|
||||
<th scope="row">{{ total.label|esc_html }}</th>
|
||||
<td class="text-end">{{ total.value|wp_kses_post }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% if order.get_customer_note() %}
|
||||
<tr>
|
||||
<th>{{ __('Note:') }}</th>
|
||||
<td class="text-end">{{ order.get_customer_note()|nl2br|esc_html }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ do_action('woocommerce_order_details_after_order_table', order) }}
|
||||
</section>
|
||||
|
||||
{{ do_action('woocommerce_after_order_details', order) }}
|
||||
|
||||
{% if show_customer_details %}
|
||||
{% include 'order/order-details-customer.html.twig' with { order: order } %}
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user