Challenge

Project 1 - Expense tracker

Answers:

Folder Structure:

my-expense-tracker/

|-- src/

| |-- components/

| | |-- ExpenseForm.js

| | |-- ExpenseList.js

| | |-- ExpenseChart.js

| |-- App.js

| |-- index.js

App.js (Main Application Component):

import React, { useState } from 'react';

import ExpenseForm from './components/ExpenseForm';

import ExpenseList from './components/ExpenseList';

import ExpenseChart from './components/ExpenseChart';

const App = () => {

const [expenses, setExpenses] = useState([]);

const addExpenseHandler = (expense) => {

setExpenses((prevExpenses) => [...prevExpenses, expense]);

};

const updateExpenseHandler = (updatedExpense) => {

setExpenses((prevExpenses) =>

prevExpenses.map((expense) =>

expense.id === updatedExpense.id ? updatedExpense : expense

)

);

};

const deleteExpenseHandler = (expenseId) => {

setExpenses((prevExpenses) =>

prevExpenses.filter((expense) => expense.id !== expenseId)

);

};

return (

<div>

<h1>Expense Tracker</h1>

<ExpenseForm onAddExpense={addExpenseHandler} />

<ExpenseList

expenses={expenses}

onUpdateExpense={updateExpenseHandler}

onDeleteExpense={deleteExpenseHandler}

/>

<ExpenseChart expenses={expenses} />

</div>

);

};

export default App;

ExpenseForm.js (Form Component):

import React, { useState } from 'react';

const ExpenseForm = ({ onAddExpense }) => {

const [title, setTitle] = useState('');

const [amount, setAmount] = useState('');

const [date, setDate] = useState('');

const submitHandler = (e) => {

e.preventDefault();

const expenseData = {

title,

amount: +amount,

date: new Date(date),

};

onAddExpense(expenseData);

// Clear the form

setTitle('');

setAmount('');

setDate('');

};

return (

<form onSubmit={submitHandler}>

<label>Title</label>

<input

type="text"

value={title}

onChange={(e) => setTitle(e.target.value)}

/>

<label>Amount</label>

<input

type="number"

min="0.01"

step="0.01"

value={amount}

onChange={(e) => setAmount(e.target.value)}

/>

<label>Date</label>

<input

type="date"

value={date}

onChange={(e) => setDate(e.target.value)}

/>

<button type="submit">Add Expense</button>

</form>

);

};

export default ExpenseForm;

ExpenseList.js (List Component):

import React from 'react';

import ExpenseItem from './ExpenseItem';

const ExpenseList = ({ expenses, onUpdateExpense, onDeleteExpense }) => {

if (expenses.length === 0) {

return <p>No expenses found.</p>;

}

return (

<ul>

{expenses.map((expense) => (

<ExpenseItem

key={expense.id}

expense={expense}

onUpdateExpense={onUpdateExpense}

onDeleteExpense={onDeleteExpense}

/>

))}

</ul>

);

};

export default ExpenseList;

ExpenseItem.js (Item Component):

import React from 'react';

const ExpenseItem = ({ expense, onUpdateExpense, onDeleteExpense }) => {

return (

<li>

<div>{expense.title}</div>

<div>${expense.amount}</div>

<div>{expense.date.toISOString()}</div>

<button onClick={() => onUpdateExpense(expense)}>Edit</button>

<button onClick={() => onDeleteExpense(expense.id)}>Delete</button>

</li>

);

};

export default ExpenseItem;

ExpenseChart.js (Chart Component):

import React from 'react';

import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';

const ExpenseChart = ({ expenses }) => {

const chartData = expenses.map((expense) => ({

month: expense.date.toLocaleString('en-US', { month: 'short' }),

amount: expense.amount,

}));

return (

<BarChart width={600} height={300} data={chartData}>

<XAxis dataKey="month" />

<YAxis />

<CartesianGrid strokeDasharray="3 3" />

<Tooltip />

<Legend />

<Bar dataKey="amount" fill="#8884d8" />

</BarChart>

);

};

export default ExpenseChart;

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.