From bcc024011f04422459af167424dbd737be8686da Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:48:17 +0000 Subject: [PATCH 1/9] docs(contributor): contrib-readme-action has updated readme --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0725e235..3754393d 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,15 @@ Special thanks to our amazing mentors who are guiding this project! 🙌 Jai Dhingra + + + Jay-1409 +
+ Jay shah +
+ + + Mohitranag18 @@ -220,8 +229,6 @@ Special thanks to our amazing mentors who are guiding this project! 🙌 Mohit Rana - - MutiatBash From 7246c02ef23418c72cae853362c7207dafdab47c Mon Sep 17 00:00:00 2001 From: Arindam <17arindambera@gmail.com> Date: Wed, 9 Oct 2024 01:20:08 +0530 Subject: [PATCH 2/9] newsletter task completed --- backend/config/nodemailer.js | 34 ++++++++++++++++++ backend/controller/newsletter.controller.js | 31 ++++++++++++++++ backend/models/newsletter.model.js | 19 ++++++++++ backend/routes/index.js | 1 + backend/routes/newsletterRoute.js | 10 ++++++ frontend/src/components/Pages/Boardgame.jsx | 40 +++++++++++++++++++++ 6 files changed, 135 insertions(+) create mode 100644 backend/controller/newsletter.controller.js create mode 100644 backend/models/newsletter.model.js create mode 100644 backend/routes/newsletterRoute.js diff --git a/backend/config/nodemailer.js b/backend/config/nodemailer.js index ad25a5c1..cef4bdf5 100644 --- a/backend/config/nodemailer.js +++ b/backend/config/nodemailer.js @@ -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; diff --git a/backend/controller/newsletter.controller.js b/backend/controller/newsletter.controller.js new file mode 100644 index 00000000..95ea8a4f --- /dev/null +++ b/backend/controller/newsletter.controller.js @@ -0,0 +1,31 @@ +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(); + + // Send a confirmation email + await sendSubscriptionConfirmation(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.' }); + } +}; diff --git a/backend/models/newsletter.model.js b/backend/models/newsletter.model.js new file mode 100644 index 00000000..d38e259c --- /dev/null +++ b/backend/models/newsletter.model.js @@ -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); \ No newline at end of file diff --git a/backend/routes/index.js b/backend/routes/index.js index 6b72eab3..84691d63 100644 --- a/backend/routes/index.js +++ b/backend/routes/index.js @@ -37,6 +37,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; diff --git a/backend/routes/newsletterRoute.js b/backend/routes/newsletterRoute.js new file mode 100644 index 00000000..3552d8d2 --- /dev/null +++ b/backend/routes/newsletterRoute.js @@ -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; diff --git a/frontend/src/components/Pages/Boardgame.jsx b/frontend/src/components/Pages/Boardgame.jsx index 768068d3..43c64a65 100644 --- a/frontend/src/components/Pages/Boardgame.jsx +++ b/frontend/src/components/Pages/Boardgame.jsx @@ -9,12 +9,26 @@ import board7 from "../../assets/Boardgames/board7.png"; import board8 from "../../assets/Boardgames/board8.png"; import board10 from "../../assets/Boardgames/board10.png"; import bg from "../../assets/Boardgames/bg.jpg"; +import axios from 'axios'; 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 + const response = await axios.post('http://localhost:3000/api/newsletter/subscribe', { email }); + 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); @@ -217,6 +231,32 @@ export default function Boardgame() { ))} +
+
+

+ Subscribe to our Newsletter +

+

+ Stay updated with our latest boardgame collections, special offers, and events. Subscribe now and never miss out! +

+
+ setEmail(e.target.value)} // Update email state on input change + required + /> + +
+
+
{/* Modal for instructions */} {selectedBoard && ( From 619b217b76411172fe8e19d53711cc5b68d88976 Mon Sep 17 00:00:00 2001 From: Arindam <17arindambera@gmail.com> Date: Wed, 9 Oct 2024 01:53:25 +0530 Subject: [PATCH 3/9] code rabbit suggestion 1 implemented --- backend/controller/newsletter.controller.js | 8 ++++++-- frontend/src/components/Pages/Boardgame.jsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/controller/newsletter.controller.js b/backend/controller/newsletter.controller.js index 95ea8a4f..2292855a 100644 --- a/backend/controller/newsletter.controller.js +++ b/backend/controller/newsletter.controller.js @@ -20,8 +20,12 @@ exports.subscribeToNewsletter = async (req, res) => { const newEmail = new NewsletterEmail({ email }); await newEmail.save(); - // Send a confirmation email - await sendSubscriptionConfirmation(email); + 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) { diff --git a/frontend/src/components/Pages/Boardgame.jsx b/frontend/src/components/Pages/Boardgame.jsx index 43c64a65..d53f6157 100644 --- a/frontend/src/components/Pages/Boardgame.jsx +++ b/frontend/src/components/Pages/Boardgame.jsx @@ -22,7 +22,7 @@ export default function Boardgame() { e.preventDefault(); try { // Make the POST request to /newsletter/subscribe endpoint - const response = await axios.post('http://localhost:3000/api/newsletter/subscribe', { email }); + const response = await axios.post(`${import.meta.env.VITE_BACKEND_URL}/api/newsletter/subscribe`, { email }); alert('Subscription successful! Check your email for confirmation.'); } catch (error) { console.error('Error subscribing to newsletter:', error); From c881d6494a8d892b7c89a60dd6cda10fb8c087d6 Mon Sep 17 00:00:00 2001 From: Arindam <17arindambera@gmail.com> Date: Wed, 9 Oct 2024 02:43:30 +0530 Subject: [PATCH 4/9] logout modal pop added --- frontend/src/components/Shared/Navbar.jsx | 57 +++++++++++++++++------ 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/Shared/Navbar.jsx b/frontend/src/components/Shared/Navbar.jsx index 6864af6b..524cabdb 100644 --- a/frontend/src/components/Shared/Navbar.jsx +++ b/frontend/src/components/Shared/Navbar.jsx @@ -1,9 +1,10 @@ -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect } from "react"; import Logo from "../../assets/Logo/playcafe.png"; import { Link, useLocation } from "react-router-dom"; const Navbar = () => { const [isloggedIn, setisloggedIn] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); const [isScrolled, setIsScrolled] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); const location = useLocation(); @@ -24,8 +25,6 @@ const Navbar = () => { window.addEventListener("scroll", handleScroll); - - return () => { window.removeEventListener("scroll", handleScroll); }; @@ -35,6 +34,11 @@ const Navbar = () => { setIsMenuOpen(!isMenuOpen); }; + const handleLogout = () => { + setisloggedIn(false); // Set isLoggedIn to false on confirmation + setIsModalOpen(false); // Close the modal + }; + const isHomePage = location.pathname === "/"; let buttonTextClass; if (isScrolled) { @@ -51,9 +55,8 @@ const Navbar = () => { return (