From 77318fb4777b7d58d7912a1d7331357d8aaf4254 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 7 Jun 2026 00:32:06 -0400 Subject: [PATCH] Contact form: split name into first/last, add ntfy notification - First and last name are now separate required fields - Server combines them into a full name for emails - Sends a push notification to NTFY_URL on new inquiry (fire-and-forget) - NTFY_URL env var wired through docker-compose Co-Authored-By: Claude Sonnet 4.6 --- .env.example | 1 + docker-compose.yml | 1 + main-site/contact-form.js | 13 +++++++++---- main-site/contact/index.html | 23 ++++++++++++++++++----- main-site/index.html | 23 ++++++++++++++++++----- main-site/server.js | 22 ++++++++++++++++++++-- 6 files changed, 67 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index e9878bd..aecb264 100644 --- a/.env.example +++ b/.env.example @@ -25,3 +25,4 @@ SMTP_SECURE=false SMTP_USER=info@beachpartyballoons.com SMTP_PASS= CONTACT_TO=info@beachpartyballoons.com +NTFY_URL=https://ntfy.example.com/your-topic diff --git a/docker-compose.yml b/docker-compose.yml index d26a14c..a397e78 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ services: SMTP_USER: ${SMTP_USER} SMTP_PASS: ${SMTP_PASS} CONTACT_TO: ${CONTACT_TO} + NTFY_URL: ${NTFY_URL:-} volumes: - ./main-site/update.json:/usr/src/app/update.json restart: always diff --git a/main-site/contact-form.js b/main-site/contact-form.js index 3230d45..5232b1c 100644 --- a/main-site/contact-form.js +++ b/main-site/contact-form.js @@ -47,9 +47,13 @@ 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 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())) { @@ -131,7 +135,8 @@ } const fd = new FormData(); - fd.append('name', form.querySelector('[name="name"]').value.trim()); + 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()); diff --git a/main-site/contact/index.html b/main-site/contact/index.html index e3f614b..3e08a84 100644 --- a/main-site/contact/index.html +++ b/main-site/contact/index.html @@ -47,12 +47,25 @@ -
- -
- +
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
-
diff --git a/main-site/index.html b/main-site/index.html index 6782c61..d703b2d 100644 --- a/main-site/index.html +++ b/main-site/index.html @@ -79,12 +79,25 @@
-
- -
- +
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
-
diff --git a/main-site/server.js b/main-site/server.js index da17fd7..f07b4b4 100644 --- a/main-site/server.js +++ b/main-site/server.js @@ -117,9 +117,10 @@ apiRouter.post('/contact', upload.array('photos', 3), async (req, res) => { return res.json({ success: true }); } - const { name, email, phone, message, eventType, eventDate } = req.body; + const { firstName, lastName, email, phone, message, eventType, eventDate } = req.body; + const name = [firstName, lastName].filter(Boolean).join(' '); - if (!name || !email || !phone || !message) { + if (!firstName || !lastName || !email || !phone || !message) { return res.status(400).json({ success: false, message: 'Please fill in all required fields.' }); } @@ -182,6 +183,23 @@ apiRouter.post('/contact', upload.array('photos', 3), async (req, res) => { transporter.sendMail(autoReply).catch(err => console.error(`[${new Date().toISOString()}] Auto-reply failed:`, err) ); + if (process.env.NTFY_URL) { + const ntfyBody = [ + phone, + eventDateFormatted || null, + eventType || null, + message.slice(0, 100) + (message.length > 100 ? 'โ€ฆ' : ''), + ].filter(Boolean).join(' ยท '); + fetch(process.env.NTFY_URL, { + method: 'POST', + headers: { + 'Title': `๐ŸŽˆ New inquiry โ€” ${name}`, + 'Priority': 'default', + 'Content-Type': 'text/plain', + }, + body: ntfyBody, + }).catch(err => console.error(`[${new Date().toISOString()}] ntfy failed:`, err)); + } res.json({ success: true }); } catch (err) { console.error(`[${new Date().toISOString()}] Contact form mail error:`, err);