Task_12281 (#1)

Co-authored-by: User A0264400 <a0264400@jarl.from.sh>
Reviewed-on: #1
Co-authored-by: Anton.AE <ab.an.ev@yandex.ru>
Co-committed-by: Anton.AE <ab.an.ev@yandex.ru>
This commit is contained in:
2026-07-05 16:07:04 +03:00
committed by Антон
parent 50f3a8e626
commit 3e42863ef5
2878 changed files with 59059 additions and 181273 deletions

View File

@@ -0,0 +1,216 @@
const mobileToggle = document.getElementById('mobileToggle')
const mobilePanel = document.getElementById('mobilePanel')
const modalBackdrop = document.getElementById('orderModal')
const modalCloseButton = document.getElementById('modalCloseButton')
const orderButtons = document.querySelectorAll('[data-open-order]')
const faqItems = document.querySelectorAll('.faq-item')
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 modalCard = modalBackdrop?.querySelector('.modal-card')
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 openMobileMenu = () => {
if (!mobilePanel || !mobileToggle) {
return
}
mobilePanel.classList.add('active')
mobileToggle.setAttribute('aria-expanded', 'true')
document.body.classList.add('menu-open')
}
const closeMobileMenu = () => {
if (!mobilePanel || !mobileToggle) {
return
}
mobilePanel.classList.remove('active')
mobileToggle.setAttribute('aria-expanded', 'false')
document.body.classList.remove('menu-open')
}
const openModal = triggerElement => {
if (!modalBackdrop) {
return
}
lastModalTrigger = triggerElement || document.activeElement
if (orderItemsField) {
orderItemsField.value = ''
}
modalBackdrop.classList.add('open')
modalBackdrop.setAttribute('aria-hidden', 'false')
document.body.classList.add('modal-open')
focusFirstElement(modalCard)
}
const closeModal = () => {
if (!modalBackdrop) {
return
}
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 submitLeadForm = (formElement, successElement, formType, onSuccess) => {
if (!formElement || !successElement) {
return
}
formElement.addEventListener('submit', async event => {
event.preventDefault()
const leadFormConfig = window.test1LeadForm || null
if (!leadFormConfig?.ajaxUrl || !leadFormConfig?.action || !leadFormConfig?.nonce) {
window.alert('Форма временно недоступна. Обновите страницу и попробуйте снова.')
return
}
const formData = new window.FormData(formElement)
formData.append('action', leadFormConfig.action)
formData.append('nonce', leadFormConfig.nonce)
formData.append('form_type', formType)
formData.append('page_url', window.location.href)
try {
const response = await window.fetch(leadFormConfig.ajaxUrl, {
method: 'POST',
credentials: 'same-origin',
body: formData,
})
const payload = await response.json().catch(() => null)
if (!response.ok || !payload?.success) {
throw new Error('submit_failed')
}
successElement.classList.add('visible')
if (typeof onSuccess === 'function') {
onSuccess()
}
setTimeout(() => {
formElement.reset()
successElement.classList.remove('visible')
}, 2200)
} catch (error) {
window.alert('Не удалось отправить заявку. Попробуйте еще раз.')
}
})
}
if (mobileToggle && mobilePanel) {
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)
})
}
orderButtons.forEach(button => {
button.addEventListener('click', () => openModal(button))
})
if (modalCloseButton) {
modalCloseButton.addEventListener('click', closeModal)
}
if (modalBackdrop) {
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
}
})
})
submitLeadForm(orderForm, orderSuccess, 'landing_order', () => {
setTimeout(() => {
closeModal()
}, 700)
})
submitLeadForm(contactForm, contactSuccess, 'landing_contacts')
document.addEventListener('keydown', event => {
if (event.key !== 'Escape') {
return
}
closeModal()
closeMobileMenu()
})