From 143a68da53499ce80bdfa22e602ef6b4685b936c Mon Sep 17 00:00:00 2001 From: younes1337 Date: Tue, 30 Jan 2024 17:25:45 +0100 Subject: [PATCH 1/3] Commit Message: Update SignUp component to handle user sign-up and display Snackbar messages Description: - Modified the SignUp component to handle user sign-up functionality. - Implemented asynchronous form submission handling in the handleSubmit function. - Added error handling using try-catch blocks to catch errors during sign-up. - Updated the Snackbar messages to provide feedback to the user based on the sign-up status. - Snackbar messages now display success message for successful sign-up and error message for failed sign-up attempts. - If the error response indicates that the email already exists, the Snackbar displays a message informing the user that the email is already in use. - Implemented efficient error handling to provide clear feedback to the user. --- .gitignore | 3 +- client/package.json | 2 +- client/src/App.js | 6 +- client/src/actions/userActions.js | 27 ++++ client/src/componets/Auth/Copyright.jsx | 17 +++ client/src/componets/Auth/SingIn.jsx | 112 ++++++++++++++++ client/src/componets/Auth/SingUp.jsx | 171 ++++++++++++++++++++++++ client/src/componets/Header.js | 8 +- client/src/componets/Login.js | 117 ---------------- server/.gitignore | 2 +- server/config/db.js | 4 +- server/controller/user-contoller.js | 80 ++++++----- server/model/User.js | 16 ++- server/package.json | 151 +++++++++++---------- server/routes/user-routes.js | 10 +- server/server.js | 38 ++++-- 16 files changed, 507 insertions(+), 257 deletions(-) create mode 100644 client/src/actions/userActions.js create mode 100644 client/src/componets/Auth/Copyright.jsx create mode 100644 client/src/componets/Auth/SingIn.jsx create mode 100644 client/src/componets/Auth/SingUp.jsx delete mode 100644 client/src/componets/Login.js diff --git a/.gitignore b/.gitignore index 49e0fc6b..ffe3c43c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules -/package-lock.json \ No newline at end of file +/package-lock.json +/config.env \ No newline at end of file diff --git a/client/package.json b/client/package.json index 5be513f5..69beb879 100644 --- a/client/package.json +++ b/client/package.json @@ -1,7 +1,7 @@ { "name": "client", "version": "0.1.0", - "private": true, + "proxy": "http://localhost:4000", "dependencies": { "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", diff --git a/client/src/App.js b/client/src/App.js index 5b28d753..f0e9efda 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -2,7 +2,8 @@ import './App.css'; import { Route, Routes } from "react-router-dom"; import Header from './componets/Header'; import React from 'react'; -import Login from './componets/Login'; +import SingIn from './componets/Auth/SingIn'; +import SingUp from './componets/Auth/SingUp'; import Blogs from './componets/Blogs'; import UserBlogs from './componets/UserBlogs' import AddBlogs from './componets/AddBlogs' @@ -17,7 +18,8 @@ function App() {
- }> + }> + }> }> }> }> diff --git a/client/src/actions/userActions.js b/client/src/actions/userActions.js new file mode 100644 index 00000000..50387eae --- /dev/null +++ b/client/src/actions/userActions.js @@ -0,0 +1,27 @@ +import axios from 'axios' + + + +export const signUp = async (userData) => { + try { + const res = await axios.post('/api/v1/signup', userData); + console.log(res.data) + return res.data; + + } catch (error) { + console.error('Error signing up:', error); + throw error; + } +}; + + +export const signIn = async (userData) => { + try { + const res = await axios.post('/api/v1/signin', userData); + return res.data; + } catch (error) { + console.error('Error signing in:', error); + throw error; + } + }; + \ No newline at end of file diff --git a/client/src/componets/Auth/Copyright.jsx b/client/src/componets/Auth/Copyright.jsx new file mode 100644 index 00000000..990942b6 --- /dev/null +++ b/client/src/componets/Auth/Copyright.jsx @@ -0,0 +1,17 @@ +import Typography from '@mui/material/Typography'; +import Link from '@mui/material/Link'; + +function Copyright(props) { + return ( + + {'Copyright © '} + + SafEarth + {' '} + {new Date().getFullYear()} + {'.'} + + ); +} + +export default Copyright diff --git a/client/src/componets/Auth/SingIn.jsx b/client/src/componets/Auth/SingIn.jsx new file mode 100644 index 00000000..ae85cebb --- /dev/null +++ b/client/src/componets/Auth/SingIn.jsx @@ -0,0 +1,112 @@ +import React, { useState } from 'react'; +import Avatar from '@mui/material/Avatar'; +import Button from '@mui/material/Button'; +import CssBaseline from '@mui/material/CssBaseline'; +import TextField from '@mui/material/TextField'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Checkbox from '@mui/material/Checkbox'; +import Link from '@mui/material/Link'; +import Grid from '@mui/material/Grid'; +import Box from '@mui/material/Box'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +import Typography from '@mui/material/Typography'; +import Container from '@mui/material/Container'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +import { signIn } from '../../actions/userActions'; + +const defaultTheme = createTheme(); + +const SignInPage = () => { + const [signInError, setSignInError] = useState(null); + + const handleSubmit = async (event) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const email = formData.get('email'); + const password = formData.get('password'); + + try { + const signInData = await signIn({ email, password }); + console.log('Sign In Successful:', signInData); + // Handle successful sign-in, such as redirecting to a new page + } catch (error) { + console.error('Error signing in:', error.message); + setSignInError('Invalid email or password. Please try again.'); + } + }; + + return ( + + + + + + + + + Sign in + + + + + } + label="Remember me" + /> + {signInError && ( + + {signInError} + + )} + + + + + Forgot password? + + + + + {"Don't have an account? Sign Up"} + + + + + + + + ); +}; + +export default SignInPage; diff --git a/client/src/componets/Auth/SingUp.jsx b/client/src/componets/Auth/SingUp.jsx new file mode 100644 index 00000000..a1a23be5 --- /dev/null +++ b/client/src/componets/Auth/SingUp.jsx @@ -0,0 +1,171 @@ +import * as React from 'react'; +import Avatar from '@mui/material/Avatar'; +import Button from '@mui/material/Button'; +import CssBaseline from '@mui/material/CssBaseline'; +import TextField from '@mui/material/TextField'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Checkbox from '@mui/material/Checkbox'; +import Link from '@mui/material/Link'; +import Grid from '@mui/material/Grid'; +import Box from '@mui/material/Box'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +import Typography from '@mui/material/Typography'; +import Container from '@mui/material/Container'; +import Snackbar from '@mui/material/Snackbar'; +import MuiAlert from '@mui/material/Alert'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +import { signUp } from '../../actions/userActions' +import { useState } from 'react'; +import Copyright from './Copyright'; + + +// TODO remove, this demo shouldn't need to reset the theme. + +const defaultTheme = createTheme(); + +const SingUp = () => { + const [openSnackbar, setOpenSnackbar] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(''); + const [snackbarSeverity, setSnackbarSeverity] = useState('success'); + + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; + + const handleSubmit = async (event) => { + event.preventDefault(); + const data = new FormData(event.currentTarget); + const userData = { + firstName: data.get('firstName'), + lastName: data.get('lastName'), + email: data.get('email'), + password: data.get('password'), + }; + console.log(userData) + try { + const response = await signUp(userData); + console.log('Signed up successfully:', response); + setSnackbarSeverity('success'); + setSnackbarMessage('User created successfully'); + setOpenSnackbar(true); + } catch (error) { + console.error('Error signing up:', error); + if (error.response && error.response.data.message === 'User already exists') { + setSnackbarSeverity('error'); + setSnackbarMessage('The email is already in use. Please use a different email.'); + } else { + setSnackbarSeverity('error'); + setSnackbarMessage('Error signing up. Please try again.'); + } + setOpenSnackbar(true); + } + }; + + + return ( + + + + + + + + + Sign up + + + + + + + + + + + + + + + + + } + label="I want to receive inspiration, marketing promotions and updates via email." + /> + + + + + + + Already have an account? Sign in + + + + + + + + {snackbarMessage} + + + + + + ); +} +export default SingUp diff --git a/client/src/componets/Header.js b/client/src/componets/Header.js index f41bb7a6..20150cc5 100644 --- a/client/src/componets/Header.js +++ b/client/src/componets/Header.js @@ -56,14 +56,14 @@ const Header = () => { {!isLoggedIn && ( <> - - - - - ); -}; - -export default Login; \ No newline at end of file diff --git a/server/.gitignore b/server/.gitignore index 49e0fc6b..d5025124 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,2 +1,2 @@ /node_modules -/package-lock.json \ No newline at end of file +/package-lock.json diff --git a/server/config/db.js b/server/config/db.js index cd0e9cdd..81eeaeb7 100644 --- a/server/config/db.js +++ b/server/config/db.js @@ -3,8 +3,8 @@ const mongoose = require("mongoose"); mongoose.set('strictQuery', false); -mongoose.connect("mongodb://127.0.0.1:27017/BlogApp").then(()=>{ - console.log("connected!"); +mongoose.connect("mongodb+srv://raymondyounes:cu4yLypyIbmMfL7K@younes-dev.enszkpk.mongodb.net/test").then(()=>{ + console.log("DataBase Is connected Now Let's Store Some Data..!"); }).catch((err)=>{ console.log(err); }) \ No newline at end of file diff --git a/server/controller/user-contoller.js b/server/controller/user-contoller.js index 192c7d00..4d8ae260 100644 --- a/server/controller/user-contoller.js +++ b/server/controller/user-contoller.js @@ -1,6 +1,52 @@ -const User = require("../model/User"); +const User = require("../model/User.js"); const bcrypt = require("bcryptjs"); + +const signUp = async (req, res, next) => { + console.log(req.body); + // Extracting fields from the request body + const { firstName, lastName, email, password } = req.body; + + try { + // Checking if the user already exists + const existingUser = await User.findOne({ email }); + if (existingUser) { + // If a user with the same email exists, return a 400 status with a message + return res.status(400).json({ message: "User already exists" }); + } + // Hashing the password + const hashedPassword = await bcrypt.hash(password, 10); + console.log('hashed password: ', hashedPassword); + + // Creating a new user instance + const newUser = new User({ + firstName, + lastName, + email, + password: hashedPassword, + blogs: [] + }); + + // Saving the new user to the database + await newUser.save(); + + // Log the response + console.log("User created successfully:", newUser); + + // Sending a success response + res.status(201).json({ message: "User created successfully", user: newUser }); + } catch (error) { + // Handling any errors that occur during the signup process + console.error("Error signing up:", error); + res.status(500).json({ message: "Internal server error" }); + } +}; + + + + + + const getAllUser = async(req,res,next) =>{ let users; @@ -17,35 +63,9 @@ const getAllUser = async(req,res,next) =>{ return res.status(200).json({users}); } -const signUp = async(req,res,next) =>{ - const { name , email , password } = req.body; - - let existingUser; - - try{ - existingUser = await User.findOne({email}) - }catch(e){ - console.log(err); - } - - if(existingUser){ - return res.status(400).json({message : "User is already exists!"}) - } - const hashedPassword = bcrypt.hashSync(password); - const user = new User({ - name,email, - password: hashedPassword, - blogs: [] - }); - - try{ - user.save(); - return res.status(201).json({ user }) - } - catch(e){console.log(e);} -} -const logIn = async(req,res,next) => { + +const singIn = async(req,res,next) => { const {email , password} = req.body; let existingUser; @@ -68,4 +88,4 @@ const logIn = async(req,res,next) => { return res.status(200).json({user: existingUser}); } -module.exports = { getAllUser, signUp , logIn}; \ No newline at end of file +module.exports = { getAllUser, signUp , singIn}; \ No newline at end of file diff --git a/server/model/User.js b/server/model/User.js index 1ee5cdff..4afd1887 100644 --- a/server/model/User.js +++ b/server/model/User.js @@ -3,24 +3,26 @@ const mongoose = require("mongoose"); const Schema = mongoose.Schema; const userSchema = new Schema({ - name : { + firstName : { + type: String, + required: true, + }, + lastName: { type: String, required: true, }, - email : { type: String, required: true, unique: true, }, - password: { type: String, required: true, - minlength: 6 + minlength: 10 }, - blogs: [{ type: mongoose.Types.ObjectId, ref: "Blog", required: true }], -}) +}); + -module.exports = mongoose.model("User", userSchema); \ No newline at end of file +module.exports = mongoose.model("TestUsers", userSchema); \ No newline at end of file diff --git a/server/package.json b/server/package.json index 5bc27252..39643099 100644 --- a/server/package.json +++ b/server/package.json @@ -1,73 +1,78 @@ -{ - - - "name": "blogapp", - - - "version": "1.0.0", - - - "description": "", - - - "main": "server.js", - - - "scripts": { - - - - - "start": "nodemon server.js", - - - - - "test": "echo \"Error: no test specified\" && exit 1" - - - }, - - - "author": "khushi patel", - - - "license": "ISC", - - - "devDependencies": { - - - - - "nodemon": "^2.0.16" - - - }, - - - "dependencies": { - - - - - "bcryptjs": "^2.4.3", - - - - - "cors": "^2.8.5", - - - - - "express": "^4.18.1", - - - - - "mongoose": "^6.3.4" - - - } -} +{ + + + "name": "blogapp", + + + "version": "1.0.0", + + + "description": "", + + + "main": "server.js", + + + "scripts": { + + + + + "start": "nodemon server.js", + + + + + "test": "echo \"Error: no test specified\" && exit 1" + + + }, + + + "author": "khushi patel", + + + "license": "ISC", + + + "devDependencies": { + + + + + "nodemon": "^2.0.16" + + + }, + + + "dependencies": { + + + + + "bcryptjs": "^2.4.3", + + + + + "body-parser": "^1.20.2", + + + + + "cors": "^2.8.5", + + + + + "express": "^4.18.1", + + + + + "mongoose": "^6.3.4" + + + } +} diff --git a/server/routes/user-routes.js b/server/routes/user-routes.js index b36dcee7..a079fd1d 100644 --- a/server/routes/user-routes.js +++ b/server/routes/user-routes.js @@ -1,10 +1,10 @@ +// user-routes.js const express = require("express"); -const { getAllUser , signUp ,logIn } = require("../controller/user-contoller"); +const { getAllUser, signUp, singIn } = require("../controller/user-contoller"); const userRouter = express.Router(); - -userRouter.get("/",getAllUser); +userRouter.get("/", getAllUser); userRouter.post("/signup", signUp); -userRouter.post("/login" , logIn); +userRouter.post("/signin", singIn); -module.exports = userRouter; \ No newline at end of file +module.exports = userRouter; diff --git a/server/server.js b/server/server.js index df557554..06f4b2a6 100644 --- a/server/server.js +++ b/server/server.js @@ -1,23 +1,33 @@ -const express = require("express"); -const userRouter = require("./routes/user-routes"); +const express = require('express'); +const path = require('path'); +const app = express(); +const userRouter = require("./routes/user-routes"); const blogRouter = require("./routes/blog-routes"); +const bodyParser = require('body-parser'); + require("./config/db"); const cors = require('cors'); -const app = express(); - -app.use(cors()); +// Serve static files from the React app +app.use(express.static(path.join(__dirname, 'client/build'))); -app.set("view engine","ejs"); -app.use(express.json()); +// Handle all other routes by returning the React app's HTML file +app.get('*', (req, res) => { + res.sendFile(path.join(__dirname+'/client/build/index.html')); +}); -app.use("/api/users",userRouter); -app.use("/api/blogs",blogRouter); +// Parse application/x-www-form-urlencoded +app.use(bodyParser.urlencoded({ extended: false })); -app.use("/api",(req,res,next) =>{ - res.send("hello") -}) +// Parse application/json +app.use(bodyParser.json()); -//define port +// Define API routes +app.use("/api/v1", userRouter); +app.use("/api/v1", blogRouter); -app.listen(5000, () => console.log("app started at 5000...")); \ No newline at end of file +// Define port +const PORT = process.env.PORT || 4000; +app.listen(PORT, () => { + console.log(`Server is listening on port ${PORT}`); +}); From 73ccd3294e8351a4dedd37f3bfb96b824cc31bed Mon Sep 17 00:00:00 2001 From: younes1337 Date: Tue, 30 Jan 2024 17:30:39 +0100 Subject: [PATCH 2/3] Commit Message: Update SignUp component to handle user sign-up and display Snackbar messages Description: - Modified the SignUp component to handle user sign-up functionality. - Implemented asynchronous form submission handling in the handleSubmit function. - Added error handling using try-catch blocks to catch errors during sign-up. - Updated the Snackbar messages to provide feedback to the user based on the sign-up status. - Snackbar messages now display success message for successful sign-up and error message for failed sign-up attempts. - If the error response indicates that the email already exists, the Snackbar displays a message informing the user that the email is already in use. - Implemented efficient error handling to provide clear feedback to the user. --- server/config/db.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config/db.js b/server/config/db.js index 81eeaeb7..b67eaba9 100644 --- a/server/config/db.js +++ b/server/config/db.js @@ -3,7 +3,7 @@ const mongoose = require("mongoose"); mongoose.set('strictQuery', false); -mongoose.connect("mongodb+srv://raymondyounes:cu4yLypyIbmMfL7K@younes-dev.enszkpk.mongodb.net/test").then(()=>{ +mongoose.connect("Enter you MongoDb Uri").then(()=>{ console.log("DataBase Is connected Now Let's Store Some Data..!"); }).catch((err)=>{ console.log(err); From 520feeac2cf753e9947469bbf0049a4d0c9e5b24 Mon Sep 17 00:00:00 2001 From: younes1337 Date: Tue, 30 Jan 2024 17:36:05 +0100 Subject: [PATCH 3/3] Commit Message: Update SignUp component to handle user sign-up and display Snackbar messages Description: - Modified the SignUp component to handle user sign-up functionality. - Implemented asynchronous form submission handling in the handleSubmit function. - Added error handling using try-catch blocks to catch errors during sign-up. - Updated the Snackbar messages to provide feedback to the user based on the sign-up status. - Snackbar messages now display success message for successful sign-up and error message for failed sign-up attempts. - If the error response indicates that the email already exists, the Snackbar displays a message informing the user that the email is already in use. - Implemented efficient error handling to provide clear feedback to the user. --- server/config/db.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config/db.js b/server/config/db.js index b67eaba9..29a5f303 100644 --- a/server/config/db.js +++ b/server/config/db.js @@ -3,7 +3,7 @@ const mongoose = require("mongoose"); mongoose.set('strictQuery', false); -mongoose.connect("Enter you MongoDb Uri").then(()=>{ +mongoose.connect("Enter you MongoDb Uri Here").then(()=>{ console.log("DataBase Is connected Now Let's Store Some Data..!"); }).catch((err)=>{ console.log(err);