init commit
This commit is contained in:
250
routes/contact.js
Normal file
250
routes/contact.js
Normal file
@@ -0,0 +1,250 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { body, validationResult } = require('express-validator');
|
||||
const nodemailer = require('nodemailer');
|
||||
const Contact = require('../models/Contact');
|
||||
const TelegramBot = require('node-telegram-bot-api');
|
||||
|
||||
// Initialize Telegram bot if token is provided
|
||||
let bot = null;
|
||||
if (process.env.TELEGRAM_BOT_TOKEN) {
|
||||
bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, { polling: false });
|
||||
}
|
||||
|
||||
// Contact form validation
|
||||
const contactValidation = [
|
||||
body('name').trim().isLength({ min: 2, max: 100 }),
|
||||
body('email').isEmail().normalizeEmail(),
|
||||
body('subject').trim().isLength({ min: 5, max: 200 }),
|
||||
body('message').trim().isLength({ min: 10, max: 2000 }),
|
||||
body('phone').optional().isMobilePhone(),
|
||||
body('company').optional().trim().isLength({ max: 100 })
|
||||
];
|
||||
|
||||
// Submit contact form
|
||||
router.post('/submit', contactValidation, async (req, res) => {
|
||||
try {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Invalid input data',
|
||||
errors: errors.array()
|
||||
});
|
||||
}
|
||||
|
||||
const contactData = {
|
||||
...req.body,
|
||||
ipAddress: req.ip,
|
||||
userAgent: req.get('User-Agent'),
|
||||
source: 'website'
|
||||
};
|
||||
|
||||
// Save to database
|
||||
const contact = new Contact(contactData);
|
||||
await contact.save();
|
||||
|
||||
// Send email notification
|
||||
await sendEmailNotification(contact);
|
||||
|
||||
// Send Telegram notification
|
||||
await sendTelegramNotification(contact);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Your message has been sent successfully. We will get back to you soon!',
|
||||
contactId: contact._id
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Contact form error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Sorry, there was an error sending your message. Please try again.'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get project estimate
|
||||
router.post('/estimate', [
|
||||
body('services').isArray().notEmpty(),
|
||||
body('projectType').notEmpty(),
|
||||
body('timeline').notEmpty(),
|
||||
body('budget').notEmpty(),
|
||||
body('description').trim().isLength({ min: 10, max: 1000 })
|
||||
], async (req, res) => {
|
||||
try {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Invalid input data',
|
||||
errors: errors.array()
|
||||
});
|
||||
}
|
||||
|
||||
const { services, projectType, timeline, budget, description, contactInfo } = req.body;
|
||||
|
||||
// Calculate estimate (simplified)
|
||||
const estimate = calculateProjectEstimate(services, projectType, timeline);
|
||||
|
||||
// Save inquiry to database
|
||||
const contactData = {
|
||||
name: contactInfo.name,
|
||||
email: contactInfo.email,
|
||||
phone: contactInfo.phone,
|
||||
company: contactInfo.company,
|
||||
subject: `Project Estimate Request - ${projectType}`,
|
||||
message: `Project Description: ${description}\n\nServices: ${services.join(', ')}\nTimeline: ${timeline}\nBudget: ${budget}\n\nCalculated Estimate: ${estimate.formatted}`,
|
||||
serviceInterest: projectType,
|
||||
budget: budget,
|
||||
timeline: timeline,
|
||||
source: 'calculator',
|
||||
ipAddress: req.ip,
|
||||
userAgent: req.get('User-Agent')
|
||||
};
|
||||
|
||||
const contact = new Contact(contactData);
|
||||
await contact.save();
|
||||
|
||||
// Send notifications
|
||||
await sendEmailNotification(contact);
|
||||
await sendTelegramNotification(contact);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Your project estimate request has been submitted successfully!',
|
||||
estimate: estimate,
|
||||
contactId: contact._id
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Estimate request error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Sorry, there was an error processing your request. Please try again.'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to send email notification
|
||||
async function sendEmailNotification(contact) {
|
||||
if (!process.env.EMAIL_HOST || !process.env.EMAIL_USER) {
|
||||
console.log('Email configuration not provided, skipping email notification');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const transporter = nodemailer.createTransporter({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: process.env.EMAIL_PORT || 587,
|
||||
secure: false,
|
||||
auth: {
|
||||
user: process.env.EMAIL_USER,
|
||||
pass: process.env.EMAIL_PASS
|
||||
}
|
||||
});
|
||||
|
||||
const mailOptions = {
|
||||
from: process.env.EMAIL_USER,
|
||||
to: process.env.ADMIN_EMAIL || process.env.EMAIL_USER,
|
||||
subject: `New Contact Form Submission: ${contact.subject}`,
|
||||
html: `
|
||||
<h2>New Contact Form Submission</h2>
|
||||
<p><strong>Name:</strong> ${contact.name}</p>
|
||||
<p><strong>Email:</strong> ${contact.email}</p>
|
||||
<p><strong>Phone:</strong> ${contact.phone || 'Not provided'}</p>
|
||||
<p><strong>Company:</strong> ${contact.company || 'Not provided'}</p>
|
||||
<p><strong>Subject:</strong> ${contact.subject}</p>
|
||||
<p><strong>Message:</strong></p>
|
||||
<p>${contact.message.replace(/\n/g, '<br>')}</p>
|
||||
<p><strong>Source:</strong> ${contact.source}</p>
|
||||
<p><strong>Submitted:</strong> ${contact.createdAt}</p>
|
||||
<hr>
|
||||
<p><a href="${process.env.SITE_URL}/admin/contacts/${contact._id}">View in Admin Panel</a></p>
|
||||
`
|
||||
};
|
||||
|
||||
await transporter.sendMail(mailOptions);
|
||||
console.log('Email notification sent successfully');
|
||||
} catch (error) {
|
||||
console.error('Email notification error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to send Telegram notification
|
||||
async function sendTelegramNotification(contact) {
|
||||
if (!bot || !process.env.TELEGRAM_CHAT_ID) {
|
||||
console.log('Telegram configuration not provided, skipping Telegram notification');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const message = `
|
||||
🔔 *New Contact Form Submission*
|
||||
|
||||
👤 *Name:* ${contact.name}
|
||||
📧 *Email:* ${contact.email}
|
||||
📱 *Phone:* ${contact.phone || 'Not provided'}
|
||||
🏢 *Company:* ${contact.company || 'Not provided'}
|
||||
📝 *Subject:* ${contact.subject}
|
||||
|
||||
💬 *Message:*
|
||||
${contact.message}
|
||||
|
||||
📍 *Source:* ${contact.source}
|
||||
🕐 *Time:* ${contact.createdAt.toLocaleString()}
|
||||
|
||||
[View in Admin Panel](${process.env.SITE_URL}/admin/contacts/${contact._id})
|
||||
`;
|
||||
|
||||
await bot.sendMessage(process.env.TELEGRAM_CHAT_ID, message, {
|
||||
parse_mode: 'Markdown',
|
||||
disable_web_page_preview: true
|
||||
});
|
||||
|
||||
console.log('Telegram notification sent successfully');
|
||||
} catch (error) {
|
||||
console.error('Telegram notification error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to calculate project estimate
|
||||
function calculateProjectEstimate(services, projectType, timeline) {
|
||||
const baseRates = {
|
||||
'web-development': 50000,
|
||||
'mobile-app': 80000,
|
||||
'ui-ux-design': 30000,
|
||||
'branding': 20000,
|
||||
'e-commerce': 70000,
|
||||
'consulting': 40000
|
||||
};
|
||||
|
||||
const timelineMultipliers = {
|
||||
'asap': 1.5,
|
||||
'1-month': 1.2,
|
||||
'1-3-months': 1.0,
|
||||
'3-6-months': 0.9,
|
||||
'flexible': 0.8
|
||||
};
|
||||
|
||||
let basePrice = baseRates[projectType] || 50000;
|
||||
let multiplier = timelineMultipliers[timeline] || 1.0;
|
||||
|
||||
// Add service modifiers
|
||||
let serviceModifier = 1.0;
|
||||
if (services.length > 3) serviceModifier += 0.3;
|
||||
if (services.length > 5) serviceModifier += 0.5;
|
||||
|
||||
const totalEstimate = Math.round(basePrice * multiplier * serviceModifier);
|
||||
const rangeMin = Math.round(totalEstimate * 0.8);
|
||||
const rangeMax = Math.round(totalEstimate * 1.3);
|
||||
|
||||
return {
|
||||
base: totalEstimate,
|
||||
min: rangeMin,
|
||||
max: rangeMax,
|
||||
formatted: `₩${rangeMin.toLocaleString()} - ₩${rangeMax.toLocaleString()}`,
|
||||
currency: 'KRW'
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user