0% found this document useful (0 votes)
38 views

Expense Management System Using MERN Stack

Expense Management System using MERN Stack

Uploaded by

Ronny Camacho
Copyright
© © All Rights Reserved
Available Formats
Download as PDF or read online on Scribd
0% found this document useful (0 votes)
38 views

Expense Management System Using MERN Stack

Expense Management System using MERN Stack

Uploaded by

Ronny Camacho
Copyright
© © All Rights Reserved
Available Formats
Download as PDF or read online on Scribd
You are on page 1/ 28
TutorialsDSAData ScienceWeb TechCourses oS MERN Stack MERN Interview Questions MERN Projects MERN StackDeveloper ReactJS React Interviev Expense Management System using MERN Stack Last Updated : 11 Mar, 2024 In this article, we'll walk through the step-by-step process of creating a Expense Management System using the MERN (MongoDB, ExpressIS, React, NodeJS) stack. This project will showcase how to set up a full-stack web application where users can add their budget and put daily expenses that get deducted from the budget. Output Preview: Let us have a look at how the final output will look like. GEG Budget Tracker Gee] || Gee as fa Create New Budget Page Prerequisites: NPM & NodeJS ReactlS MongoDB. ExpressJS JsonWebToken Approach to Create Expense Management System using MERN: * List all the requirement for the project and make the structure of the project accordingly. * Chooses the required dependencies and requirement which are more suitable for the project For Backend:- * Create a directory named model inside root directory. * Create javascript files named Userjs and Budgets in the model directory for collection schema + Then create another route directory inside root(Backend folder) * Create javascript files named authjs and budget,js to handle API request. For Frontend:- * Create a components directory inside root directory( Budget_Tracker folder). * Create four file of javascript inside components folder namely Expense jsx, Home,jsx, RegistrationForm,sx and LoginForm,jsx. Steps to Create the Backend Server: Step 1: Create a directory for project mkdir Backend cd Backend Step 2: Create a server using the following command in your terminal. npm init -y Step 3: Install the required dependencies in your server using the following command npm i express mongoose cors noderon jsonwebtoken Project Structure: routes or Preress The package,json file of backend will look like: "dependencies": { “beryptis": "42.4.3", "cors": "2.8.5", "express": "44,18,2", “jsonwebtoken": "49.2.2", "mongoose": "48.2.0" Example: Below is an example of server for creating budget tracker with MERN Stack. Javascript JJ server. js const express = require('express'); const bodyParser = require(‘body-parser'); const mongoose = require('mongoose'); const authRoutes = require('./routes/auth'); const budgetRoutes = require(’./routes/budget'); const cors = require('cors') const app = express(); const PORT = process.env.PORT || 4000; app-use(cors()) app-use(bodyParser.json()); mongoose. connect ('mongodb: //localhost:27017/ny-app' t useNewUrlParser: true, useUnifiedTopology: true v3 app.use('/auth', authRoutes); app.use(’/budget', budgetRoutes) ; app.listen(PORT, () => { console.log(Server is running on port ${PORT}”); Y3 Javascript J/ routes/auth.js const const const const const express = require('express'); router = express.Router(); berypt = require(‘beryptjs"); Jwt = require(' jsonwebtoken" ); User = require('../models/User'); router.post('/signup', async (req, res) => { const { name, email, password } = req.body; try { } ? 3 const existingUser = await User.findone({ email }); if (existinguser) { return res.status(40@).json({ message: ‘User already exists’ vs const hashedPassword = await bcrypt.hash(password, 10); const newUser = new User({ email, password: hashedPassword vs await newUser.save(); res. status (201). json({ message: ‘User created successfully’ ys catch (error) ( res. status (500) . json({ message: ‘Internal server error’ ns router.post('/login’, async (req, res) => { const { email, password } = req.body; try { const user = await User.findOne({ email }); if (tuser) { return res.status(40@) .json({ message: ‘Invalid email or password’ ys const passwordMatch = await bcrypt.compare( password, user.password) ; if (IpasswordMatch) { return res.status(40@) .json({ message: ‘Invalid email or password" ys const token = jwt.sign({ userid: user._id }, "your_secret_key"); res.status(20@).json({ token }); } catch (error) { res.status (500). json({ message: ‘Internal server error’ ys } Ys module.exports = router; Javascript // routes /budget.js const express = require(' express’); const router = express .Router(); const berypt = require('berypt js"); const jwt = require('jsonwebtoken'); const User = require('../models/User'); const Budget = require(’../models/Budget"); const mongoose = require('mongoose’); // authentication middleware const authMiddleware = async (req, res, next) => { const token = req.header(*Authorization'); if (!token) return res.status(401).json({ message: ‘Access denied’ 3 try { const decoded = jwt.verify(token, ‘your_secret_key'); req.user = await User. findById(decoded.userld) ; next(); ) catch (error) ¢ res.status(400).Json({ message: "Invalid token’ }); oH router.get('/:id/expenses', authMiddleware, async (req, res) => { const { id } = req.params; try { const budgets = await Budget.findOne({ _id: id }); console. log(budgets) if (Ibudgets) { return res.status(20@).json({ expenses: [] })3 , const { available, remaining, totalexpenses } = calculateamounts (budgets) ; const data = { available, remaining, used: totalexpenses, budgets, name: budgets name, total: budgets. totalAmount y console. log(data) res.status(200).json({ data: data }); } catch (error) { console. 1og(error) res. status (500). json({ message: ‘Internal server error’ ns n3 J/ Create a new budget router.post('/create’, authMiddleware, async (req, res) => { const { name, totalAmount } = req. body; try { const newBudget = new Budget ({ nane, totalanount, user: req.user._id, expenses: [], ys await newBudget.save(); res. status(201) . json(newBudget) ; } catch (error) ( res.status (500). json({ message: ‘Internal server error’ ys 3 // Enter an expense for a budget router.post(‘/:id/expenses', authMiddleware, async (req, res) => { const { id } = req.params; const { name, amount } = req. body; try { const budget = avait Budget. Findone({ “id: id, user: req.user._id Ds if (!budget) { return res.status (404) .json({ message: ‘Budget not found’ ys budget.expenses.push({ name, amount }); await budget.save(); res. status (200). json(budget) ; y catch (error) { res. status (500). json({ message: ‘Internal server error’ }); Y3 // Calculate available and remaining amounts for a budget function calculateAmounts(budget) { const totalexpenses = budget .expenses.reduce( (total, expense) => total + expense.anount, 8); const available = budget.totalAnount - totalexpenses; const remaining = budget.totalAmount - available; return { available, remaining, total€xpenses }; } router.get('/', authMiddleware, async (req, res) => { try { const budgets = await Budget.find({ user: req.user._id }); const budgetswWithAmounts = budgets.map(budget => { const { available, remaining } = calculateAmounts(budget); const used = budget.totalAmount - available; return { “id: budget._id, name: budget.name, totalanount: budget.totalanount, available, remaining, used, user: budget.user oe Ds res. status(200) .json(budgetsWithAmounts); } catch (error) { res.status(50@).json({ message: ‘Internal server error’ })5 Y3 module.exports = router Javascript // models/Budget. js const mongoose = require('mongoose'); const expenseSchema = new mongoose. Schema({ name: String, amount: Number, 3 const budgetSchema = new mongoose. Schema({ user: String, name: String, totalAnount: Number, expenses: [expenseSchema],, Y3 module.exports = mongoose.model(' Budget’, budgetSchema); Javascript // models/User.js const mongoose = require('mongoose’); const userSchema = new mongoose.Schema({ name: String, enail: string, password: String n3 module.exports = mongoose.model('User’, userSchema) ; Start your server using the following command. npm start Steps to Create the Frontend Application: Step 1: Initialized the React App with Vite and installing the required packages npm create vite@letest -y ->Enter Project name: "Frontend" >Select a framework: "React" +>Select a Variant: "Javascript" cd Frontend npm install Project Structure: The package,json file of frontend will look like: "dependencies": { "react": "18.2.8", “react=dom": "18.2.0", "react-icons": "45.0.1", “react=router=dom": "6.22.2" ds "devDependencies": { "@types/react": "418.2.56", "@types/react-dom": "418.2.19", "@vitejs/plugin-react": "4.2.1", “eslint": "*8.56.8", "eslint-plugin-react": "47.33.2", "eslint-plugin-react-hooks": "44.6.0", “eslint-plugin-react-refresh" "vite": "5.1, 8.4.5", Example: Below is an example of frontend for creating budget tracker with MERN Stack. css /* src/index.css */ “{ margin: 0; first { width: 50%; height: 1000px; float: left; «second { width: 50%; height: 1000px; float: right; sinputt { 82%5 2px 20px; margin: 8px @; display: inline-block; border: 1px solid greens border-radius: 4px; box-sizing: border-box; text-align: center; margin-left: 3%; btn { width: 10%; background-color: #4CArS0; color: white; padding: 12px 2@px; margin: 8px 05 border: none; border-radius: 4px; cursor: pointer; margin-left: 1%; stext { text-align: center margin: 2%5 sinput2 { width: 90%; padding: 12px 2@px; margin: 8px 05 display: inline-block; border: 1px solid #cccj border-radius: 4px; box-sizing: border-box; text-align: center; margin-left: 5%; -labelt { margin-left: 6%; font-size: large; -btn2 { width: 10%; background-color: blue; color: whites padding: 12px 20px; margin: 8px 0; border: none; border-radius: 4px; cursor: pointer; margin-left: 85%; stext2 { text-align: center; margin-top: 10%; color: blue; justify-content: centers sbudget { width: 55%; background-color: rgb(149, @, 255); color: white; Padding: 12px 2@px; text-align: center; border-radius: 15px; margin-top: 2%; margin-left: 5%; left { width: 55%; background-color: rgb(@, 255, 132); 2 whites + 2px 20px; margin-top: 2%; margin-left: 5%; text-align: center; border-radius: 15px; font-weight: bolder; sold ul { List-style-type: none; width: 60%; sold li { display: block; color: black; padding: 16px; border: 1px solid #ecc; border-radius: 4px; margin: 1%; width: 100%; display: flex; justify-content: space-between; snamel { sel border-radius: Spx; background-color: rgba(@, @, 255, 0.701) color: whites t padding: 35px; font-size: 30px; color: green; font-weight: bolder; margin: 0; padding: 0; -float-container { border: 3px solid #f Ff; 20px3 flex; justify-content: center; -first-child ( width: 50%; 2@px; border: 2px solid green; sinput_exp { width: 80%; padding: 12px 20px; margin: 8px 0; display: inline-block; border: 1px solid #ccc3 border-radius: 4px; box-sizing: border-box; margin-left: 10%; + sbtn_exp ( width: 80%; background-color: #4CAF5®; color: white; padding: 14px 2@px; margin: 8px @; border: none; border-radius: 4px; cursor: pointer; margin-left: 10%; + -btn_expzhover ( background-color: #452049; -second-child { width: 50%; float: right; padding: 2px; border: 2px solid greens anewul { List-style-type: none; -Liexp ( display: block; color: black; padding: 16px; border: 1px solid #cccs border-radius: 4px; width: 75%; display: flex; margin-left: 10%; margin-top: 3%; justify-content: space-between; stext_exp { color: blue; text-align: center; -name_exp { border-radius: Spx; color: black; font-weight: bolder; -outer_div { display: flex; justify-content: center; souter_btn { width: 40%; background-color: rgb(149, @, 255); color: whites padding: 12px 20px; text-align: center; border-radius: 15px; margin: 25px3 /* LoginForm.css */ -login-container { display: flex; justify-content: center; align-items: center; height: 1¢0vh; -login-form ¢ width: 350px; padding: 30px; border: 1px solid #ecc3 border-radius: Spx; padding-right: 30px; box-shadow: @ 2px Spx rgba(?, ®, @ 0.1)5 -login-form input { width: 100%; margin-bottom: 10px; padding: 15px; border: 1px solid #cccs border-radius: 3px; -login-form button { width: 100%; padding: 15px; background-color: #00ffe4; border: none; border-radius: 3px; color: FFF; font-size: 16px; cursor: pointer; -login-form button:hover { background-color: #0063745 15px; text-align: center; *{ margin: 0; padding: @; justify-conten padding-top: 5 centers sinput1 { width: 100%; margin: 8px 0; display: inline-block; border: 1px solid green; border-radius: 4px; box-sizing: border-box; text-align: center; abtnt { width: 15%; background-color: #4CAF50; color: whites padding: 12px 20x; margin: 8px 0; border: none; border-radius: 10px; cursor: pointers display: inline-block; of { width: 60%; serid { display: grid height: 20epx; width: 100%; gap: 20px; justify-content: center; grid-template-columns: auto auto auto; margin-top: 3@px; sinnert { border-radius: 16px; Padding: S2px; border: Spx solid rgba(1z8, 128, 128, 0.55); sina { width: auto; border: Spx ridge grays color: black; padding: Spx; vind { width: auto; border: Spx ridge gray; color: black; padding: Spx; margin-top: 10px3 -btn_exp ( background-color: He4Aa6D; border: none; color: whites text-align: center; text-decoration: none; display: inline-block; font-size: 13px; cursor: pointer; -registration-container { display: flex; justify-content: centers align-items: center; height: 1¢0vh; } “pl { padding: 15px3 text-align: center; } sregistration-form { width: 400px; padding: 20x; border: 1px solid #ccc; border-radius: Spx; box-shadow: @ 2px Spx rgba(®, 2, ® 0.1)5 -registration-form input { width: 100%; margin-bottom: 10px; padding: 1@px; border: 1px solid #cccs border-radius: 3px; sregistration-form button { width: 100%; padding: 1@px; background-color: #00ffa4; border: none; border-radius: 3px; color: #FFF; font-size: 16px; cursor: pointer; -registration-form buttonzhover { background-color: #006374; Javascript // src/main import React from "react"; import ReactDOM from “react-dom/client"; import "./index.css"; import LoginForm from ". /component/LoginForm. sx"; import RegistrationForm from . /component/RegistrationForm. jsx"; import { BrowserRouter, Routes, Route } from “react-router-dom" ; import Home from “./component/Home.jsx"; import Expense from "./component/Expense.jsx"} ReactDOM. createRoot (document. getéLementById("root™)) .render( 7" element={} /> "/login” element={} /> /register” element={} /> /expense/:id" element={} /> uw Javascript // src/conponent/Expense. jsx import React, { useeffect, usestate } from “react”; import { MdDeleteForever } from import { useNavigate, useParams } from “react-router-dor function Expense(props) { const navigate = useNavigate(); useéffect(() => { if (!localstorage.getItem('token')) { navigate("/login"); + » 0) let { id } = useParams(); const [expenses, setExpenses] = useState({}); const [expAdd, setExpAdd] = useState(true); const [name, setNane] = useState(''); const [anount, setAnount] = usestate( async function fetchExpenses() ¢ try const response = await fetch( “http: //localhost :4000/budget/${id}/expenses”, { headers: { Authorization: localStorage.getItem( token"), },// Assuming token is stored in local storage Ds if (Iresponse.ok) { ‘throw new Error(‘Failed to fetch expenses‘); y const data = await response. json(); console. log(data.data) if (data.data) { setExpenses(data.data); } catch (error) { console. log(error.message) console.error('Error fetching expenses:', error); us useEffect(() => { fetchExpenses(); }, [id]); // Runs whenever budgetid changes useEffect(() => { fetchExpenses(); }, LexpAdd]); // Runs whenever budgetTd changes const handleSubmit = async (e) => ( e.preventDefault (); try { const response await fetch( http: // localhost :3000/budget/${id}/expenses”, { method: ‘Post’, headers: { ‘Content-Type’: ‘application/ json", Authorization: localStorage.getItem(‘token"), }4// Assuming token is stored in local storage body: JSON. stringify({ name, amount }), vs if (Iresponse.ok) { ‘throw new Error('Failed to add expense’); const data = await response. json(); console. log(' Expense added:', data); alert ("added") setExpAdd(!expadd) y* Handle success: e.g., show a success message or update the UI */ } catch (error) { console.error('Error adding expense:', error); // Handle error: e.g., show an error message to the user + u return ( °

GFG Budget Tracker

Budget Name :{expenses.name}
{ if (llocalstorage.getItem(‘token')) { navigate("/login") + fetchbudgets(); }, [193 // Runs only once on component mount useEffect(() => { fetchBudgets(); }, [budAdd]); // Runs only once on component mount const handleSubmit = async (e) => { e.preventDefault(); try { const token = localStorage.getItem(‘token'); console. log(token) const response = await fetch( ‘http://localhost:4000/budget/create’, { method: ‘Post’, headers: { ‘content-Type': ‘application/json', Authorization: token, yy body: JSON. stringify({ name, totalAnount: amount }), ys const data = await response. json(); console. 1og( ‘Budget created:", data); alert("Budget created") setAddBud(!budAdd) } catch (error) { console.error('Error creating budget:', error); alert("Error creating budget”) + a return ( °

className=' input1" placeholder="Enter Expense Nane’ name} setName(e. target. value) } input1" Input Anount* placeholdet value=(amount} onChange={(e) => setAmount(e.target.value)} bP
{budget?.map((bud, index) => (

Don't Have an Account Sign Up

<> v3 wb export default LoginForm Javascript // sec/conponent /Registrationform.j import React, { useState } from ‘react’; import { Link, useNavigate } from “react-router-dom"; const RegistrationForm = () => { const [email, seténail] = usestate(''); const [password, setPassword] = useState("'); const [nane, setName] = useState(''); const navigate = useNavigate(); const handleSubmit = async (e) => ( e.preventDefault(); try { const response = await fetch( ‘http: //Jocalhost :408@/auth/signup’ , method: ‘POST’, headers: { "content-Type': ‘application/json’ hb body: JSON. stringify({ email, password » ys const data = await response. json(); if (response.ok) { localstorage.setItem(‘token’, data.token); alert(‘Success:', data.message) navigate("/login"); p else { console. error(data.message) ; alert(‘Error:", data.message) + } catch (error) { console.error(‘Error:", error); alert(‘Error:', error) y h return (
setNane(e.target.value)} required Pp Register

Sign In

3 oH export default Registrationforn: Start your frontend application using the following command. npm run dev Output: * Browser Output: Expens snagement System using MERN * Output of data saved in Database: Database of Expense Management Sys Want to be a Software Developer or a Working Professional looking to enhance your Software Development Skills? Then, master the concepts of Full-Stack Development. Our Full Stack Development - React and Nod Course will help you achieve this quickly. Learn everything from Front-End to Back-End Development with hands-on Projects and real-world examples. This course enables you to build scalable, efficient, dynamic web applications that stand out. Ready to become an expert in Full-Stack? Enroll Now and Start Creating the Future!

You might also like