188 lines
7.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(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"]');
const dateInput = form.querySelector('input[name="eventDate"]');
let selectedFiles = [];
// Forbid past dates (today is allowed)
if (dateInput) {
const t = new Date();
dateInput.min = `${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,'0')}-${String(t.getDate()).padStart(2,'0')}`;
}
// 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 firstName = form.querySelector('[name="firstName"]');
if (!firstName.value.trim()) { setErr(firstName, 'Please enter your first name.'); ok = false; }
else clearErr(firstName);
const lastName = form.querySelector('[name="lastName"]');
if (!lastName.value.trim()) { setErr(lastName, 'Please enter your last name.'); ok = false; }
else clearErr(lastName);
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 = '&times;';
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('firstName', form.querySelector('[name="firstName"]').value.trim());
fd.append('lastName', form.querySelector('[name="lastName"]').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! Well 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' });
}
})();