From e8e1bcd9115f520eb46c066c673159bdcb3445e9 Mon Sep 17 00:00:00 2001 From: Sawan Date: Sun, 10 Nov 2024 11:44:24 +0530 Subject: [PATCH] Added newsletter functionality to glassy ui --- server/app.js | 9 ++- server/controllers/newsletterController.js | 27 +++++++ server/model/Newsletter.js | 23 ++++++ server/routes/newsletterRoute.js | 11 +++ server/sendSuscribedMail.js | 59 +++++++++++++++ src/components/Footer.tsx | 83 ++++++++++++++-------- 6 files changed, 179 insertions(+), 33 deletions(-) create mode 100644 server/controllers/newsletterController.js create mode 100644 server/model/Newsletter.js create mode 100644 server/routes/newsletterRoute.js create mode 100644 server/sendSuscribedMail.js diff --git a/server/app.js b/server/app.js index 9b2ee27..bdbde96 100644 --- a/server/app.js +++ b/server/app.js @@ -3,6 +3,7 @@ import dotenv from 'dotenv'; import connectDB from './utils/db.js'; import cors from 'cors'; import contactRoutes from './routes/contactRoutes.js'; +import newsletterRoutes from './routes/newsletterRoute.js'; dotenv.config(); const app = express(); @@ -10,11 +11,15 @@ connectDB(); app.use(express.json()); -// to avoid cross-origin error -app.use(cors()); +app.use( + cors({ + origin: 'http://localhost:3000', // replace with your frontend origin + }), +); // Serve static files from the uploads directory app.use('/api/contact', contactRoutes); +app.use('/api/newsletter', newsletterRoutes); const PORT = process.env.PORT || 5000; app.listen(PORT, () => { diff --git a/server/controllers/newsletterController.js b/server/controllers/newsletterController.js new file mode 100644 index 0000000..107a9ae --- /dev/null +++ b/server/controllers/newsletterController.js @@ -0,0 +1,27 @@ +import NewsLetter from '../model/Newsletter.js'; +import { sendMailToSubscriber } from '../sendSuscribedMail.js'; + +export async function saveNewsletter(req, res) { + try { + const { name, email } = req.body; + + if (!name || !email) { + return res.status(400).json({ message: 'All fields are required.' }); + } + + // Create new contact document + const newNewsLetter = new NewsLetter({ name, email }); + sendMailToSubscriber(newNewsLetter); + await newNewsLetter.save(); + res + .status(201) + .json({ message: 'Contact form submitted successfully!', newNewsLetter }); + } catch (error) { + console.error('Error saving contact form:', error); + res.status(500).json({ message: 'Failed to submit contact form.', error }); + } +} + +export async function getNewsletter(req, res) { + res.send('hello newsletter'); +} diff --git a/server/model/Newsletter.js b/server/model/Newsletter.js new file mode 100644 index 0000000..599fc36 --- /dev/null +++ b/server/model/Newsletter.js @@ -0,0 +1,23 @@ +import mongoose from 'mongoose'; + +const newsletterSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + }, + email: { + type: String, + required: true, + trim: true, + match: [/^\S+@\S+\.\S+$/, 'Please enter a valid email address'], + }, + subscribedAt: { + type: Date, + default: Date.now, + }, +}); + +const Newsletter = mongoose.model('Newsletter', newsletterSchema); + +export default Newsletter; diff --git a/server/routes/newsletterRoute.js b/server/routes/newsletterRoute.js new file mode 100644 index 0000000..a9e60e7 --- /dev/null +++ b/server/routes/newsletterRoute.js @@ -0,0 +1,11 @@ +import express from 'express'; +const router = express.Router(); +import { + getNewsletter, + saveNewsletter, +} from '../controllers/newsletterController.js'; + +router.post('/subscribe', saveNewsletter); +router.get('/getNewsletter', getNewsletter); + +export default router; diff --git a/server/sendSuscribedMail.js b/server/sendSuscribedMail.js new file mode 100644 index 0000000..c0a8b06 --- /dev/null +++ b/server/sendSuscribedMail.js @@ -0,0 +1,59 @@ +import nodemailer from 'nodemailer'; +import dotenv from 'dotenv'; +dotenv.config(); + +const sendMailToSubscriber = userdata => { + const transporter = nodemailer.createTransport({ + service: 'gmail', + host: 'smtp.gmail.com', + port: 587, + secure: false, + auth: { + user: process.env.EMAIL_ID, + pass: process.env.PASS_KEY, + }, + }); + + async function main() { + await transporter.sendMail({ + from: { + name: 'GlassyUI-Components', + address: process.env.EMAIL_ID, + }, + to: userdata.email, + subject: 'Welcome to GlassyUI-Components! 🎉', + text: 'Thank you for subscribing to GlassyUI-Components!', + html: ` +
+
+

Welcome to GlassyUI-Components, ${userdata.name}!

+

+ Hi ${userdata.name}, +

+

+ We’re thrilled to have you join us at GlassyUI-Components, an open-source library that brings you beautiful glassmorphism-themed React components. Our library is perfect for creating sleek, modern web applications, and we can’t wait for you to explore and enjoy it! +

+

✨ Features

+
    +
  • Glassmorphism-themed React components
  • +
  • Customizable styles with SCSS
  • +
  • Beginner-friendly and easy to contribute
  • +
  • Modular and reusable components
  • +
+

+ Stay tuned for the latest updates and don’t hesitate to contribute to make GlassyUI-Components even better! +

+

+ Best Regards,
+ The GlassyUI-Components Team +

+
+
+ `, + }); + } + + main().catch(console.error); +}; + +export { sendMailToSubscriber }; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index ca315d6..3963e05 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -8,26 +8,29 @@ const Footer: React.FC = () => { const handleSubmit = async (e: FormEvent) => { e.preventDefault(); - console.log(name + ' ' + email); - // try { - // const response = await fetch("http://localhost:5000/api/newsletter/subscribe", { - // method: "POST", - // headers: { - // "Content-Type": "application/json", - // }, - // body: JSON.stringify({ name, email }), - // }); - - // if (response.ok) { - // alert("Subscription successful!"); - // setName(""); - // setEmail(""); - // } else { - // alert("Failed to subscribe."); - // } - // } catch (error) { - // alert("An error occurred. Please try again."); - // } + + try { + const response = await fetch( + 'http://localhost:5000/api/newsletter/subscribe', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, email }), + }, + ); + + if (response.ok) { + alert('Subscription successful!'); + setName(''); + setEmail(''); + } else { + alert('Failed to subscribe.'); + } + } catch (error) { + alert('An error occurred. Please try again.'); + } }; return ( @@ -57,7 +60,35 @@ const Footer: React.FC = () => { -
+
+ {/* Newsletter Section */} +
+
+ setName(e.target.value)} + className='mb-4 md:mb-0 md:mr-2 px-4 py-2 w-full md:w-1/2 text-black rounded-md border border-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-500' + /> + setEmail(e.target.value)} + className='mb-4 md:mb-0 md:mr-2 px-4 py-2 w-full md:w-1/2 text-black rounded-md border border-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-500' + /> + +
+
{ } `}
-

- © 2024 GlassyUI. All rights reserved. -