UIAngular/Server/src/routes/api/vbs.js

181 lines
7.0 KiB
JavaScript

var express = require('express');
var router = express.Router();
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
host: 'smtp.ionos.com',
port: 587,
secure: false,
auth:{
user: 'mail@ofbbutte.com',
pass: '@2014OfbPwd'
}
});
router.get("/",function(req,res){
res.status(200).json({"message":"Hello World"});
return;
});
router.post("/", function(req,res){
console.log(req.body);
//This is the honeypot field
//If it has something in it then we know it was filled out by a bot
if (!req.body.hp || req.body.hp != '.'){
res.status(200).json({"status":200,"message":"Success!"});
return;
}
let mailOptions = {
from: 'donotreply@ofbbutte.com',
to: 'djabsher@gmail.com',
subject: 'OFB - VBS Registration' + req.body.firstName,
html: generateRegistrationEmailHTML(req.body)
};
transporter.sendMail(mailOptions,(error, info) =>{
if (error){
console.log(error);
res.status(400).json({"status":400,"message":"There was an error","error":error.response});
} else {
res.status(200).json({"status":200,"message":"Success"});
}
});
});
/**
* Generates a sectioned HTML email string for the registration form.
* Displays all fields even if they are empty.
* @param {Object} data - The value object from this.form.value
* @returns {string} Ready-to-send HTML string
*/
function generateRegistrationEmailHTML(data) {
// Helper to cleanly format boolean true/false fields
const formatBool = (val) => {
if (val === true || val === 'true') return 'Yes';
if (val === false || val === 'false') return 'No';
return val;
};
// Helper to ensure we don't render literal 'null' or 'undefined' text
const sanitizeValue = (val) => {
if (val === null || val === undefined) return '';
return String(val).trim();
};
// Define the layout sections and human-readable labels
const sections = [
{
title: "Student Information",
fields: [
{ label: "Student Name", value: `${sanitizeValue(data.firstName)} ${sanitizeValue(data.lastName)}`.trim() },
{ label: "Grade", value: sanitizeValue(data.grade) },
{ label: "Date of Birth", value: sanitizeValue(data.dob) },
{ label: "Has Allergies?", value: sanitizeValue(formatBool(data.hasAllergies)) },
{ label: "Allergies", value: sanitizeValue(data.allergies) },
{ label: "Has Dietary Restrictions?", value: sanitizeValue(formatBool(data.hasDietaryRestrictions)) },
{ label: "Dietary Restrictions", value: sanitizeValue(data.dietaryRestrictions) },
{ label: "Attended in Past?", value: sanitizeValue(formatBool(data.attendedInPast)) },
{ label: "Rides Bus?", value: sanitizeValue(formatBool(data.ridesBus)) }
]
},
{
title: "Parent / Guardian Contact",
fields: [
{ label: "Parent Name", value: `${sanitizeValue(data.parentFirstName)} ${sanitizeValue(data.parentLastName)}`.trim() },
{ label: "Email", value: sanitizeValue(data.parentEmail) },
{ label: "Mobile Phone", value: sanitizeValue(data.parentMobilePhone) },
{ label: "Home Phone", value: sanitizeValue(data.parentHomePhone) },
{ label: "Work Phone", value: sanitizeValue(data.parentWorkPhone) },
{ label: "Address", value: `${sanitizeValue(data.address1)}${data.address2 ? ', ' + sanitizeValue(data.address2) : ''}, ${sanitizeValue(data.city)}, ${sanitizeValue(data.state)} ${sanitizeValue(data.zip)}`.trim().replace(/^,|,$/g, '') }
]
},
{
title: "Emergency Contact",
fields: [
{ label: "Same as Parent?", value: sanitizeValue(formatBool(data.emergencySameAsParent)) },
{ label: "Emergency Name", value: `${sanitizeValue(data.emergencyFirstName)} ${sanitizeValue(data.emergencyLastName)}`.trim() },
{ label: "Emergency Phone", value: sanitizeValue(data.emergencyPhone) }
]
}
];
// Map the sections array into HTML tables (No filtering out fields!)
const htmlContent = sections.map(section => {
const rows = section.fields.map(field => `
<tr>
<td style="padding: 10px 12px; border-bottom: 1px solid #edf2f7; font-weight: 600; color: #4a5568; width: 35%; font-size: 14px;">
${field.label}
</td>
<td style="padding: 10px 12px; border-bottom: 1px solid #edf2f7; color: #2d3748; font-size: 14px;">
${field.value}
</td>
</tr>
`).join('');
return `
<h3 style="color: #4f46e5; font-size: 16px; margin-top: 24px; margin-bottom: 10px; border-bottom: 2px solid #e2e8f0; padding-bottom: 6px; font-weight: 600;">
${section.title}
</h3>
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; margin-bottom: 15px;">
<tbody>
${rows}
</tbody>
</table>
`;
}).join('');
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Registration Submission</title>
</head>
<body style="margin: 0; padding: 0; background-color: #f7fafc; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color: #f7fafc; padding: 24px 0;">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 650px; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 6px rgba(0,0,0,0.05); border: 1px solid #e2e8f0;">
<!-- Header Banner -->
<tr>
<td style="background-color: #4f46e5; padding: 24px; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 20px; font-weight: 600; letter-spacing: 0.5px;">
New Registration Submitted
</h1>
</td>
</tr>
<!-- Content Body -->
<tr>
<td style="padding: 24px 32px;">
<p style="margin-top: 0; margin-bottom: 16px; font-size: 15px; color: #718096; line-height: 1.5;">
A new form submission has been received.
</p>
${htmlContent}
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8fafc; padding: 20px; text-align: center; font-size: 12px; color: #a0aec0; border-top: 1px solid #edf2f7;">
This email was automatically generated and sent from the registration system.
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
`;
}
module.exports = router;