Skip to content

Commit

Permalink
Merge pull request #174 from 17arindam/newsletter
Browse files Browse the repository at this point in the history
Feat: Newsletter saved to db and a thank you mail is sent to email
  • Loading branch information
RamakrushnaBiswal authored Oct 9, 2024
2 parents 180babd + 90c2df1 commit eb33f68
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 0 deletions.
34 changes: 34 additions & 0 deletions backend/config/nodemailer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,40 @@ const transporter = nodemailer.createTransport({
},
});

// Function to send newsletter subscription confirmation via email
exports.sendSubscriptionConfirmation = async (email) => {
// Construct the email content
const emailText = `
Dear Customer,
Thank you for subscribing to our newsletter! We're excited to have you on board.
You will now receive regular updates about our latest boardgame collections, special offers, and upcoming events.
If you have any questions or feedback, feel free to reach out.
Best regards,
PlayCafe Team
`;

try {
await transporter.sendMail({
from: process.env.EMAIL_USER,
to: email,
subject: "Thank You for Subscribing!",
text: emailText,
});
logger.info('Newsletter subscription confirmation sent successfully via email', { email });
} catch (error) {
logger.error('Failed to send newsletter subscription confirmation email', { error, email });
if (error.code === 'ECONNREFUSED') {
throw new Error('Failed to connect to email server. Please try again later.');
} else {
throw new Error(`Failed to send subscription confirmation email: ${error.message}`);
}
}
};

// Function to send reservation confirmation via email
exports.sendReservationConfirmation = async (email, reservationDetails) => {
const { reservationDate, guests, time } = reservationDetails;
Expand Down
35 changes: 35 additions & 0 deletions backend/controller/newsletter.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const NewsletterEmail = require('../models/newsletter.model'); // Import the Mongoose model
const { sendSubscriptionConfirmation } = require('../config/nodemailer'); // Import the mailer function

// Controller for handling newsletter subscriptions
exports.subscribeToNewsletter = async (req, res) => {
const { email } = req.body;

if (!email) {
return res.status(400).json({ error: 'Email is required' });
}

try {
// Check if the email already exists in the database
const existingEmail = await NewsletterEmail.findOne({ email });
if (existingEmail) {
return res.status(400).json({ error: 'This email is already subscribed.' });
}

// Save the email to the database
const newEmail = new NewsletterEmail({ email });
await newEmail.save();

try {
await sendSubscriptionConfirmation(email);
} catch (error) {
console.error('Error sending confirmation email:', error);
return res.status(500).json({ error: 'Subscription successful, but there was an error sending the confirmation email.' });
}

return res.status(201).json({ message: 'Subscription successful! A confirmation email has been sent.' });
} catch (error) {
console.error('Error subscribing to newsletter:', error);
return res.status(500).json({ error: 'Error subscribing to the newsletter.' });
}
};
19 changes: 19 additions & 0 deletions backend/models/newsletter.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const mongoose = require('mongoose');

// Define the schema for newsletter emails
const NewsletterEmailSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true, // Ensure no duplicate emails
trim: true,
match: [/.+\@.+\..+/, 'Please enter a valid email address'], // Simple email validation
},
subscribedAt: {
type: Date,
default: Date.now, // Automatically set the date of subscription
}
});

// Export the model
module.exports = mongoose.model('NewsletterEmail', NewsletterEmailSchema);
1 change: 1 addition & 0 deletions backend/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ router.use("/admin", require("./adminRouter"));
router.use("/feedback", feedbackRouter);
router.use("/user", require("./customerRouter"));
router.use("/reservation", require("./reservationRouter"));
router.use("/newsletter", require("./newsletterRoute"));


module.exports = router;
10 changes: 10 additions & 0 deletions backend/routes/newsletterRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const express = require("express");
const { subscribeToNewsletter } = require("../controller/newsletter.controller"); // Import the controller
const router = express.Router();
require("dotenv").config();



router.post("/subscribe", subscribeToNewsletter);

module.exports = router;
52 changes: 52 additions & 0 deletions frontend/src/components/Pages/Boardgame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,37 @@ import board8 from "../../assets/Boardgames/board8.png";
import board10 from "../../assets/Boardgames/board10.png";
import bg from "../../assets/Boardgames/bg.jpg";


import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';

export default function Boardgame() {
const [selectedBoard, setSelectedBoard] = useState(null);
const [email, setEmail] = useState('');

const handleSubmit = async (e) => {
e.preventDefault();
try {
// Make the POST request to /newsletter/subscribe endpoint using fetch
const response = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/newsletter/subscribe`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
alert('Subscription successful! Check your email for confirmation.');
} catch (error) {
console.error('Error subscribing to newsletter:', error);
alert('Error subscribing. Please try again.');
}
};

const handleOpenInstructions = (board) => {
setSelectedBoard(board);
Expand Down Expand Up @@ -217,6 +243,32 @@ export default function Boardgame() {
))}
</div>
</section>
<section className="w-full py-12 md:py-24 lg:py-32 bg-gray-100">
<div className="container mx-auto px-4 md:px-6 text-center">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl md:text-5xl lg:text-6xl mb-4">
Subscribe to our Newsletter
</h2>
<p className="mx-auto max-w-[700px] text-muted-foreground md:text-xl mb-6">
Stay updated with our latest boardgame collections, special offers, and events. Subscribe now and never miss out!
</p>
<form className="flex flex-col items-center space-y-4 sm:space-y-0 sm:flex-row sm:space-x-4 justify-center" onSubmit={handleSubmit}>
<input
type="email"
className="px-4 py-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)} // Update email state on input change
required
/>
<button
type="submit"
className="px-6 py-2 text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Subscribe
</button>
</form>
</div>
</section>

{/* Modal for instructions */}
{selectedBoard && (
Expand Down

0 comments on commit eb33f68

Please sign in to comment.