diff --git a/addons/dine360_theme_chennora/views/checkout_address.xml b/addons/dine360_theme_chennora/views/checkout_address.xml index 0a1f710..a8116f0 100644 --- a/addons/dine360_theme_chennora/views/checkout_address.xml +++ b/addons/dine360_theme_chennora/views/checkout_address.xml @@ -84,11 +84,6 @@ -
Preferred Greeting / Timing
-
- -
-
Contact Details
@@ -106,8 +101,105 @@ function initUnifiedForm() { const hiddenType = document.getElementById('hidden_fulfilment_type'); const msgDiv = document.getElementById('uber_message'); - const submitBtn = document.querySelector('button[type="submit"]') || document.querySelector('.btn-primary'); + const submitBtn = document.querySelector('button[type="submit"]') || document.querySelector('.btn-primary') || document.querySelector('.s_website_form_send'); let debounceTimer; + + // Force Name, Email, and Phone to be required + ['name', 'email', 'phone'].forEach(fieldName => { + const input = document.querySelector(`form.checkout_autoformat [name="${fieldName}"]`); + if (input) input.setAttribute('required', 'required'); + }); + + // 1. Add prominent red required icons to labels + document.querySelectorAll('form.checkout_autoformat .control-label, form.checkout_autoformat label').forEach(label => { + const inputId = label.getAttribute('for'); + const input = inputId ? document.getElementById(inputId) : label.closest('.mb-3')?.querySelector('input, select'); + if (input && input.hasAttribute('required') && !label.querySelector('.fa-asterisk')) { + label.innerHTML += ' '; + } + }); + + // 2. Clear error state on input change (Real-time update) + document.querySelectorAll('form.checkout_autoformat input, form.checkout_autoformat select').forEach(input => { + const handler = function() { + const val = this.value ? this.value.trim() : ""; + // Check if the field is actually filled (0 is valid for select if it's not the placeholder) + const isFilled = val && val !== "0" && val !== ""; + + if (isFilled) { + this.classList.remove('is-invalid'); + this.style.borderColor = ''; + + // Update the summary error list dynamically + const form = this.closest('form'); + const errorDiv = document.getElementById('chennora_val_error'); + if (errorDiv) { + const stillInvalid = form.querySelectorAll('.is-invalid'); + if (stillInvalid.length === 0) { + errorDiv.style.display = 'none'; + } else { + let missingNames = []; + stillInvalid.forEach(inv => { + const l = form.querySelector(`label[for="${inv.name}"]`) || inv.closest('.mb-3')?.querySelector('label'); + missingNames.push(l ? l.textContent.replace('*', '').trim() : inv.name); + }); + errorDiv.innerHTML = `Missing Required Fields:
${missingNames.join(', ')}`; + } + } + } + }; + input.addEventListener('input', handler); + input.addEventListener('change', handler); + }); + + // 3. Custom Validation on Submit + if (submitBtn) { + submitBtn.addEventListener('click', function(e) { + const form = document.querySelector('form.checkout_autoformat'); + if (!form) return; + + // Reset errors before checking + let missingFields = []; + const requiredInputs = form.querySelectorAll('input[required]:not([type="hidden"]), select[required]'); + + requiredInputs.forEach(input => { + // Skip hidden fields (from pickup/delivery toggle or company hide) + const container = input.closest('div[class*="col-"], .mb-3'); + if (container && container.style.display === 'none') return; + if (input.name === 'company_name' || input.name === 'vat') return; + + const val = input.value ? input.value.trim() : ""; + const isMissing = !val || val === "0" || val === ""; + + if (isMissing) { + const label = form.querySelector(`label[for="${input.name}"]`) || input.closest('.mb-3')?.querySelector('label'); + const fieldName = label ? label.textContent.replace('*', '').trim() : input.name; + missingFields.push(fieldName); + input.classList.add('is-invalid'); + input.style.borderColor = '#dc3545'; + } else { + input.classList.remove('is-invalid'); + input.style.borderColor = ''; + } + }); + + if (missingFields.length > 0) { + e.preventDefault(); + e.stopPropagation(); + + let errorDiv = document.getElementById('chennora_val_error'); + if (!errorDiv) { + errorDiv = document.createElement('div'); + errorDiv.id = 'chennora_val_error'; + errorDiv.className = 'alert alert-danger mt-3 animated fadeIn'; + form.insertBefore(errorDiv, form.firstChild); + } + errorDiv.style.display = 'block'; + errorDiv.innerHTML = `Missing Required Fields:
${missingFields.join(', ')}`; + errorDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }); + } function getAddressContainers() { const addressNames = ['street', 'street2', 'city', 'zip', 'country_id', 'state_id']; @@ -143,11 +235,19 @@ containers.forEach(c => c.style.display = 'none'); if (addrHeader) addrHeader.style.display = 'none'; if (msgDiv) msgDiv.style.display = 'none'; - if (submitBtn) submitBtn.disabled = false; + // Remove required for pickup + containers.forEach(c => { + c.querySelectorAll('input, select').forEach(i => i.removeAttribute('required')); + }); } else { containers.forEach(c => c.style.display = ''); if (addrHeader) addrHeader.style.display = ''; if (msgDiv) msgDiv.style.display = ''; + // Restore required + ['street', 'city', 'zip', 'country_id', 'state_id'].forEach(name => { + const i = document.querySelector(`[name="${name}"]`); + if (i) i.setAttribute('required', 'required'); + }); checkUber(); } };