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;