Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contact us frontend with email functionality #275

Merged
merged 6 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@emailjs/browser": "^4.3.3",
"@react-icons/all-files": "^4.1.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand All @@ -12,7 +14,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.11.0",
"react-icons": "^4.12.0",
"react-icons-kit": "^2.0.0",
"react-modal": "^3.16.1",
"react-router-dom": "^6.16.0",
Expand Down
Binary file added public/c4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/i9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions server/controllers/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const User = require("../models/studentLoginInfo");
const jwt = require("jsonwebtoken");
const Canteen = require("../models/canteenLoginInfo");
const Session = require("../models/session");
const Contact = require('../models/Contact');

require("dotenv").config();

Expand Down Expand Up @@ -393,3 +394,22 @@ exports.changeCanteenPassword = async (req, res) => {
message: "Password updated successfully.",
});
};


//contactUs

exports.saveContactMessage = async (req, res) => {
try {
const { name, email, message } = req.body;
if (!name || !email || !message) {
return res.status(400).send('All fields are required');
}
const newContact = new Contact({ name, email, message });
await newContact.save();
res.status(201).send('Message received');
} catch (error) {
console.error('Error saving message:', error.message, error);
res.status(500).send('Error saving message');
}
};

11 changes: 11 additions & 0 deletions server/models/Contact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const mongoose = require('mongoose');

const contactSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
message: { type: String, required: true },
});

const Contact = mongoose.model('Contact', contactSchema);

module.exports = Contact;
7 changes: 7 additions & 0 deletions server/routes/contactRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const express = require('express');
const { saveContactMessage } = require('../controllers/Auth');
const router = express.Router();

router.post('/', saveContactMessage);

module.exports = router;
3 changes: 2 additions & 1 deletion server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const cors = require("cors");
var cookieParser = require("cookie-parser");
const PORT = process.env.PORT || 4000;
const cloudinaryConfig = require("./config/cloudinaryConfig");

const contactRoutes = require('./routes/contactRoutes');

