Flymango is a web application where users can share their good memories from their trips and search for the next destination.
- To build a Full Stack Web Application using MongoDB - Express - React - Node.
- Authentication & Login with JWT (Json Web Token)
- Creating Realtime Web App with CRUD function
- App with Redux Framework with React Hooks
After 'git-clone', you can simply run this application from your local server by installing each dependencies from Client and Server Client : yarn add jwt-decode react-google-login / Server: yarn add bcrypt jsonwebtoken
##Server side## . npm i body-parser : to POST request . npm i cors : Cross Origin Resource Sharing : a middleware to Connect/ Express . npm i express : a framework for creating the Routing of our application . npm i mongoose : to create models of our POST . npm i nodemon : auto reset the server . npm i bcryptjs jsonwebtoken
##Client side## . npm i @material-ui/core : ui kit used in this project . npm i axios : for making api request . npm i moment : library working with time and date . npm i react-file-base . npm i redux redux-thunk : asynchronous actions with redux . npm i jwt-decode react-google-login
.
│
└── Client
│ └── src
│ │ ├── actions
│ │ ├── api
│ │ ├── components
│ │ ├── constants
│ │ └── reducers
│ │
│ ├── App.js
│ └── index.js
│
└── Server
├── controller
├── middleware
├── models
├── routes
└── index.js
- Client / Auth.js : The Login Information entered by users received from Auth.js file and here the action is dispatched so the data is sent to Reducers.
const handleSubmit =(e)=> {
e.preventDefault();
if (isSignup) {
dispatch(signup(form, history))
} else {
dispatch(signin(form, history))
}
}
const handleChange=(e)=> {
setForm({...form,[e.target.name]: e.target.value});
}
const googleSuccess = async (res) => {
const result = res?.profileObj;
const token = res?.tokenId;
try {
dispatch({type: 'AUTH', data:{result, token}});
history.push('/');
} catch (error) {
console.log(error);
}
}
const googleFailure =( error ) => {
console.log("Google Sign In was unsuccessful. Try Again Later")
console.log(error);
}
- Client / Reducer > Auth.js : Once the action is dispatched to a reduce, based on the action type, it will be sent to reduces. In this case the action type was Auth so the Auth.js in reduces folder will be executed and the {state & action} will be received into Reducer.
const authReducer = (state = { authData: null }, action) => {
switch (action.type) {
case actionType.AUTH:
localStorage.setItem('profile', JSON.stringify({ ...action?.data }));
return { ...state, authData: action.data, loading: false, errors: null };
case actionType.LOGOUT:
localStorage.clear();
return { ...state, authData: null, loading: false, errors: null };
default:
return state;
}
};
- Server / controllers > user.js : This is where our server actually pass in the input data and save into our server.
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import UserModal from "../models/user.js";
const secret = "test";
export const signup = async (req, res) => {
const { email, password, firstName, lastName } = req.body;
try {
const oldUser = await UserModal.findOne({ email });
if (oldUser)
return res.status(400).json({ message: "User already exists" });
const hashedPassword = await bcrypt.hash(password, 12);
const result = await UserModal.create({
email,
password: hashedPassword,
name: `${firstName} ${lastName}`,
});
const token = jwt.sign({ email: result.email, id: result._id }, secret, {
expiresIn: "1h",
});
res.status(201).json({ result, token });
} catch (error) {
res.status(500).json({ message: "Something went wrong" });
console.log(error);
}
};
export const signin = async (req, res) => {
const { email, password } = req.body;
try {
const oldUser = await UserModal.findOne({ email });
if (!oldUser)
return res.status(404).json({ message: "User doesn't exist" });
const isPasswordCorrect = await bcrypt.compare(password, oldUser.password);
if (!isPasswordCorrect)
return res.status(400).json({ message: "Invalid credentials" });
const token = jwt.sign({ email: oldUser.email, id: oldUser._id }, secret, {
expiresIn: "1h",
});
res.status(200).json({ result: oldUser, token });
} catch (err) {
res.status(500).json({ message: "Something went wrong" });
}
};