Update AboutUsPage, server routes, packages, and assets
This commit is contained in:
@@ -79,3 +79,21 @@ export function updateAdminPassword(passwordHash) {
|
||||
admin.passwordHash = passwordHash;
|
||||
writeJson(ADMIN_FILE, admin);
|
||||
}
|
||||
|
||||
const LEADS_FILE = path.join(DATA_DIR, 'contact-leads.json');
|
||||
|
||||
export function saveLead(leadData) {
|
||||
const leads = readJson(LEADS_FILE, []);
|
||||
const newLead = {
|
||||
id: `lead_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
|
||||
...leadData,
|
||||
createdAt: new Date().toISOString()
|
||||
};
|
||||
leads.unshift(newLead);
|
||||
writeJson(LEADS_FILE, leads);
|
||||
return newLead;
|
||||
}
|
||||
|
||||
export function getLeads() {
|
||||
return readJson(LEADS_FILE, []);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { initDb } from './db.js';
|
||||
import authRoutes from './routes/auth.js';
|
||||
import contentRoutes from './routes/content.js';
|
||||
import uploadRoutes from './routes/upload.js';
|
||||
import contactRoutes from './routes/contact.js';
|
||||
import multer from 'multer';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
@@ -49,6 +50,8 @@ function mountApp(base) {
|
||||
app.use(`${prefix}/api/auth`, authRoutes);
|
||||
app.use(`${prefix}/api/content`, contentRoutes);
|
||||
app.use(`${prefix}/api/upload`, uploadRoutes);
|
||||
app.use(`${prefix}/api/contact`, contactRoutes);
|
||||
app.use(`${prefix}/api/send`, contactRoutes);
|
||||
|
||||
if (serveStatic) {
|
||||
app.use(prefix || '/', express.static(distDir));
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import express from 'express';
|
||||
import { saveLead, getLeads } from '../db.js';
|
||||
import { sendContactEmail } from '../services/mailService.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// POST /api/contact - Handle Contact Us Form submission via SMTP
|
||||
router.post('/', async (req, res) => {
|
||||
try {
|
||||
const { name, email, phone, mobile, subject, message, interests, type } = req.body;
|
||||
|
||||
const contactName = name?.trim();
|
||||
const contactEmail = email?.trim();
|
||||
const contactPhone = (phone || mobile || '').trim();
|
||||
const contactSubject = (subject || interests || type || 'General Inquiry').trim();
|
||||
const contactMessage = (message || req.body.comments || '').trim();
|
||||
|
||||
if (!contactName || !contactEmail) {
|
||||
return res.status(400).json({ error: 'Name and Email are required.' });
|
||||
}
|
||||
|
||||
// Save lead record in database
|
||||
const lead = saveLead({
|
||||
name: contactName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
subject: contactSubject,
|
||||
message: contactMessage,
|
||||
type: type || 'contact'
|
||||
});
|
||||
|
||||
// Attempt sending email via SMTP service
|
||||
const mailResult = await sendContactEmail({
|
||||
name: contactName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
subject: contactSubject,
|
||||
message: contactMessage
|
||||
});
|
||||
|
||||
if (!mailResult.success) {
|
||||
// If SMTP is not yet configured or fails, return 200 with lead saved & warning
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
saved: true,
|
||||
leadId: lead.id,
|
||||
smtpError: mailResult.error,
|
||||
message: 'Your message was saved successfully. Note: SMTP email dispatch requires SMTP credentials in .env.'
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
saved: true,
|
||||
leadId: lead.id,
|
||||
messageId: mailResult.messageId,
|
||||
message: 'Message sent successfully via SMTP!'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Contact Route Error]', error);
|
||||
return res.status(500).json({ error: error.message || 'Internal Server Error' });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/contact/leads - Retrieve saved contact leads
|
||||
router.get('/leads', (_req, res) => {
|
||||
try {
|
||||
const leads = getLeads();
|
||||
return res.json({ success: true, leads });
|
||||
} catch (error) {
|
||||
return res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -246,18 +246,16 @@
|
||||
{ "label": "Our Services", "href": "#services" }
|
||||
],
|
||||
"productLinks": [
|
||||
{ "label": "PRODMAX", "href": "#products" },
|
||||
{ "label": "Budgie HRMS", "href": "#products" },
|
||||
{ "label": "EVIDO", "href": "#products" }
|
||||
{ "label": "Nebula AI platform", "href": "#products" },
|
||||
{ "label": "Prodmax", "href": "#products" },
|
||||
{ "label": "Budgie", "href": "#products" }
|
||||
],
|
||||
"social": [
|
||||
{ "platform": "Facebook", "url": "#" },
|
||||
{ "platform": "Instagram", "url": "#" },
|
||||
{ "platform": "LinkedIn", "url": "#" },
|
||||
{ "platform": "Telegram", "url": "#" },
|
||||
{ "platform": "WhatsApp", "url": "#" },
|
||||
{ "platform": "X", "url": "#" },
|
||||
{ "platform": "YouTube", "url": "#" }
|
||||
{ "platform": "Facebook", "url": "https://www.facebook.com/cavininfotech1" },
|
||||
{ "platform": "X", "url": "https://x.com/cavin_infotech" },
|
||||
{ "platform": "Instagram", "url": "https://www.instagram.com/cavin_infotech" },
|
||||
{ "platform": "LinkedIn", "url": "https://www.linkedin.com/company/cavin-infotech/" },
|
||||
{ "platform": "YouTube", "url": "https://youtube.com/@cavin_infotech" }
|
||||
],
|
||||
"legal": [
|
||||
{ "label": "Privacy Policy", "href": "#" },
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
|
||||
/**
|
||||
* Creates and returns a nodemailer SMTP transporter using environment variables.
|
||||
*/
|
||||
export function createSmtpTransporter() {
|
||||
const host = process.env.SMTP_HOST;
|
||||
const port = parseInt(process.env.SMTP_PORT || '465', 10);
|
||||
const secure = process.env.SMTP_SECURE === 'true' || port === 465;
|
||||
const user = process.env.SMTP_USER;
|
||||
const pass = process.env.SMTP_PASS;
|
||||
|
||||
if (!host || !user || !pass) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return nodemailer.createTransport({
|
||||
host,
|
||||
port,
|
||||
secure,
|
||||
auth: {
|
||||
user,
|
||||
pass
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a contact form email via SMTP using nodemailer.
|
||||
*/
|
||||
export async function sendContactEmail({ name, email, phone, subject, message }) {
|
||||
const transporter = createSmtpTransporter();
|
||||
|
||||
const toEmail = process.env.SMTP_TO || process.env.SMTP_USER || 'info@cavinfotech.com';
|
||||
const fromEmail = process.env.SMTP_FROM || `"Cavin Infotech Contact Form" <${process.env.SMTP_USER || 'info@cavinfotech.com'}>`;
|
||||
|
||||
const mailSubject = `[Contact Inquiry] ${subject ? subject : `New Inquiry from ${name}`}`;
|
||||
|
||||
const htmlContent = `
|
||||
<div style="font-family: 'Segoe UI', Helvetica, Arial, sans-serif; background-color: #020710; color: #f8fafc; padding: 40px 20px; max-width: 650px; margin: 0 auto; border-radius: 16px; border: 1px solid #1e293b;">
|
||||
<div style="text-align: center; padding-bottom: 24px; border-bottom: 1px solid #334155;">
|
||||
<h2 style="color: #ffaa00; font-size: 24px; margin: 0; font-weight: 700;">Cavin Infotech</h2>
|
||||
<p style="color: #94a3b8; font-size: 14px; margin-top: 6px;">New Website Contact Form Inquiry</p>
|
||||
</div>
|
||||
|
||||
<div style="padding: 24px 0;">
|
||||
<table style="width: 100%; border-collapse: collapse; color: #e2e8f0; font-size: 15px;">
|
||||
<tr>
|
||||
<td style="padding: 10px 0; font-weight: 600; color: #ffaa00; width: 130px;">Name:</td>
|
||||
<td style="padding: 10px 0; color: #ffffff;">${name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 0; font-weight: 600; color: #ffaa00;">Email:</td>
|
||||
<td style="padding: 10px 0;"><a href="mailto:${email}" style="color: #38bdf8; text-decoration: none;">${email}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 0; font-weight: 600; color: #ffaa00;">Phone No:</td>
|
||||
<td style="padding: 10px 0; color: #ffffff;">${phone || 'Not provided'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 0; font-weight: 600; color: #ffaa00;">Subject:</td>
|
||||
<td style="padding: 10px 0; color: #ffffff;">${subject || 'General Inquiry'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="margin-top: 24px; padding: 20px; background-color: #0b1528; border-left: 4px solid #ffaa00; border-radius: 8px;">
|
||||
<h4 style="margin: 0 0 10px 0; color: #94a3b8; font-size: 13px; text-transform: uppercase; letter-spacing: 0.05em;">Message:</h4>
|
||||
<p style="margin: 0; color: #f1f5f9; font-size: 15px; line-height: 1.6; white-space: pre-line;">${message}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center; padding-top: 20px; border-top: 1px solid #334155; color: #64748b; font-size: 12px;">
|
||||
Submitted on ${new Date().toLocaleString()} from Cavin Infotech Contact Us Page
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const textContent = `
|
||||
New Contact Inquiry - Cavin Infotech
|
||||
|
||||
Name: ${name}
|
||||
Email: ${email}
|
||||
Phone: ${phone || 'Not provided'}
|
||||
Subject: ${subject || 'General Inquiry'}
|
||||
|
||||
Message:
|
||||
${message}
|
||||
|
||||
Submitted on: ${new Date().toLocaleString()}
|
||||
`;
|
||||
|
||||
if (!transporter) {
|
||||
console.warn('[SMTP Service] SMTP credentials not set in environment (SMTP_HOST, SMTP_USER, SMTP_PASS).');
|
||||
return {
|
||||
success: false,
|
||||
error: 'SMTP credentials not configured on the server. Please set SMTP_HOST, SMTP_USER, and SMTP_PASS in .env file.'
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const info = await transporter.sendMail({
|
||||
from: fromEmail,
|
||||
to: toEmail,
|
||||
replyTo: `"${name}" <${email}>`,
|
||||
subject: mailSubject,
|
||||
text: textContent,
|
||||
html: htmlContent
|
||||
});
|
||||
|
||||
console.log('[SMTP Service] Contact email sent via SMTP:', info.messageId);
|
||||
return { success: true, messageId: info.messageId };
|
||||
} catch (err) {
|
||||
console.error('[SMTP Service] Failed to send email via SMTP:', err);
|
||||
return { success: false, error: err.message || 'SMTP sending failed' };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user