301 lines
9.1 KiB
JavaScript
301 lines
9.1 KiB
JavaScript
const express = require('express');
|
|
const cors = require('cors');
|
|
const nodemailer = require('nodemailer');
|
|
const axios = require('axios');
|
|
const path = require('path');
|
|
require('dotenv').config();
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
// Middleware
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
app.use(express.static(path.join(__dirname, '../dist/florale-emotion')));
|
|
|
|
// Email configuration
|
|
const transporter = nodemailer.createTransport({
|
|
host: 'smtp.mailbox.org',
|
|
port: 587,
|
|
secure: false,
|
|
auth: {
|
|
user: process.env.EMAIL_USER || 'info@florale-emotion.de',
|
|
pass: process.env.EMAIL_PASS || 'your-email-password'
|
|
}
|
|
});
|
|
|
|
// Gitea configuration
|
|
const GITEA_CONFIG = {
|
|
url: process.env.GITEA_URL || 'https://your-gitea-instance.com',
|
|
token: process.env.GITEA_TOKEN || 'your-gitea-token',
|
|
owner: 'florale-emotion',
|
|
repo: 'tickets'
|
|
};
|
|
|
|
// Email templates
|
|
const getCustomerEmailTemplate = (formData) => {
|
|
const eventTypes = {
|
|
'wedding': 'Hochzeit',
|
|
'funeral': 'Beerdigung',
|
|
'corporate': 'Firmenevent',
|
|
'birthday': 'Geburtstag',
|
|
'anniversary': 'Jubiläum',
|
|
'other': 'Sonstiges'
|
|
};
|
|
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
.header { background: linear-gradient(135deg, #ec4899, #22c55e); color: white; padding: 20px; text-align: center; }
|
|
.content { padding: 20px; }
|
|
.footer { background: #f8f9fa; padding: 15px; text-align: center; font-size: 12px; color: #666; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>Florale Emotion</h1>
|
|
<p>Vielen Dank für Ihre Anfrage!</p>
|
|
</div>
|
|
<div class="content">
|
|
<p>Liebe/r ${formData.firstName} ${formData.lastName},</p>
|
|
|
|
<p>vielen Dank für Ihr Interesse an unseren floralen Services für Ihr/e ${eventTypes[formData.eventType] || formData.eventType}!</p>
|
|
|
|
<p>Wir haben Ihre Anfrage erhalten und werden uns schnellstmöglich bei Ihnen melden. In der Regel antworten wir innerhalb von 24 Stunden.</p>
|
|
|
|
<h3>Ihre Anfrage im Überblick:</h3>
|
|
<ul>
|
|
<li><strong>Event-Art:</strong> ${eventTypes[formData.eventType] || formData.eventType}</li>
|
|
${formData.eventDate ? `<li><strong>Gewünschtes Datum:</strong> ${new Date(formData.eventDate).toLocaleDateString('de-DE')}</li>` : ''}
|
|
${formData.guestCount ? `<li><strong>Anzahl Gäste:</strong> ${formData.guestCount}</li>` : ''}
|
|
${formData.budget ? `<li><strong>Budget:</strong> ${formData.budget}</li>` : ''}
|
|
</ul>
|
|
|
|
<p>Falls Sie noch Fragen haben oder zusätzliche Informationen benötigen, zögern Sie nicht, uns zu kontaktieren.</p>
|
|
|
|
<p>Mit floralen Grüßen,<br>
|
|
Ihr Team von Florale Emotion<br>
|
|
Veronika & Corinna</p>
|
|
</div>
|
|
<div class="footer">
|
|
<p>Florale Emotion | info@florale-emotion.de | www.florale-emotion.de</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`;
|
|
};
|
|
|
|
const getInternalEmailTemplate = (formData) => {
|
|
const eventTypes = {
|
|
'wedding': 'Hochzeit',
|
|
'funeral': 'Beerdigung',
|
|
'corporate': 'Firmenevent',
|
|
'birthday': 'Geburtstag',
|
|
'anniversary': 'Jubiläum',
|
|
'other': 'Sonstiges'
|
|
};
|
|
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
.header { background: #1f2937; color: white; padding: 20px; }
|
|
.content { padding: 20px; }
|
|
.info-box { background: #f3f4f6; padding: 15px; margin: 10px 0; border-left: 4px solid #ec4899; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>Neue Kundenanfrage - Florale Emotion</h1>
|
|
</div>
|
|
<div class="content">
|
|
<h2>Kundeninformationen</h2>
|
|
<div class="info-box">
|
|
<p><strong>Name:</strong> ${formData.firstName} ${formData.lastName}</p>
|
|
<p><strong>E-Mail:</strong> ${formData.email}</p>
|
|
<p><strong>Telefon:</strong> ${formData.phone || 'Nicht angegeben'}</p>
|
|
</div>
|
|
|
|
<h2>Event-Details</h2>
|
|
<div class="info-box">
|
|
<p><strong>Art des Events:</strong> ${eventTypes[formData.eventType] || formData.eventType}</p>
|
|
<p><strong>Gewünschtes Datum:</strong> ${formData.eventDate ? new Date(formData.eventDate).toLocaleDateString('de-DE') : 'Nicht angegeben'}</p>
|
|
<p><strong>Anzahl Gäste:</strong> ${formData.guestCount || 'Nicht angegeben'}</p>
|
|
<p><strong>Budget:</strong> ${formData.budget || 'Nicht angegeben'}</p>
|
|
</div>
|
|
|
|
<h2>Nachricht</h2>
|
|
<div class="info-box">
|
|
<p>${formData.message.replace(/\n/g, '<br>')}</p>
|
|
</div>
|
|
|
|
<p><em>Eingegangen am: ${new Date().toLocaleString('de-DE')}</em></p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`;
|
|
};
|
|
|
|
// Create Gitea ticket
|
|
async function createGiteaTicket(formData) {
|
|
try {
|
|
const eventTypes = {
|
|
'wedding': 'Hochzeit',
|
|
'funeral': 'Beerdigung',
|
|
'corporate': 'Corporate Event',
|
|
'birthday': 'Geburtstag',
|
|
'anniversary': 'Jubiläum',
|
|
'other': 'Sonstiges'
|
|
};
|
|
|
|
const title = `Neue Anfrage: ${eventTypes[formData.eventType] || formData.eventType} - ${formData.firstName} ${formData.lastName}`;
|
|
|
|
const body = `## Kundeninformationen
|
|
- **Name:** ${formData.firstName} ${formData.lastName}
|
|
- **E-Mail:** ${formData.email}
|
|
- **Telefon:** ${formData.phone || 'Nicht angegeben'}
|
|
|
|
## Event-Details
|
|
- **Art des Events:** ${eventTypes[formData.eventType] || formData.eventType}
|
|
- **Gewünschtes Datum:** ${formData.eventDate || 'Nicht angegeben'}
|
|
- **Anzahl Gäste:** ${formData.guestCount || 'Nicht angegeben'}
|
|
- **Budget:** ${formData.budget || 'Nicht angegeben'}
|
|
|
|
## Nachricht
|
|
${formData.message}
|
|
|
|
---
|
|
*Automatisch erstellt am ${new Date().toLocaleString('de-DE')}*`;
|
|
|
|
const issue = {
|
|
title,
|
|
body,
|
|
labels: ['kunde-anfrage', eventTypes[formData.eventType]?.toLowerCase().replace(' ', '-') || 'sonstiges'],
|
|
assignees: ['veronika', 'corinna']
|
|
};
|
|
|
|
const response = await axios.post(
|
|
`${GITEA_CONFIG.url}/api/v1/repos/${GITEA_CONFIG.owner}/${GITEA_CONFIG.repo}/issues`,
|
|
issue,
|
|
{
|
|
headers: {
|
|
'Authorization': `token ${GITEA_CONFIG.token}`,
|
|
'Content-Type': 'application/json'
|
|
}
|
|
}
|
|
);
|
|
|
|
return response.data;
|
|
} catch (error) {
|
|
console.error('Error creating Gitea ticket:', error.response?.data || error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Routes
|
|
app.post('/api/contact', async (req, res) => {
|
|
try {
|
|
const formData = req.body;
|
|
|
|
// Send confirmation email to customer
|
|
const customerMailOptions = {
|
|
from: process.env.EMAIL_USER || 'info@florale-emotion.de',
|
|
to: formData.email,
|
|
subject: 'Bestätigung Ihrer Anfrage - Florale Emotion',
|
|
html: getCustomerEmailTemplate(formData)
|
|
};
|
|
|
|
// Send notification email to team
|
|
const teamMailOptions = {
|
|
from: process.env.EMAIL_USER || 'info@florale-emotion.de',
|
|
to: [
|
|
'veronika@florale-emotion.de',
|
|
'corinna@florale-emotion.de',
|
|
'info@florale-emotion.de'
|
|
],
|
|
subject: `Neue Kundenanfrage: ${formData.firstName} ${formData.lastName}`,
|
|
html: getInternalEmailTemplate(formData)
|
|
};
|
|
|
|
// Send emails
|
|
await Promise.all([
|
|
transporter.sendMail(customerMailOptions),
|
|
transporter.sendMail(teamMailOptions)
|
|
]);
|
|
|
|
// Create Gitea ticket
|
|
let ticketId = null;
|
|
try {
|
|
const ticket = await createGiteaTicket(formData);
|
|
ticketId = ticket.number;
|
|
} catch (ticketError) {
|
|
console.error('Failed to create Gitea ticket:', ticketError);
|
|
// Continue even if ticket creation fails
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Anfrage erfolgreich gesendet',
|
|
ticketId
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error processing contact form:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Fehler beim Senden der Anfrage'
|
|
});
|
|
}
|
|
});
|
|
|
|
app.post('/api/newsletter', async (req, res) => {
|
|
try {
|
|
const { email } = req.body;
|
|
|
|
const mailOptions = {
|
|
from: process.env.EMAIL_USER || 'info@florale-emotion.de',
|
|
to: email,
|
|
subject: 'Willkommen bei Florale Emotion Newsletter',
|
|
html: `
|
|
<h2>Willkommen bei unserem Newsletter!</h2>
|
|
<p>Vielen Dank für Ihr Interesse an Florale Emotion.</p>
|
|
<p>Sie erhalten ab sofort Updates über neue Projekte, Tipps und besondere Angebote.</p>
|
|
`
|
|
};
|
|
|
|
await transporter.sendMail(mailOptions);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Newsletter-Anmeldung erfolgreich'
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error processing newsletter signup:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Fehler bei der Newsletter-Anmeldung'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Health check
|
|
app.get('/api/health', (req, res) => {
|
|
res.json({ status: 'OK', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// Serve Angular app
|
|
app.get('*', (req, res) => {
|
|
res.sendFile(path.join(__dirname, '../dist/florale-emotion/index.html'));
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`);
|
|
}); |