335 lines
12 KiB
JavaScript
335 lines
12 KiB
JavaScript
const audienceContent = {
|
||
home: 'Артезианская вода 19 литров с доставкой на дом и в офис. Привозим по Гагаринскому, Ленинскому, Нахимовскому и Балаклавскому районам, помогаем с возвратной тарой и держим понятные цены без скрытых доплат.',
|
||
office: 'Доставка воды в офис в Севастополе с регулярным графиком, безналичной оплатой и приоритетными интервалами. Подходит для команд, кафе, студий, фитнес-клубов и клиентских пространств.'
|
||
}
|
||
|
||
const audienceButtons = document.querySelectorAll('[data-audience]')
|
||
const heroAudienceText = document.getElementById('heroAudienceText')
|
||
const mobileToggle = document.getElementById('mobileToggle')
|
||
const mobilePanel = document.getElementById('mobilePanel')
|
||
const cartDrawer = document.getElementById('cartDrawer')
|
||
const cartOpenButton = document.getElementById('cartOpenButton')
|
||
const mobileCartOpenButton = document.getElementById('mobileCartOpenButton')
|
||
const cartCloseButton = document.getElementById('cartCloseButton')
|
||
const modalBackdrop = document.getElementById('orderModal')
|
||
const modalCloseButton = document.getElementById('modalCloseButton')
|
||
const viewCartButton = document.getElementById('viewCartButton')
|
||
const checkoutButton = document.getElementById('checkoutButton')
|
||
const orderButtons = document.querySelectorAll('[data-open-order]')
|
||
const addToCartButtons = document.querySelectorAll('.add-to-cart')
|
||
const faqItems = document.querySelectorAll('.faq-item')
|
||
const cartCount = document.getElementById('cartCount')
|
||
const mobileCartCount = document.getElementById('mobileCartCount')
|
||
const cartItemsCount = document.getElementById('cartItemsCount')
|
||
const cartTotal = document.getElementById('cartTotal')
|
||
const cartList = document.getElementById('cartList')
|
||
const orderForm = document.getElementById('orderForm')
|
||
const contactForm = document.getElementById('contactForm')
|
||
const orderItemsField = document.getElementById('orderItemsField')
|
||
const orderSuccess = document.getElementById('orderSuccess')
|
||
const contactSuccess = document.getElementById('contactSuccess')
|
||
const wooCommerceConfig = window.test1WooCommerce || null
|
||
const cartPanel = cartDrawer?.querySelector('.cart-panel')
|
||
const modalCard = modalBackdrop?.querySelector('.modal-card')
|
||
|
||
let cart = []
|
||
let lastCartTrigger = null
|
||
let lastModalTrigger = null
|
||
|
||
const getFocusableElements = container => {
|
||
if (!container) {
|
||
return []
|
||
}
|
||
|
||
return Array.from(container.querySelectorAll('a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'))
|
||
.filter(element => !element.hasAttribute('hidden') && !element.closest('[hidden]'))
|
||
}
|
||
|
||
const focusFirstElement = container => {
|
||
const [first] = getFocusableElements(container)
|
||
|
||
if (first) {
|
||
first.focus()
|
||
}
|
||
}
|
||
|
||
const updateAudience = audience => {
|
||
heroAudienceText.textContent = audienceContent[audience]
|
||
audienceButtons.forEach(button => {
|
||
const isActive = button.dataset.audience === audience
|
||
button.classList.toggle('active', isActive)
|
||
button.setAttribute('aria-selected', String(isActive))
|
||
})
|
||
const typeField = orderForm.elements.customerType
|
||
typeField.value = audience === 'office' ? 'Для офиса' : 'Для дома'
|
||
}
|
||
|
||
const openMobileMenu = () => {
|
||
mobilePanel.classList.add('active')
|
||
mobileToggle.setAttribute('aria-expanded', 'true')
|
||
document.body.classList.add('menu-open')
|
||
}
|
||
|
||
const closeMobileMenu = () => {
|
||
mobilePanel.classList.remove('active')
|
||
mobileToggle.setAttribute('aria-expanded', 'false')
|
||
document.body.classList.remove('menu-open')
|
||
}
|
||
|
||
const openCart = triggerElement => {
|
||
lastCartTrigger = triggerElement || document.activeElement
|
||
cartDrawer.classList.add('open')
|
||
cartDrawer.setAttribute('aria-hidden', 'false')
|
||
document.body.classList.add('modal-open')
|
||
focusFirstElement(cartPanel)
|
||
}
|
||
|
||
const closeCart = () => {
|
||
const shouldRestoreFocus = cartDrawer.classList.contains('open')
|
||
cartDrawer.classList.remove('open')
|
||
cartDrawer.setAttribute('aria-hidden', 'true')
|
||
document.body.classList.remove('modal-open')
|
||
|
||
if (shouldRestoreFocus && lastCartTrigger && typeof lastCartTrigger.focus === 'function') {
|
||
lastCartTrigger.focus()
|
||
}
|
||
|
||
lastCartTrigger = null
|
||
}
|
||
|
||
const openModal = triggerElement => {
|
||
lastModalTrigger = triggerElement || document.activeElement
|
||
orderItemsField.value = cart.length
|
||
? cart.map(item => `${item.name} (${item.volume}) - ${item.price} ₽`).join('\n')
|
||
: ''
|
||
modalBackdrop.classList.add('open')
|
||
modalBackdrop.setAttribute('aria-hidden', 'false')
|
||
document.body.classList.add('modal-open')
|
||
focusFirstElement(modalCard)
|
||
}
|
||
|
||
const closeModal = () => {
|
||
const shouldRestoreFocus = modalBackdrop.classList.contains('open')
|
||
modalBackdrop.classList.remove('open')
|
||
modalBackdrop.setAttribute('aria-hidden', 'true')
|
||
document.body.classList.remove('modal-open')
|
||
|
||
if (shouldRestoreFocus && lastModalTrigger && typeof lastModalTrigger.focus === 'function') {
|
||
lastModalTrigger.focus()
|
||
}
|
||
|
||
lastModalTrigger = null
|
||
}
|
||
|
||
const renderCart = () => {
|
||
const total = cart.reduce((sum, item) => sum + item.price, 0)
|
||
const count = cart.length
|
||
|
||
cartCount.textContent = count
|
||
mobileCartCount.textContent = count
|
||
cartItemsCount.textContent = count
|
||
cartTotal.textContent = `${total} ₽`
|
||
|
||
if (!count) {
|
||
cartList.innerHTML = '<div class="empty-state">Корзина пока пуста. Добавьте воду 19 литров, компактные форматы или минеральную воду из каталога.</div>'
|
||
return
|
||
}
|
||
|
||
cartList.innerHTML = cart.map((item, index) => `
|
||
<div class="cart-item">
|
||
<div>
|
||
<strong>${item.name}</strong>
|
||
<span>${item.volume} · ${item.price} ₽</span>
|
||
</div>
|
||
<button type="button" data-remove-index="${index}" aria-label="Удалить ${item.name} из корзины">Удалить</button>
|
||
</div>
|
||
`).join('')
|
||
|
||
cartList.querySelectorAll('[data-remove-index]').forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const index = Number(button.dataset.removeIndex)
|
||
cart.splice(index, 1)
|
||
renderCart()
|
||
})
|
||
})
|
||
}
|
||
|
||
audienceButtons.forEach(button => {
|
||
button.addEventListener('click', () => updateAudience(button.dataset.audience))
|
||
})
|
||
|
||
mobileToggle.addEventListener('click', () => {
|
||
const isOpen = mobilePanel.classList.contains('active')
|
||
if (isOpen) {
|
||
closeMobileMenu()
|
||
return
|
||
}
|
||
openMobileMenu()
|
||
})
|
||
|
||
document.querySelectorAll('.mobile-nav a').forEach(link => {
|
||
link.addEventListener('click', closeMobileMenu)
|
||
})
|
||
|
||
addToCartButtons.forEach(button => {
|
||
button.addEventListener('click', () => {
|
||
const productId = Number(button.dataset.productId || 0)
|
||
|
||
if (wooCommerceConfig && productId && wooCommerceConfig.addToCartUrl && wooCommerceConfig.checkoutUrl) {
|
||
button.disabled = true
|
||
|
||
fetch(wooCommerceConfig.addToCartUrl, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||
},
|
||
body: new URLSearchParams({
|
||
product_id: String(productId),
|
||
quantity: '1'
|
||
})
|
||
})
|
||
.then(async response => {
|
||
let payload = null
|
||
|
||
try {
|
||
payload = await response.json()
|
||
} catch (error) {
|
||
payload = null
|
||
}
|
||
|
||
if (!response.ok) {
|
||
throw new Error('add_to_cart_failed')
|
||
}
|
||
|
||
if (payload && payload.error && payload.product_url) {
|
||
window.location.href = payload.product_url
|
||
return
|
||
}
|
||
|
||
cart.push({
|
||
name: button.dataset.name,
|
||
volume: button.dataset.volume,
|
||
price: Number(button.dataset.price)
|
||
})
|
||
renderCart()
|
||
openCart(button)
|
||
button.disabled = false
|
||
})
|
||
.catch(() => {
|
||
button.disabled = false
|
||
})
|
||
|
||
return
|
||
}
|
||
|
||
cart.push({
|
||
name: button.dataset.name,
|
||
volume: button.dataset.volume,
|
||
price: Number(button.dataset.price)
|
||
})
|
||
renderCart()
|
||
openCart(button)
|
||
})
|
||
})
|
||
|
||
cartOpenButton.addEventListener('click', () => openCart(cartOpenButton))
|
||
mobileCartOpenButton.addEventListener('click', () => {
|
||
closeMobileMenu()
|
||
openCart(mobileCartOpenButton)
|
||
})
|
||
cartCloseButton.addEventListener('click', closeCart)
|
||
viewCartButton.addEventListener('click', () => {
|
||
if (wooCommerceConfig && wooCommerceConfig.cartUrl) {
|
||
window.location.href = wooCommerceConfig.cartUrl
|
||
}
|
||
})
|
||
checkoutButton.addEventListener('click', () => {
|
||
if (wooCommerceConfig && wooCommerceConfig.checkoutUrl) {
|
||
window.location.href = wooCommerceConfig.checkoutUrl
|
||
return
|
||
}
|
||
|
||
closeCart()
|
||
openModal(checkoutButton)
|
||
})
|
||
|
||
orderButtons.forEach(button => {
|
||
button.addEventListener('click', () => openModal(button))
|
||
})
|
||
|
||
modalCloseButton.addEventListener('click', closeModal)
|
||
|
||
cartDrawer.addEventListener('click', event => {
|
||
if (event.target === cartDrawer) {
|
||
closeCart()
|
||
}
|
||
})
|
||
|
||
modalBackdrop.addEventListener('click', event => {
|
||
if (event.target === modalBackdrop) {
|
||
closeModal()
|
||
}
|
||
})
|
||
|
||
faqItems.forEach(item => {
|
||
const trigger = item.querySelector('.faq-question')
|
||
const answer = item.querySelector('.faq-answer')
|
||
|
||
if (!trigger || !answer) {
|
||
return
|
||
}
|
||
|
||
trigger.addEventListener('click', () => {
|
||
const isOpen = item.classList.contains('open')
|
||
faqItems.forEach(entry => {
|
||
const entryTrigger = entry.querySelector('.faq-question')
|
||
const entryAnswer = entry.querySelector('.faq-answer')
|
||
|
||
entry.classList.remove('open')
|
||
entryTrigger?.setAttribute('aria-expanded', 'false')
|
||
|
||
if (entryAnswer) {
|
||
entryAnswer.hidden = true
|
||
}
|
||
})
|
||
if (!isOpen) {
|
||
item.classList.add('open')
|
||
trigger.setAttribute('aria-expanded', 'true')
|
||
answer.hidden = false
|
||
}
|
||
})
|
||
})
|
||
|
||
orderForm.addEventListener('submit', event => {
|
||
event.preventDefault()
|
||
orderSuccess.classList.add('visible')
|
||
cart = []
|
||
renderCart()
|
||
setTimeout(() => {
|
||
closeModal()
|
||
orderForm.reset()
|
||
orderSuccess.classList.remove('visible')
|
||
}, 1800)
|
||
})
|
||
|
||
contactForm.addEventListener('submit', event => {
|
||
event.preventDefault()
|
||
contactSuccess.classList.add('visible')
|
||
setTimeout(() => {
|
||
contactForm.reset()
|
||
contactSuccess.classList.remove('visible')
|
||
}, 2200)
|
||
})
|
||
|
||
document.addEventListener('keydown', event => {
|
||
if (event.key !== 'Escape') {
|
||
return
|
||
}
|
||
closeCart()
|
||
closeModal()
|
||
closeMobileMenu()
|
||
})
|
||
|
||
renderCart()
|
||
updateAudience('home')
|