diff --git a/src/components/TrackExpenses.jsx b/src/components/TrackExpenses.jsx index 58fc04e..8391d9a 100644 --- a/src/components/TrackExpenses.jsx +++ b/src/components/TrackExpenses.jsx @@ -1,20 +1,382 @@ -import React from "react"; -import { Link } from "react-router-dom"; +import React, { useState, useEffect } from 'react'; +import { Link } from 'react-router-dom'; +import { useTransactions } from './TransactionContext'; +import { useCurrency } from './CurrencyContext'; +import { motion } from 'framer-motion'; +import { + Plus, + TrendingUp, + TrendingDown, + Calendar, + Filter, + Search, + ArrowLeft, + BarChart3, + PieChart, + DollarSign, + Receipt, + Target, + Sparkles +} from 'lucide-react'; +import AddTransactionModal from './AddTransactionModal'; const TrackExpenses = () => { + const { transactions, income, expense } = useTransactions(); + const { currency, locale } = useCurrency(); + const [showAddModal, setShowAddModal] = useState(false); + const [searchTerm, setSearchTerm] = useState(''); + const [filterType, setFilterType] = useState('All'); + const [filterCategory, setFilterCategory] = useState('All'); + const [sortBy, setSortBy] = useState('date'); + + const getCurrencySymbol = (currency, locale) => { + return (0).toLocaleString(locale, { + style: "currency", + currency, + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }).replace(/\d/g, "").trim(); + }; + + const formatAmount = (amount) => { + return amount.toLocaleString(locale, { + style: 'currency', + currency, + minimumFractionDigits: 0, + maximumFractionDigits: 2, + }); + }; + + const getCategoryIcon = (category) => { + const icons = { + 'Food': '🍕', + 'Transport': '🚗', + 'Groceries': '🛒', + 'Entertainment': '🎬', + 'Bills': '📄', + 'Shopping': '🛍️', + 'Rent': '🏠', + 'Utilities': '⚡', + 'EMI': '💳', + 'Income': '💰', + 'Others': '📦' + }; + return icons[category] || '📊'; + }; + + const getCategoryColor = (category) => { + const colors = { + 'Food': 'bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300', + 'Transport': 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300', + 'Groceries': 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300', + 'Entertainment': 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300', + 'Bills': 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300', + 'Shopping': 'bg-pink-100 text-pink-800 dark:bg-pink-900/30 dark:text-pink-300', + 'Rent': 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900/30 dark:text-indigo-300', + 'Utilities': 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-300', + 'EMI': 'bg-gray-100 text-gray-800 dark:bg-gray-900/30 dark:text-gray-300', + 'Income': 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300', + 'Others': 'bg-slate-100 text-slate-800 dark:bg-slate-900/30 dark:text-slate-300' + }; + return colors[category] || 'bg-gray-100 text-gray-800 dark:bg-gray-900/30 dark:text-gray-300'; + }; + + const filteredTransactions = transactions + .filter(transaction => { + const matchesSearch = transaction.note.toLowerCase().includes(searchTerm.toLowerCase()) || + transaction.category.toLowerCase().includes(searchTerm.toLowerCase()); + const matchesType = filterType === 'All' || transaction.type === filterType; + const matchesCategory = filterCategory === 'All' || transaction.category === filterCategory; + return matchesSearch && matchesType && matchesCategory; + }) + .sort((a, b) => { + switch (sortBy) { + case 'date': + return new Date(b.date.split('/').reverse().join('-')) - new Date(a.date.split('/').reverse().join('-')); + case 'amount': + return b.amount - a.amount; + case 'category': + return a.category.localeCompare(b.category); + default: + return 0; + } + }); + + const categories = [...new Set(transactions.map(t => t.category))].filter(Boolean); + const recentTransactions = filteredTransactions.slice(0, 5); + const totalBalance = income - expense; + + const cardVariants = { + initial: { opacity: 0, y: 20 }, + animate: { opacity: 1, y: 0 }, + hover: { y: -5, transition: { type: "spring", stiffness: 300 } } + }; + return ( -
- Track Expenses Page Coming Soon ..... -
- - - ) +
+ {/* Header */} +
+
+
+
+ + + Back to Home + +
+
+ +

Track Expenses

+
+
+ + +
+
+
+ +
+ {/* Summary Cards */} +
+ +
+
+

Total Balance

+

= 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}`}> + {formatAmount(totalBalance)} +

+
+
= 0 ? 'bg-green-100 dark:bg-green-900/30' : 'bg-red-100 dark:bg-red-900/30'}`}> + = 0 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}`} /> +
+
+
+ + +
+
+

Total Income

+

+ {formatAmount(income)} +

+
+
+ +
+
+
+ + +
+
+

Total Expenses

+

+ {formatAmount(expense)} +

+
+
+ +
+
+
+
+ + {/* Filters and Search */} +
+
+
+ + setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-white" + /> +
+ + + + + + +
+
+ + {/* Recent Transactions */} +
+
+

+ + Recent Transactions +

+ + View All + +
+ + {recentTransactions.length === 0 ? ( +
+
+ +
+

No transactions yet

+

Add your first transaction to get started

+
+ ) : ( +
+ {recentTransactions.map((transaction) => ( + +
+
{getCategoryIcon(transaction.category)}
+
+

{transaction.note}

+
+ + {transaction.category} + + + + {transaction.date} + +
+
+
+
+

+ {transaction.type === 'Income' ? '+' : '-'}{formatAmount(transaction.amount)} +

+

{transaction.type}

+
+
+ ))} +
+ )} +
+ + {/* Quick Actions */} +
+ +
+
+ +
+
+

Smart Analytics

+

Get insights into your spending patterns

+ + View Analytics → + +
+
+
+ + +
+
+ +
+
+

Budget Goals

+

Set and track your financial goals

+ + Manage Goals → + +
+
+
+
+
+ + {/* Add Transaction Modal */} + +
+ ); }; export default TrackExpenses; \ No newline at end of file