feat: Containerize services with Docker Compose (PostgreSQL, Strapi CMS, Express Backend, Nginx Frontend) on custom ports >9000
This commit is contained in:
+42
-14
@@ -1,8 +1,10 @@
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
import { saveLead, getLeads } from '../db.js';
|
||||
import { sendContactEmail } from '../services/mailService.js';
|
||||
import { sendContactEmail, sendCareersEmail, sendStrategyEmail } from '../services/mailService.js';
|
||||
|
||||
const router = express.Router();
|
||||
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } });
|
||||
|
||||
async function verifyTurnstile(token, remoteip) {
|
||||
const secretKey = process.env.TURNSTILE_SECRET_KEY || '1x000000000000000000000000000000AA';
|
||||
@@ -25,10 +27,10 @@ async function verifyTurnstile(token, remoteip) {
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/contact - Handle Contact Us Form submission via SMTP
|
||||
router.post('/', async (req, res) => {
|
||||
// POST /api/contact - Handle Contact, Careers, and Strategy Call form submissions via SMTP
|
||||
router.post('/', upload.single('resume'), async (req, res) => {
|
||||
try {
|
||||
const { name, email, phone, mobile, subject, message, interests, type, turnstileToken } = req.body;
|
||||
const { name, email, phone, mobile, subject, message, interests, type, designation, dateTime, resumeName, turnstileToken } = req.body;
|
||||
|
||||
const contactName = name?.trim();
|
||||
const contactEmail = email?.trim();
|
||||
@@ -55,17 +57,43 @@ router.post('/', async (req, res) => {
|
||||
phone: contactPhone,
|
||||
subject: contactSubject,
|
||||
message: contactMessage,
|
||||
designation,
|
||||
dateTime,
|
||||
resumeName,
|
||||
type: type || 'contact'
|
||||
});
|
||||
|
||||
// Attempt sending email via SMTP service
|
||||
const mailResult = await sendContactEmail({
|
||||
name: contactName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
subject: contactSubject,
|
||||
message: contactMessage
|
||||
});
|
||||
// Attempt sending email via SMTP service based on form type
|
||||
let mailResult = { success: false };
|
||||
|
||||
if (type === 'careers') {
|
||||
mailResult = await sendCareersEmail({
|
||||
name: contactName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
resumeName: req.file ? req.file.originalname : (resumeName || 'Resume Uploaded'),
|
||||
message: contactMessage,
|
||||
file: req.file
|
||||
});
|
||||
} else if (type === 'strategy') {
|
||||
mailResult = await sendStrategyEmail({
|
||||
name: contactName,
|
||||
email: contactEmail,
|
||||
phone: contactPhone,
|
||||
designation: designation || 'N/A',
|
||||
dateTime: dateTime || 'N/A',
|
||||
interests: interests || 'General Strategy Consultation',
|
||||
message: contactMessage
|
||||
});
|
||||
} else {
|
||||
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
|
||||
@@ -74,7 +102,7 @@ router.post('/', async (req, res) => {
|
||||
saved: true,
|
||||
leadId: lead.id,
|
||||
smtpError: mailResult.error,
|
||||
message: 'Your message was saved successfully. Note: SMTP email dispatch requires SMTP credentials in .env.'
|
||||
message: 'Your request was saved successfully. Note: SMTP email dispatch requires SMTP credentials in .env.'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -83,7 +111,7 @@ router.post('/', async (req, res) => {
|
||||
saved: true,
|
||||
leadId: lead.id,
|
||||
messageId: mailResult.messageId,
|
||||
message: 'Message sent successfully via SMTP!'
|
||||
message: 'Request sent successfully via SMTP!'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Contact Route Error]', error);
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
import { Router } from 'express';
|
||||
import { getContent, updateSection, updateAllContent } from '../db.js';
|
||||
import { requireAuth } from '../auth.js';
|
||||
import { getStrapiBlogs } from '../strapi.js';
|
||||
import seedContent from '../seed/default-content.json' with { type: 'json' };
|
||||
|
||||
const VALID_SECTIONS = Object.keys(seedContent);
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/', (_req, res) => {
|
||||
router.get('/', async (_req, res) => {
|
||||
const { content, updatedAt } = getContent();
|
||||
const strapiItems = await getStrapiBlogs();
|
||||
if (strapiItems && content.insights) {
|
||||
content.insights.items = strapiItems;
|
||||
}
|
||||
res.json({ ...content, _updatedAt: updatedAt });
|
||||
});
|
||||
|
||||
router.get('/blogs', async (_req, res) => {
|
||||
const { content } = getContent();
|
||||
const strapiItems = await getStrapiBlogs();
|
||||
res.json(strapiItems || content.insights?.items || []);
|
||||
});
|
||||
|
||||
router.put('/', requireAuth, (req, res) => {
|
||||
const { _updatedAt, ...content } = req.body;
|
||||
const updatedAt = updateAllContent(content);
|
||||
|
||||
Reference in New Issue
Block a user