diff --git a/main-site/contact-form.js b/main-site/contact-form.js new file mode 100644 index 0000000..3230d45 --- /dev/null +++ b/main-site/contact-form.js @@ -0,0 +1,175 @@ +(function () { + const form = document.getElementById('contactForm'); + if (!form) return; + + const dropzone = document.getElementById('dropzone'); + const photoInput = document.getElementById('photoInput'); + const photoPreview = document.getElementById('photoPreview'); + const photoError = document.getElementById('photoError'); + const formAlert = document.getElementById('formAlert'); + const submitBtn = document.getElementById('submitBtn'); + const textarea = form.querySelector('textarea[name="message"]'); + const phoneInput = form.querySelector('input[name="phone"]'); + let selectedFiles = []; + + // Textarea auto-resize + textarea.style.overflow = 'hidden'; + textarea.addEventListener('input', function () { + this.style.height = 'auto'; + this.style.height = this.scrollHeight + 'px'; + }); + + // Phone auto-format + phoneInput.addEventListener('input', function () { + const digits = this.value.replace(/\D/g, '').slice(0, 10); + if (digits.length >= 7) this.value = '(' + digits.slice(0,3) + ') ' + digits.slice(3,6) + '-' + digits.slice(6); + else if (digits.length >= 4) this.value = '(' + digits.slice(0,3) + ') ' + digits.slice(3); + else this.value = digits; + }); + + // Clear inline errors on input + form.querySelectorAll('.input, .textarea').forEach(el => { + el.addEventListener('input', () => clearErr(el)); + }); + + function setErr(input, msg) { + input.classList.add('is-danger'); + const el = document.getElementById('err-' + input.name); + if (el) { el.textContent = msg; el.style.display = ''; } + } + + function clearErr(input) { + input.classList.remove('is-danger'); + const el = document.getElementById('err-' + input.name); + if (el) el.style.display = 'none'; + } + + function validate() { + let ok = true; + + const name = form.querySelector('[name="name"]'); + if (!name.value.trim()) { setErr(name, 'Please enter your name.'); ok = false; } + else clearErr(name); + + const email = form.querySelector('[name="email"]'); + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value.trim())) { + setErr(email, 'Please enter a valid email address.'); ok = false; + } else clearErr(email); + + const phone = form.querySelector('[name="phone"]'); + if (phone.value.replace(/\D/g, '').length < 10) { + setErr(phone, 'Please enter a valid 10-digit phone number.'); ok = false; + } else clearErr(phone); + + const msg = form.querySelector('[name="message"]'); + if (!msg.value.trim()) { setErr(msg, 'Please enter a message.'); ok = false; } + else clearErr(msg); + + return ok; + } + + // Dropzone + dropzone.addEventListener('click', () => photoInput.click()); + dropzone.addEventListener('dragover', e => { e.preventDefault(); dropzone.classList.add('drag-over'); }); + dropzone.addEventListener('dragleave', () => dropzone.classList.remove('drag-over')); + dropzone.addEventListener('drop', e => { + e.preventDefault(); + dropzone.classList.remove('drag-over'); + addFiles(Array.from(e.dataTransfer.files)); + }); + photoInput.addEventListener('change', () => { + addFiles(Array.from(photoInput.files)); + photoInput.value = ''; + }); + + function addFiles(newFiles) { + const images = newFiles.filter(f => f.type.startsWith('image/')); + const tooBig = images.filter(f => f.size > 10 * 1024 * 1024); + if (tooBig.length) showAlert('One or more photos exceed 10 MB and were skipped.', 'is-warning'); + const ok = images.filter(f => f.size <= 10 * 1024 * 1024); + const combined = [...selectedFiles, ...ok]; + photoError.style.display = combined.length > 3 ? '' : 'none'; + selectedFiles = combined.slice(0, 3); + renderPreviews(); + } + + function renderPreviews() { + photoPreview.innerHTML = ''; + selectedFiles.forEach((file, i) => { + const url = URL.createObjectURL(file); + const wrap = document.createElement('div'); + wrap.className = 'preview-wrap'; + const img = document.createElement('img'); + img.src = url; + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'remove-btn'; + btn.innerHTML = '×'; + btn.addEventListener('click', () => { + URL.revokeObjectURL(url); + selectedFiles.splice(i, 1); + photoError.style.display = 'none'; + renderPreviews(); + }); + wrap.appendChild(img); + wrap.appendChild(btn); + photoPreview.appendChild(wrap); + }); + } + + // Submit + form.addEventListener('submit', async e => { + e.preventDefault(); + formAlert.style.display = 'none'; + + if (!validate()) { + showAlert('Please correct the errors below.', 'is-danger'); + // Scroll to first error + const first = form.querySelector('.is-danger'); + if (first) first.scrollIntoView({ behavior: 'smooth', block: 'center' }); + return; + } + + const fd = new FormData(); + fd.append('name', form.querySelector('[name="name"]').value.trim()); + fd.append('email', form.querySelector('[name="email"]').value.trim()); + fd.append('phone', form.querySelector('[name="phone"]').value.trim()); + fd.append('message', form.querySelector('[name="message"]').value.trim()); + const et = form.querySelector('[name="eventType"]'); + if (et) fd.append('eventType', et.value); + const ed = form.querySelector('[name="eventDate"]'); + if (ed) fd.append('eventDate', ed.value); + const hp = form.querySelector('[name="website"]'); + if (hp) fd.append('website', hp.value); + selectedFiles.forEach(f => fd.append('photos', f)); + + submitBtn.classList.add('is-loading'); + submitBtn.disabled = true; + + try { + const res = await fetch('/api/contact', { method: 'POST', body: fd }); + const data = await res.json(); + if (data.success) { + showAlert("Message sent! We’ll get back to you soon. Check your email for a confirmation.", 'is-success'); + form.reset(); + selectedFiles = []; + renderPreviews(); + textarea.style.height = 'auto'; + } else { + showAlert(data.message || 'Something went wrong. Please try again.', 'is-danger'); + } + } catch { + showAlert('Network error. Please try again or email us directly.', 'is-danger'); + } finally { + submitBtn.classList.remove('is-loading'); + submitBtn.disabled = false; + } + }); + + function showAlert(msg, cls) { + formAlert.className = 'notification ' + cls; + formAlert.textContent = msg; + formAlert.style.display = ''; + formAlert.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } +})(); diff --git a/main-site/contact/index.html b/main-site/contact/index.html index a3df8af..475ecd9 100644 --- a/main-site/contact/index.html +++ b/main-site/contact/index.html @@ -2,75 +2,136 @@
- - - - - - - - - -