forked from alaguraj/odoo-testing-addons
Implement pickup/delivery order type selection on checkout, customizing address fields and removing the old service mode template.
This commit is contained in:
parent
1ab45b9ba7
commit
2478823569
@ -1,41 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="cart_service_mode" inherit_id="website_sale.cart" name="Service Mode Selector" priority="1000">
|
||||
<xpath expr="//div[hasclass('col')]/h3" position="before">
|
||||
<div class="container container-fluid mt-4">
|
||||
<div id="service_mode_selector" class="mb-4 bg-white p-3 p-md-4 rounded-4 shadow-sm border" style="border-left: 5px solid #FECD4F !important;">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-warning-light p-2 rounded-circle me-3">
|
||||
<i class="fa fa-shopping-basket text-warning fs-5"></i>
|
||||
</div>
|
||||
<h4 class="mb-0 fw-bold">How would you like your order?</h4>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 gap-md-3">
|
||||
<label class="service-option position-relative flex-fill cursor-pointer m-0">
|
||||
<input type="radio" name="fulfilment_type" value="pickup" class="d-none" t-att-checked="'checked' if website_sale_order and website_sale_order.fulfilment_type == 'pickup' else None"/>
|
||||
<div class="service-card p-3 rounded-3 border text-center transition-all h-100 d-flex flex-column justify-content-center">
|
||||
<i class="fa fa-shopping-bag mb-2 text-warning"></i>
|
||||
<div class="fw-bold h6 mb-1">Pickup</div>
|
||||
<div class="x-small text-muted">Ready in 15-20 mins</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="service-option position-relative flex-fill cursor-pointer m-0">
|
||||
<input type="radio" name="fulfilment_type" value="delivery" class="d-none" t-att-checked="'checked' if website_sale_order and website_sale_order.fulfilment_type == 'delivery' else None"/>
|
||||
<div class="service-card p-3 rounded-3 border text-center transition-all h-100 d-flex flex-column justify-content-center">
|
||||
<i class="fa fa-truck mb-2 text-primary"></i>
|
||||
<div class="fw-bold h6 mb-1">Delivery</div>
|
||||
<div class="x-small text-muted">Estimated 30-45 mins</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 small text-danger d-none" id="service_mode_error">
|
||||
<i class="fa fa-exclamation-circle me-1"></i> Please select Pickup or Delivery to continue.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
<!-- Removed cart_service_mode template as requested by user to move it to checkout page -->
|
||||
</odoo>
|
||||
|
||||
@ -31,10 +31,198 @@
|
||||
<h3 class="mb-3">Address Details</h3>
|
||||
</xpath>
|
||||
|
||||
<!-- Pickup / Delivery Order Type Toggle -->
|
||||
<xpath expr="//form[contains(@class, 'checkout_autoformat')]" position="before">
|
||||
<div class="checkout-order-type-selector mb-5 mt-4">
|
||||
<style>
|
||||
.order-type-card {
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
background: #fff;
|
||||
}
|
||||
.order-type-card:hover {
|
||||
border-color: #FECD4F;
|
||||
background: #fffbf0;
|
||||
}
|
||||
.order-type-input:checked + .order-type-card {
|
||||
border-color: #2BB1A5;
|
||||
background: #f0fdfc;
|
||||
box-shadow: 0 4px 15px rgba(43, 177, 165, 0.15);
|
||||
}
|
||||
.order-type-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f8f9fa;
|
||||
border-radius: 50%;
|
||||
font-size: 20px;
|
||||
color: #04121D;
|
||||
}
|
||||
.order-type-input:checked + .order-type-card .order-type-icon {
|
||||
background: #2BB1A5;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Aggressive hiding for pickup fields to prevent empty space */
|
||||
form.is-pickup-mode .div_street,
|
||||
form.is-pickup-mode .div_street2,
|
||||
form.is-pickup-mode .div_city,
|
||||
form.is-pickup-mode .div_zip,
|
||||
form.is-pickup-mode .div_country,
|
||||
form.is-pickup-mode .div_state,
|
||||
form.is-pickup-mode div:has(> label[for="street"]),
|
||||
form.is-pickup-mode div:has(> label[for="street2"]),
|
||||
form.is-pickup-mode div:has(> label[for="city"]),
|
||||
form.is-pickup-mode div:has(> label[for="zip"]),
|
||||
form.is-pickup-mode div:has(> label[for="country_id"]),
|
||||
form.is-pickup-mode div:has(> label[for="state_id"]) {
|
||||
display: none !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<input type="radio" name="delivery_method_switch" id="method_delivery" class="d-none order-type-input" value="delivery" checked="checked"/>
|
||||
<label for="method_delivery" class="order-type-card w-100 m-0">
|
||||
<div class="order-type-icon">
|
||||
<i class="fa fa-truck"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="mb-1 fw-bold" style="color: #04121D;">Delivery</h5>
|
||||
<small class="text-muted">Deliver to my address</small>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="radio" name="delivery_method_switch" id="method_pickup" class="d-none order-type-input" value="pickup"/>
|
||||
<label for="method_pickup" class="order-type-card w-100 m-0">
|
||||
<div class="order-type-icon">
|
||||
<i class="fa fa-shopping-bag"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="mb-1 fw-bold" style="color: #04121D;">Store Pickup</h5>
|
||||
<small class="text-muted">Pick up at the restaurant</small>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const typeDelivery = document.getElementById('method_delivery');
|
||||
const typePickup = document.getElementById('method_pickup');
|
||||
const streetInput = document.querySelector('input[name="street"]');
|
||||
const cityInput = document.querySelector('input[name="city"]');
|
||||
const zipInput = document.querySelector('input[name="zip"]');
|
||||
const countrySelect = document.querySelector('select[name="country_id"]');
|
||||
const stateSelect = document.querySelector('select[name="state_id"]');
|
||||
const formElement = document.querySelector('form.checkout_autoformat');
|
||||
|
||||
const allRequiredInputs = [streetInput, cityInput, zipInput, countrySelect, stateSelect];
|
||||
|
||||
function applyMethod() {
|
||||
if(typePickup.checked) {
|
||||
if(formElement) formElement.classList.add('is-pickup-mode');
|
||||
|
||||
// Remove "required" so HTML5 validation doesn't block submission
|
||||
allRequiredInputs.forEach(input => {
|
||||
if (input) {
|
||||
if (input.hasAttribute('required') || input.dataset.wasRequired) {
|
||||
input.dataset.wasRequired = 'true';
|
||||
input.removeAttribute('required');
|
||||
input.classList.remove('s_website_form_required');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add dummy values exactly when they are blank
|
||||
if(streetInput && !streetInput.value) { streetInput.value = 'In-Store Pickup'; }
|
||||
if(cityInput && !cityInput.value) { cityInput.value = 'Brampton'; }
|
||||
if(zipInput && (!zipInput.value || zipInput.value === '')) { zipInput.value = 'L6Y0N1'; }
|
||||
|
||||
// For country, just select Canada or first available if blank
|
||||
if(countrySelect && (!countrySelect.value || countrySelect.value == "")) {
|
||||
let caOption = Array.from(countrySelect.options).find(o => o.text.includes('Canada'));
|
||||
if (caOption) {
|
||||
countrySelect.value = caOption.value;
|
||||
} else if (countrySelect.options.length > 1) {
|
||||
countrySelect.selectedIndex = 1;
|
||||
}
|
||||
countrySelect.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
// Ensure state is set if country is Canada
|
||||
if(stateSelect && countrySelect && countrySelect.options[countrySelect.selectedIndex]?.text.includes('Canada')) {
|
||||
if(!stateSelect.value || stateSelect.value == "") {
|
||||
let onOption = Array.from(stateSelect.options).find(o => o.text.includes('Ontario'));
|
||||
if(onOption) { stateSelect.value = onOption.value; }
|
||||
else if (stateSelect.options.length > 1) { stateSelect.selectedIndex = 1; }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(formElement) formElement.classList.remove('is-pickup-mode');
|
||||
|
||||
// Restore required state
|
||||
allRequiredInputs.forEach(input => {
|
||||
if (input && input.dataset.wasRequired === 'true') {
|
||||
input.setAttribute('required', 'required');
|
||||
input.classList.add('s_website_form_required');
|
||||
}
|
||||
});
|
||||
|
||||
// Revert dummy values so user can type real ones
|
||||
if(streetInput && streetInput.value === 'In-Store Pickup') { streetInput.value = ''; }
|
||||
if(cityInput && cityInput.value === 'Brampton') { cityInput.value = ''; }
|
||||
if(zipInput && zipInput.value === 'L6Y0N1') { zipInput.value = ''; }
|
||||
}
|
||||
}
|
||||
|
||||
if (typeDelivery && typePickup) {
|
||||
typeDelivery.addEventListener('change', applyMethod);
|
||||
typePickup.addEventListener('change', applyMethod);
|
||||
|
||||
// Remember state if validation fails
|
||||
const savedMethod = sessionStorage.getItem('chennora_checkout_method');
|
||||
if (savedMethod === 'pickup') {
|
||||
typePickup.checked = true;
|
||||
}
|
||||
|
||||
// Initial run
|
||||
applyMethod();
|
||||
|
||||
typePickup.addEventListener('change', () => sessionStorage.setItem('chennora_checkout_method', 'pickup'));
|
||||
typeDelivery.addEventListener('change', () => sessionStorage.setItem('chennora_checkout_method', 'delivery'));
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</xpath>
|
||||
|
||||
|
||||
|
||||
<!-- 9. Remove the "Be aware!" warning box (Already removed or hidden) -->
|
||||
<!-- <xpath expr="//div[contains(@class, 'alert-warning') and .//h4[contains(., 'Be aware')]]" position="replace"/> -->
|
||||
</template>
|
||||
|
||||
<!-- Change Billing & Shipping Label on Payment Page -->
|
||||
<template id="chennora_address_on_payment_custom" inherit_id="website_sale.address_on_payment" name="Chennora Address Label Custom" priority="99">
|
||||
<xpath expr="//div[@id='shipping_and_billing']//b[contains(., 'Billing')]" position="replace">
|
||||
<b>Billing: </b>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Custom Checkout Page - Remove Shipping Section entirely -->
|
||||
<template id="chennora_checkout_custom" inherit_id="website_sale.checkout" name="Chennora Checkout Custom" priority="99">
|
||||
<!-- 1. Remove the "Billing" sub-header -->
|
||||
@ -49,14 +237,19 @@
|
||||
<xpath expr="//t[@groups='account.group_delivery_invoice_address']" position="replace"/>
|
||||
</template>
|
||||
|
||||
<!-- Custom Wizard - Rename Shipping step to Address -->
|
||||
<!-- Custom Wizard - Rename Shipping step to Billing safely without python errors -->
|
||||
<template id="chennora_wizard_checkout_custom" inherit_id="website_sale.wizard_checkout" name="Chennora Wizard Custom" priority="99">
|
||||
<xpath expr="//*[@t-call='website.step_wizard']" position="before">
|
||||
<t t-foreach="wizard_step" t-as="step">
|
||||
<t t-if="step[1].get('name') == 'Shipping'">
|
||||
<t t-set="dummy" t-value="step[1].update({'name': 'Address'})"/>
|
||||
</t>
|
||||
</t>
|
||||
<xpath expr="//*[@t-call='website.step_wizard']" position="after">
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const steps = document.querySelectorAll('.nav-wizard .nav-item .nav-link .text-truncate, .nav-wizard .text-truncate');
|
||||
steps.forEach(node => {
|
||||
if (node.innerText.trim() === 'Shipping') {
|
||||
node.innerText = 'Billing';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user