Skip to content

Commit

Permalink
Merge pull request #275 from Isha1233/Isha_contributer
Browse files Browse the repository at this point in the history
Contact us frontend with email functionality
  • Loading branch information
hustlerZzZ authored Jun 15, 2024
2 parents dba1004 + ee25dd4 commit bd773ba
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 2 deletions.
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.
25 changes: 25 additions & 0 deletions server/controllers/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ const User = require("../models/studentLoginInfo");
const jwt = require("jsonwebtoken");
const Canteen = require("../models/canteenLoginInfo");
const Session = require("../models/session");
<<<<<<< HEAD
const Contact = require('../models/Contact');
=======
const {
forgotPasswordToken,
verifyToken,
findUserByEmail,
findUserById,
} = require("../utils/PasswordTokenAndUser");
const nodemailer = require("nodemailer");
>>>>>>> upstream/main

require("dotenv").config();

Expand Down Expand Up @@ -441,6 +445,26 @@ exports.changeCanteenPassword = async (req, res) => {
});
};

<<<<<<< HEAD

//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');
}
};

=======
// verify user for reset password
exports.forgotPassword = async (req, res) => {
try {
Expand Down Expand Up @@ -578,3 +602,4 @@ exports.resetPassword = async (req, res) => {
res.status(500).json("Some error occurred!");
}
};
>>>>>>> upstream/main
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;
4 changes: 4 additions & 0 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ 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');
const bodyParser = require('body-parser');


app.use(
cors({
Expand All @@ -22,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
7 changes: 7 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ import Loader from './components/Loader/Loader';
import ForgotPassword from './pages/ForgotPassword';
import ResetPassword from './pages/ResetPassword';
import { ThemeProvider } from './themeContext';

import ContactUs from './pages/ContactUs';

import { AuthProvider } from './authContext'
import EditProfile from './pages/EditProfile';


const Layout = ({ children }) => {
return (
<div className="bg-cover bg-center min-h-screen bg-gradient-to-t from-blue-950 via-blue-950 to-gray-900 bg-no-repeat dark:bg-none">
Expand All @@ -35,8 +39,11 @@ 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='/forgotPassword' element={<ForgotPassword/>} />
<Route path='/api/v1/newPassword/:id/:token' element={<ResetPassword/>} />

<Route path='/about' element={<Layout><About /></Layout>} />
<Route path='/rateus' element={<Layout><Rateus /></Layout>} />
<Route path='/section/:_id' element={<Layout><SectionPage /></Layout>} />
Expand Down
15 changes: 15 additions & 0 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ const Navbar = () => {
</div>

<div className="hidden md:block">

<div className="ml-16 flex gap-6 items-baseline space-x-4">

<NavItem to="/home">Home</NavItem>
<NavItem to="/about">About</NavItem>
<NavItem to="/news">News</NavItem>
<NavItem to="/contact">Contact</NavItem>
<NavItem to="/home" icon={<IconHome />}>Home</NavItem>
<NavItem to="/about" icon={<IconAbout />}>About</NavItem>
<NavItem to="/news" icon={<IconNews />}>News</NavItem>
<NavItem to="/rateus" icon={<IconRateUs />}>RateUs</NavItem>

<div className="ml-16 flex gap-6 items-baseline space-x-4 ">
<NavItem to="/home" className="nav-item" icon={<IconHome />}>Home</NavItem>
<NavItem to="/about" className="nav-item" icon={<IconAbout />}>About</NavItem>
Expand Down Expand Up @@ -86,7 +98,10 @@ 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="/rateus">Rateus</MobileNavItem>

<MobileNavItem to="/">
<Link to="/">
<button
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(
'process.env.SERVICE_ID',//write service id here
'process.env.TEMPLETS_ID',//write templet id here
{
from_name: form.name,
to_name: "FoodiesWeb",
from_email: form.email,
to_email: "[email protected]",
message: form.message,
},
'process.env.PUBLIC_KEY' //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;
27 changes: 27 additions & 0 deletions src/pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,33 @@ function Login() {
}

return (
<>
{loading ? (
<Loader />
) : (
<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 src={logo} alt="logo" className="w-48 h-12 mb-2" />
<p className="text-white mt-1 ml-3">
Connecting You to Your College Canteens
</p>
</div>
<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>

<div className="h-screen md:flex">

<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">
Expand Down
4 changes: 3 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
module.exports = {
darkMode: 'class',
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],

theme: {
extend: {
colors:{
Expand Down

0 comments on commit bd773ba

Please sign in to comment.