Keeping track of daily expenses can be difficult, especially if a lot of items are purchased. As a result, we might not be aware of where particular expenses in our budget are allocated, an app that keeps track of our spending and displays it in a concise, precise manner is therefore essential.
The prerequisites for this project are:
Knowledge of CSS, Javascript, and React
Latest version of Node.js installed
Getting started
First, we create a new React app in the terminal using the code below.
npx create-react-app Budget manager
Next, we create a folder in the src
directory to store all of our app's components and styles.
In Parent.js
file, we import React, the hooks required for our project, and define our "Parent" component.
import React ,{useState,useEffect} from "react";
function Parent(){
return()
}
export default Parent
Next, we utilize the usestate
hook to store the the list of purchases made and input text.
const [purchases,setPurchases]=useState([])
const [purchase,setPurchase]=useState('')
const [dates,setDates]=useState('')
const [category,setCategory]=useState('')
const [cost,setCost]=useState('')
Building the operations of the app
We have to define of the activities that can be done on the app. We also define functions to update the values of the different sections of a purchase.
const _purchase=(e)=>{
setPurchase(e.target.value)
}
const _category=(e)=>{
setCategory(e.target.value)
}
const _cost=(e)=>{
setCost(e.target.value)
}
const savePurchase=()=>{
setPurchases((prevState)=>[...prevState,{
key:uuid(),
id:uuid(),
purchase:purchase,
category:category,
date:current_date,
cost:cost,
}
]);
setPurchase('')
setCategory('')
setCost('')
setDates('')
}
const deletePurchase=(id)=>{
const filteredPurchases=purchases.filter((purchase)=>{
return purchase.id !== id;
});
setPurchases(filteredPurchases)
}
In the above code:
The
savePurchase
function appends a new object to thepurchase
array.The
key
andid
are generated with uuidv4. It is set up usingnpm install uuidv4
in the terminal, and the following line of code imports it into the project:
import { v4 as uuid } from "uuid";
- The
deletePurchase
function takes in anid
argument and returns a filteredpurchases
array.
Creating a statistics section
Our app needs a statistics area to display the budget and total money spent. The cost of each purchase is added to a totalSpent
array, and the array's sum is used to determine the total amount spent.
The useEffect
hook is used to perform this so that the total is executed each time the purchases
array is changed.
useEffect(()=>{
const totalArray=purchases.map((item)=>{
const value= item.cost;
const num= parseFloat(value);
return num
});
setSpent(
totalArray.reduce((a,b)=>{
return a+b
},0));
},[purchases])
In order to load the app, we want the proposed budget to be entered by the user. In App.js
, we import the Parent
component and display the app if a condition is met.
import React,{useState} from 'react'
import Parent from './components/Parent';
function App() {
const [budget,setBudget]=useState()
const [page,setPage]=useState(true)
const updateBudget=(e)=>{
setBudget(e.target.value);
}
const saveBudget=()=>{
setPage(!page)
}
return (
<div className="App">
{page? <div className='createbudget'>
<h1>Get started by creating a new budget</h1>
<input onChange={updateBudget} type="number"/>
<button onClick={()=>{saveBudget()}} className="createbudget">create</button></div>
:
<Parent budget={budget}/>}
</div>
);
}
export default App;
The code above displays an input field when page
is set to 'true', the useState
hook is used to update the value of the budget variable. When the submit button is hit, the value of page
is changed to 'false', making the app display the parent component.
Defining our components
Next, we'll define the Createpurchase
,Stats
, and Tablelist
components which will be imported to the Parent
component.
Our Createpurchase
component displays a form that collects the information to be stored in a purchase, it is passed a number of props, each of which is allocated to a function in the Parent
component
import React from 'react'
function Createpurchase({save,pur,categ,cost,update}){
return(
<div className='create'>
<h5>New Purchase</h5>
<div>
<label >Purchase</label>
<input type="text" onChange={pur} value={update.pur} />
</div>
<div>
<label>Category</label>
<select onChange={categ} value={update.categ}>
<option>Housing</option>
<option>Food</option>
<option>Transportation</option>
<option>Utilities</option>
<option>Medical</option>
<option>Personal</option>
</select>
</div>
<div>
<label >Cost</label>
<input type="number" onChange={cost} value={update.cost}/>
</div>
<button onClick={save}>save</button>
</div>
)
}
export default Createpurchase
The stats component displays both the total amount spent and the budget provided by the user.
import React from 'react'
function Stats({spent,budget}){
return(
<div className='statistics'>
<span>
<h6>Spent</h6>
<p>${spent}</p>
</span>
<span>
<h6>Budget</h6>
<p>${budget}</p>
</span>
</div>
)
}
export default Stats
And the Tablelist
component comprises of the structure for a purchase saved in the app.
import React from 'react'
function Tablelist({purchase,category,date,cost,del,id}){
return(
<div className='list'>
<p className='purchase'>{purchase}</p>
<p className='category'>{category}</p>
<p className='date'>{date}</p>
<p className='cost'>${cost}</p>
<button onClick={()=>del(id)}>delete</button>
</div>
)
}
export default Tablelist
The Createpurchase
, Stat
, and Tablelist
components have been successfully defined, but they still need to be imported into the Parent.js
file. We return our imported components in the Parent
component and assign their props to our defined functions.
import Tablelist from "./Tablelist"
import Createpurchase from "./Createpurchase"
import Stats from "./Stats"
function Parent({budget}){
return(
<div>
<div className="dashboard">
<Stats spent={spent} budget={budget}/>
</div>
{purchases.map((row)=>(
<Tablelist purchase={row.purchase} key={row.key}
category={row.category} date={row.date} cost=
{row.cost} del={deletePurchase} id={row.id}/>
))}
<Createpurchase save={savePurchase} pur={_purchase}
categ={_category} cost={_cost} update={updateValues}/>
</div>
)
Adding a cost tracker chart
Our budget manager is almost complete, and the final thing to be added is a chart that displays the total cost spent on each category of purchase. The chart used in this project is gotten from Recharts, it is installed with the following line of code in the terminal:
npm install recharts
To accomplish this, we first create a Chart.js
file in our components
folder and then import the required resources to include a chart in our app. Next, we add the chart's content.
import React from "react";
import {PieChart,Pie,Tooltip} from 'recharts'
function Chart({data}){
return (
<PieChart width={300} height={300}>
<Pie
dataKey="value"
isAnimationActive={false}
data={data}
cx="50%"
cy="50%"
outerRadius={80}
fill="#6bbd99"
label
/>
<Tooltip />
</PieChart>
);
}
export default Chart
An array of values will be assigned to the chart's data
prop, which will be displayed in the chart.
<div className="chart">
<Chart data={chartData}/>
</div>
chartData
in the code above is an array that sums the total cost for each category.
Storing purchases using Localstorage
We'll utilize the javascript Localstorage
method to ensure that the purchases are not lost if the user leaves the app.
useEffect(()=>{
const data=JSON.parse(localStorage.getItem('Purchases'))
setPurchases(data)
},[])
useEffect(()=>{
localStorage.setItem('Purchases',JSON.stringify(purchases))
},[purchases])
The first useEffect
hook's second argument is an empty square bracket so it runs only when the app is first loaded while the second is only carried out when the purchases
array is modified.
Next we style our app in the Parent.css
file located in the css folder.
Conclusion
This article demonstrates a simple way of utilising React to build a budget manager app. We are able to do this using React hooks to store various data to be utilised later on, and also perform functions when an array is updated.
You can get the source code for this project on Github , a live demo of the site is on Vercel.
Top comments (0)