A modern, feature-rich React application for tracking personal expenses and income with real-time balance updates, interactive animations, and comprehensive financial reporting.
- Overview
- Features
- Technology Stack
- Installation
- Usage
- Project Structure
- Components
- Documentation
- Screenshots
- License
This is a fully functional web application built with React 18 that helps users track their financial transactions. The app features a clean, modern interface with smooth animations, multi-page navigation using React Router, and persistent data storage using browser's localStorage.
- ๐ Real-time Balance Tracking - Automatic calculation of income, expenses, and total balance
- ๐จ Beautiful UI - Modern gradient design with smooth animations
- ๐ฑ Responsive Design - Works seamlessly on desktop, tablet, and mobile devices
- ๐พ Data Persistence - Transactions saved in browser's localStorage
- ๐ Smooth Animations - Slide-in and fade-out effects for better UX
- ๐ Financial Reports - Detailed breakdown by categories
- โ State Management - React hooks (useState, useEffect) for managing application state
- โ Props Architecture - Clean data flow between components
- โ Reusable Components - Modular design with TransactionList, TransactionItem, and AddTransactionForm
- โ React Router v6 - Multi-page navigation with Dashboard, Add Transaction, and Reports pages
- โ Form Validation - Input validation with user-friendly error messages
- โ CSS Animations - Smooth transitions and effects
- ๐ฐ Add income transactions (Salary, Freelance, Business, Investment, Other)
- ๐ธ Add expense transactions (Food, Transportation, Shopping, Bills, Entertainment, Health, Other)
- ๐๏ธ Delete transactions with animated effects
- ๐ View balance summary cards
- ๐ Generate financial reports by category
- ๐ View transaction history
- ๐พ Automatic data persistence
- React (18.3.1) - JavaScript library for building user interfaces
- React Router DOM (6.28.0) - Declarative routing for React applications
- CSS3 - Modern styling with animations, gradients, and flexbox/grid layouts
- React Scripts (5.0.1) - Create React App build tools
- Node.js - JavaScript runtime
- npm - Package manager
- Node.js (v14 or higher)
- npm (v6 or higher)
- Clone the repository
git clone https://github.com/stashlop/IP.git
cd IP- Navigate to the project directory
cd ip- Install dependencies
npm install- Start the development server
npm start- Open in browser The app will automatically open at http://localhost:3000
npm run buildThis creates an optimized production build in the build/ folder.
- Navigate to "Add Transaction" page
- Select transaction type (Income or Expense)
- Fill in the details:
- Description (e.g., "Monthly Salary", "Grocery Shopping")
- Amount (numeric value)
- Category (dynamic dropdown based on type)
- Date (defaults to today)
- Click "Add Transaction" button
- Watch the smooth animation as the transaction appears!
- Click on "Dashboard" in the navigation
- View your financial summary:
- Total Balance - Overall financial position
- Total Income - Sum of all income transactions
- Total Expenses - Sum of all expense transactions
- Scroll down to see recent transactions
- Click "Delete" on any transaction to remove it (with fade-out animation)
- Navigate to "Reports" page
- See comprehensive financial analysis:
- Summary cards with totals
- Income breakdown by category
- Expenses breakdown by category (sorted by amount)
- Transaction statistics
IP/
โโโ README.md # This file
โโโ SUBMISSION_DOCUMENTATION.md # Detailed project documentation
โโโ OUTPUT_PRINTOUTS.md # Terminal outputs and test results
โโโ CODERABBIT_SUMMARY.md # Code review summary
โโโ FINAL_SUBMISSION_SUMMARY.md # Submission checklist
โโโ ip/ # Main application folder
โโโ package.json # Dependencies and scripts
โโโ public/
โ โโโ index.html # HTML template
โ โโโ favicon.ico # App icon
โโโ src/
โโโ App.js # Main app component with routing
โโโ App.css # Global styles and animations
โโโ index.js # Entry point (React 18)
โโโ components/ # Reusable components
โ โโโ TransactionList.js # List of transactions
โ โโโ TransactionItem.js # Individual transaction card
โ โโโ AddTransactionForm.js # Form for adding transactions
โโโ pages/ # Page components
โโโ Dashboard.js # Dashboard page
โโโ AddTransaction.js # Add transaction page
โโโ Reports.js # Reports page
- Purpose: Displays a list of all transactions
- Props:
transactions- Array of transaction objectsonDelete- Function to delete transactions
- Features: Empty state handling, maps through array, renders TransactionItem components
Basic Code:
function TransactionList({ transactions, onDelete }) {
if (transactions.length === 0) {
return <div>No transactions yet. Add your first transaction!</div>;
}
return (
<div className="transaction-list">
<h2>Recent Transactions</h2>
{transactions.map((transaction) => (
<TransactionItem
key={transaction.id}
transaction={transaction}
onDelete={onDelete}
/>
))}
</div>
);
}- Purpose: Renders individual transaction card
- Props:
transaction- Single transaction objectonDelete- Delete handler function
- Features: Color-coded by type, animated delete, displays all transaction details
Basic Code:
function TransactionItem({ transaction, onDelete }) {
return (
<div className={`transaction-item ${transaction.type}`}>
<div className="transaction-info">
<h4>{transaction.description}</h4>
<p>{transaction.category} โข {new Date(transaction.date).toLocaleDateString()}</p>
</div>
<div className="transaction-amount">
<span className={`amount ${transaction.type}`}>
{transaction.type === 'income' ? '+' : '-'}${transaction.amount.toFixed(2)}
</span>
<button onClick={() => onDelete(transaction.id)}>Delete</button>
</div>
</div>
);
}- Purpose: Form for adding new income/expense transactions
- Props:
onAddTransaction- Function to add transaction to state
- Features: Form validation, dynamic categories, controlled inputs, auto-navigation
Basic Code:
function AddTransactionForm({ onAddTransaction }) {
const [formData, setFormData] = useState({
type: 'expense',
description: '',
amount: '',
category: '',
date: new Date().toISOString().split('T')[0]
});
const handleSubmit = (e) => {
e.preventDefault();
const transaction = {
id: Date.now(),
...formData,
amount: parseFloat(formData.amount)
};
onAddTransaction(transaction);
// Reset form and navigate
};
return (
<form onSubmit={handleSubmit}>
<select name="type" value={formData.type} onChange={handleChange}>
<option value="expense">Expense</option>
<option value="income">Income</option>
</select>
<input type="text" name="description" placeholder="Description" required />
<input type="number" name="amount" placeholder="Amount" required />
<select name="category" required>
<option value="">Select Category</option>
{/* Dynamic categories based on type */}
</select>
<input type="date" name="date" />
<button type="submit">Add Transaction</button>
</form>
);
}- Route:
/ - Description: Main dashboard showing financial overview with balance summary cards and recent transactions list
- Features:
- Real-time balance calculations
- Total income and expense display
- Recent transactions list
- Delete transaction functionality
Basic Code:
function Dashboard({ transactions, onDelete }) {
// Calculate totals
const totalIncome = transactions
.filter(t => t.type === 'income')
.reduce((sum, t) => sum + t.amount, 0);
const totalExpense = transactions
.filter(t => t.type === 'expense')
.reduce((sum, t) => sum + t.amount, 0);
const balance = totalIncome - totalExpense;
return (
<div className="dashboard">
<h1>Dashboard</h1>
{/* Balance Summary Cards */}
<div className="balance-summary">
<div className="balance-card total">
<h3>Total Balance</h3>
<p>${balance.toFixed(2)}</p>
</div>
<div className="balance-card income">
<h3>Total Income</h3>
<p>${totalIncome.toFixed(2)}</p>
</div>
<div className="balance-card expense">
<h3>Total Expenses</h3>
<p>${totalExpense.toFixed(2)}</p>
</div>
</div>
{/* Transaction List */}
<TransactionList transactions={transactions} onDelete={onDelete} />
</div>
);
}- Route:
/add - Description: Dedicated page with a form to add new income or expense transactions
- Features:
- Type selection (Income/Expense)
- Form validation
- Dynamic category dropdown
- Auto-redirect after submission
Basic Code:
function AddTransaction({ onAddTransaction }) {
return (
<div className="container">
<AddTransactionForm onAddTransaction={onAddTransaction} />
</div>
);
}Full Form Implementation:
function AddTransaction({ onAddTransaction }) {
const navigate = useNavigate();
const [formData, setFormData] = useState({
type: 'expense',
description: '',
amount: '',
category: '',
date: new Date().toISOString().split('T')[0]
});
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
if (!formData.description || !formData.amount || !formData.category) {
alert('Please fill all fields');
return;
}
const transaction = {
id: Date.now(),
type: formData.type,
description: formData.description,
amount: parseFloat(formData.amount),
category: formData.category,
date: formData.date
};
onAddTransaction(transaction);
navigate('/'); // Redirect to dashboard
};
return (
<form className="add-transaction-form" onSubmit={handleSubmit}>
<h2>Add Transaction</h2>
{/* Form fields here */}
<button type="submit">Add Transaction</button>
</form>
);
}- Route:
/reports - Description: Financial analysis page showing detailed breakdown of income and expenses by category
- Features:
- Summary statistics
- Income by category
- Expenses by category (sorted by amount)
- Transaction count
Basic Code:
function Reports({ transactions }) {
// Calculate totals
const totalIncome = transactions
.filter(t => t.type === 'income')
.reduce((sum, t) => sum + t.amount, 0);
const totalExpense = transactions
.filter(t => t.type === 'expense')
.reduce((sum, t) => sum + t.amount, 0);
const balance = totalIncome - totalExpense;
// Group by category
const incomeByCategory = transactions
.filter(t => t.type === 'income')
.reduce((acc, t) => {
acc[t.category] = (acc[t.category] || 0) + t.amount;
return acc;
}, {});
const expenseByCategory = transactions
.filter(t => t.type === 'expense')
.reduce((acc, t) => {
acc[t.category] = (acc[t.category] || 0) + t.amount;
return acc;
}, {});
return (
<div className="reports">
<h2>Financial Reports</h2>
{/* Summary Section */}
<div className="report-section">
<h3>Summary</h3>
<div className="balance-summary">
<div className="balance-card total">
<h3>Net Balance</h3>
<p>${balance.toFixed(2)}</p>
</div>
<div className="balance-card income">
<h3>Total Income</h3>
<p>${totalIncome.toFixed(2)}</p>
</div>
<div className="balance-card expense">
<h3>Total Expenses</h3>
<p>${totalExpense.toFixed(2)}</p>
</div>
</div>
</div>
{/* Income by Category */}
<div className="report-section">
<h3>Income by Category</h3>
{Object.entries(incomeByCategory).map(([category, amount]) => (
<div key={category} className="category-item">
<span>{category}</span>
<span>${amount.toFixed(2)}</span>
</div>
))}
</div>
{/* Expenses by Category */}
<div className="report-section">
<h3>Expenses by Category</h3>
{Object.entries(expenseByCategory)
.sort((a, b) => b[1] - a[1]) // Sort by amount
.map(([category, amount]) => (
<div key={category} className="category-item">
<span>{category}</span>
<span>${amount.toFixed(2)}</span>
</div>
))}
</div>
{/* Statistics */}
<div className="report-section">
<h3>Transaction History</h3>
<p>Total Transactions: {transactions.length}</p>
<p>Income Transactions: {transactions.filter(t => t.type === 'income').length}</p>
<p>Expense Transactions: {transactions.filter(t => t.type === 'expense').length}</p>
</div>
</div>
);
}This repository includes comprehensive documentation:
- SUBMISSION_DOCUMENTATION.md - Complete implementation details, code structure, testing results
- OUTPUT_PRINTOUTS.md - Terminal outputs, git history, test scenarios
- CODERABBIT_SUMMARY.md - Code review and quality assessment
- FINAL_SUBMISSION_SUMMARY.md - Submission checklist and verification
- Balance summary cards (Total, Income, Expenses)
- Recent transactions list
- Delete functionality with animations
- Clean form interface
- Type selection (Income/Expense)
- Dynamic category dropdown
- Date picker
- Financial summary
- Income by category
- Expenses by category
- Transaction statistics
- Primary Gradient: Purple (#667eea โ #764ba2)
- Income: Green gradient (#11998e โ #38ef7d)
- Expense: Red gradient (#ee0979 โ #ff6a00)
- Background: White cards on gradient background
- Slide-in: New transactions appear with smooth slide-up effect (0.5s)
- Fade-out: Deleted transactions disappear with fade and scale effect (0.3s)
- Hover Effects: Buttons and items have interactive hover states
- Transitions: All navigation and state changes are smoothly animated
All features have been thoroughly tested:
- โ Add income transactions
- โ Add expense transactions
- โ Delete transactions
- โ Balance calculations
- โ Navigation between pages
- โ Form validation
- โ Data persistence (refresh browser)
- โ Responsive design
- โ Animations
- Optimized React components
- CSS animations (GPU accelerated)
- Minimal re-renders
- LocalStorage for fast data access
- No external heavy libraries
- Chrome/Edge (Chromium) โ
- Firefox โ
- Safari โ
- Modern browsers with ES6+ support
This project is created for educational purposes.
stashlop
- GitHub: @stashlop
- Repository: https://github.com/stashlop/IP
- React team for the amazing framework
- React Router team for the routing solution
- Create React App for the build setup
Potential features for future versions:
- ๐ Charts and graphs (Chart.js integration)
- ๐ค Export data to CSV/Excel
- ๐ Search and filter transactions
- ๐ Date range filtering
- ๐ฏ Budget goals and alerts
- ๐ฅ Multiple accounts support
- ๐ Dark mode toggle
- ๐ User authentication
- ๐ Backend API integration
- ๐ฑ Multi-currency support
For questions or issues:
- Check the documentation files in this repository
- Review the code comments
- Create an issue on GitHub
โญ If you find this project helpful, please give it a star!
๐ Happy Tracking! ๐