app.use(
cors({
Expand All @@ -25,6 +25,7 @@ const uploadFileRouter = require("./routes/uploadFile");
app.use("/api/v1", canteenRoutes);
app.use("/api/v1", studentRoutes);
app.use("/api/v1", uploadFileRouter);
app.use('/api/contact', contactRoutes);

app.listen(PORT, () => {
console.log(`Server started succesfully at ${PORT}`);
Expand Down
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import News from './pages/News';
import NotFound from './pages/NotFound';
import Loader from './components/Loader/Loader';
import { ThemeProvider } from './themeContext';
import ContactUs from './pages/ContactUs';

const Layout = ({ children }) => {
return (
Expand All @@ -29,6 +30,7 @@ function App() {
<Route path='/home' element={<Layout><Home /></Layout>} />
<Route path='/login' element={<Login />} />
<Route path='/signup' element={<Signup />} />
<Route path='/contact' element={<ContactUs />} />
<Route path='/about' element={<Layout><About /></Layout>} />
<Route path='/section/:_id' element={<Layout><SectionPage /></Layout>} />
<Route path="/menu/:_id" element={<Layout><MenuPage /></Layout>} />
Expand Down
2 changes: 2 additions & 0 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const Navbar = () => {
<NavItem to="/home">Home</NavItem>
<NavItem to="/about">About</NavItem>
<NavItem to="/news">News</NavItem>
<NavItem to="/contact">Contact</NavItem>
</div>
</div>
</div>
Expand Down Expand Up @@ -81,6 +82,7 @@ const Navbar = () => {
<MobileNavItem to="/home">Home</MobileNavItem>
<MobileNavItem to="/about">About us</MobileNavItem>
<MobileNavItem to="/news">News</MobileNavItem>
<MobileNavItem to="/contact">Contact</MobileNavItem>
<MobileNavItem to="/">
<button
className="bg-green-500 hover:bg-green-700 text-white py-1 px-2 rounded transition duration-300 ease-in-out transform hover:scale-105"
Expand Down
167 changes: 167 additions & 0 deletions src/pages/ContactUs.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import React, { useRef, useState } from "react";
import { motion } from "framer-motion";
import emailjs from "@emailjs/browser";
import axios from "axios";


const Contact = () => {
const formRef = useRef();
const [form, setForm] = useState({
name: "",
email: "",
message: "",
});

const [loading, setLoading] = useState(false);

const handleChange = (e) => {
const { target } = e;
const { name, value } = target;

setForm({
...form,
[name]: value,
});
};

const handleEmailSubmit = async (e) => {
e.preventDefault();
setLoading(true);

try {
await emailjs.send(
'service_kssjugu',//write service id here
'template_cg8qcij',//write templet id here
{
from_name: form.name,
to_name: "FoodiesWeb",
from_email: form.email,
to_email: "info@foodiweb.com",
message: form.message,
},
'EJL9aVO3EzRRm0IYF' //write public_key here
);




setLoading(false);
alert("Thank you. I will get back to you as soon as possible.");

setForm({
name: "",
email: "",
message: "",
});
} catch (error) {
setLoading(false);
console.error(error);

alert("Sorry, something went wrong while sending your message. Please try again later.");
}
};
const handleSaveToDB = async (e) => {
e.preventDefault();
setLoading(true);

try {
// Save to MongoDB
await axios.post('http://localhost:3000/api/contact', form);

setLoading(false);
alert("Your message has been saved to the database.");

setForm({
name: "",
email: "",
message: "",
});
} catch (error) {
setLoading(false);
console.error(error);
alert("Sorry, something went wrong while saving your message to the database. Please try again later.");
}
};

return (
<div className="absolute overflow-hidden w-screen h-screen bg-gradient-to-t from-blue-950 via-blue-950 to-gray-950 ">
<p className="text-white font-medium text-4xl pl-10 pt-8">Get in touch</p>
<h3 className="text-white font-medium text-4xl pl-20 pt-3">Contact Us.</h3>
<div
className={`xl:mt-12 pl-64 flex xl:flex-row flex-col-reverse gap-10 overflow-hidden `}
>

<div className="absolute -bottom-32 -left-40 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>
<div className="absolute -bottom-40 -left-20 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>
<div className="absolute -top-40 -right-0 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>
<div className="absolute -top-20 -right-20 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>


<div className="ml-20 w-96 h-[20%] px-7 text-black shadow-blue-900 shadow3xl bg-blue-900 bg-gradient-to-t from-gray-900 rounded-3xl">

<form
ref={formRef}
onSubmit={handleEmailSubmit}
className='my-10 flex flex-col gap-8'
>
<label className='flex flex-col '>
<span className=' font-medium mb-2'>Your Name</span>
<input
type='text'
name='name'
value={form.name}
onChange={handleChange}
placeholder="What's your good name?"
className='bg-tertiary py-3 px-6 placeholder:text-secondary rounded-lg outline-none border-none font-medium '
/>
</label>
<label className='flex flex-col'>
<span className=' font-medium mb-2'>Your email</span>
<input
type='email'
name='email'
value={form.email}
onChange={handleChange}
placeholder="What's your web address?"
className='bg-tertiary py-3 px-6 placeholder:text-secondary rounded-lg outline-none border-none font-medium '
/>
</label>
<label className='flex flex-col'>
<span className=' font-medium mb-2'>Your Message</span>
<textarea
rows={5}
name='message'
value={form.message}
onChange={handleChange}
placeholder='What you want to say?'
className='bg-tertiary py-3 px-6 placeholder:text-secondary text-white rounded-lg outline-none border-none font-medium bg-gradient-to-t from-blue-950 via-blue-950 to-gray-900'
/>
</label>

<div className='flex gap-8'>
<button
type='submit'
className='bg-tertiary py-3 px-8 rounded-xl outline-none w-fit text-white font-bold shadow-md shadow-primary bg-cyan-700 hover:scale-[1.1]'
>
{loading ? "Sending..." : "Send_Mail"}
</button>
<button
type='button'
onClick={handleSaveToDB}
className='bg-tertiary py-3 px-8 rounded-xl outline-none w-fit text-white font-bold shadow-md shadow-primary bg-cyan-800 hover:scale-[1.1]'
>
{loading ? "Saving..." : "Submit"}
</button>
</div>
</form></div>
<div className=" -mt-10 ml-10 ">
<img src="/i9.png" className="w-full h-full"/>
</div>

</div><div className="p-10"></div>

</div>
);
};

export default Contact;
12 changes: 10 additions & 2 deletions src/pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,16 @@ function Login() {
{loading ? (
<Loader />
) : (
<div className="h-screen md:flex">
<div className="relative h-screen md:flex">
<div className="absolute top-0 right-0 m-3">
<Link to="/contact">
<button
className="hover:shadow-blue-950 hover:shadow-sm text-white py-1 px-2 w-full h-auto text-l relative z-0 rounded-full transition-all duration-200 hover:scale-110"
>
<img src="/c4.png" className="h-10 w-10" />
</button>
</Link>
</div>
<div className="relative overflow-hidden md:flex w-1/2 bg-gradient-to-t from-blue-950 via-blue-950 to-gray-900 bg-no-repeat justify-around items-center hidden">
<div>
<img
Expand All @@ -93,7 +102,6 @@ function Login() {
<div className="absolute -top-40 -right-0 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>
<div className="absolute -top-20 -right-20 w-80 h-80 border-4 rounded-full border-opacity-30 border-t-8"></div>
</div>

<div className="flex md:w-1/2 justify-center py-10 items-center bg-white">
<form
className="bg-white p-8 rounded shadow-lg w-80"
Expand Down