Bank statement converter downloader

import React, { useState } from 'react'; import { Upload, Download, FileText, TrendingUp, DollarSign, Calendar, Tag, Filter, X } from 'lucide-react'; const BankStatementConverter = () => { const [statements, setStatements] = useState([]); const [processing, setProcessing] = useState(false); const [view, setView] = useState('upload'); const [filterCategory, setFilterCategory] = useState('all'); const [dateRange, setDateRange] = useState({ start: '', end: '' }); const [error, setError] = useState(''); const categories = { 'Food & Dining': ['restaurant', 'cafe', 'food', 'grocery', 'uber eats', 'doordash', 'grubhub', 'starbucks', 'mcdonald', 'pizza'], 'Shopping': ['amazon', 'walmart', 'target', 'store', 'shop', 'retail', 'ebay', 'etsy'], 'Transportation': ['uber', 'lyft', 'gas', 'fuel', 'parking', 'transit', 'shell', 'chevron', 'exxon'], 'Bills & Utilities': ['electric', 'water', 'internet', 'phone', 'utilities', 'insurance', 'verizon', 'att'], 'Entertainment': ['netflix', 'spotify', 'movie', 'theater', 'game', 'steam', 'hulu', 'disney'], 'Healthcare': ['pharmacy', 'doctor', 'medical', 'health', 'cvs', 'walgreens', 'hospital'], 'Transfer': ['transfer', 'payment', 'zelle', 'venmo', 'paypal', 'cashapp'], 'Income': ['deposit', 'salary', 'payroll', 'income', 'refund', 'direct dep'], 'Other': [] }; const categorizeTransaction = (description) => { const desc = description.toLowerCase(); for (const [category, keywords] of Object.entries(categories)) { if (keywords.some(keyword => desc.includes(keyword))) { return category; } } return 'Other'; }; const parseCSVText = (text) => { const lines = text.split('\n').filter(line => line.trim()); if (lines.length === 0) return []; const headers = lines[0].split(',').map(h => h.trim().replace(/"/g, '')); const transactions = []; for (let i = 1; i < lines.length; i++) { const values = lines[i].split(',').map(v => v.trim().replace(/"/g, '')); const row = {}; headers.forEach((header, index) => { row[header] = values[index] || ''; }); const date = row.Date || row.date || row.DATE || row['Transaction Date'] || row['Posted Date'] || ''; const description = row.Description || row.description || row.DESCRIPTION || row.Memo || row.memo || row.Merchant || ''; const amountStr = (row.Amount || row.amount || row.AMOUNT || row.Debit || row.Credit || '0').replace(/[$,]/g, ''); const amount = parseFloat(amountStr) || 0; if (date && description) { transactions.push({ id: `txn_${Date.now()}_${i}`, date: date, description: description, amount: amount, balance: row.Balance || row.balance || row.BALANCE || '', type: amount >= 0 ? 'credit' : 'debit', category: categorizeTransaction(description) }); } } return transactions; }; const handleFileUpload = async (e) => { const files = Array.from(e.target.files); if (files.length === 0) return; setProcessing(true); setError(''); try { const allTransactions = []; for (const file of files) { let transactions = []; if (file.name.endsWith('.csv') || file.type === 'text/csv') { const text = await file.text(); transactions = parseCSVText(text); } else { setError(`File format not supported: ${file.name}. Please upload CSV files.`); continue; } allTransactions.push(...transactions); } if (allTransactions.length === 0) { setError('No valid transactions found. Please check your file format.'); setProcessing(false); return; } setStatements(allTransactions); setView('analysis'); } catch (error) { console.error('Error processing files:', error); setError('Error processing files. Please check the format and try again.'); } finally { setProcessing(false); } }; const downloadCSV = () => { const headers = ['Date', 'Description', 'Category', 'Amount', 'Type', 'Balance']; const rows = statements.map(s => [ s.date, `"${s.description}"`, s.category, s.amount, s.type, s.balance ]); const csv = [headers.join(','), ...rows.map(r => r.join(','))].join('\n'); const blob = new Blob([csv], { type: 'text/csv' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `bank_statement_categorized_${Date.now()}.csv`; a.click(); URL.revokeObjectURL(url); }; const getFilteredStatements = () => { let filtered = statements; if (filterCategory !== 'all') { filtered = filtered.filter(s => s.category === filterCategory); } if (dateRange.start) { filtered = filtered.filter(s => { try { return new Date(s.date) >= new Date(dateRange.start); } catch { return true; } }); } if (dateRange.end) { filtered = filtered.filter(s => { try { return new Date(s.date) <= new Date(dateRange.end); } catch { return true; } }); } return filtered; }; const calculateStats = () => { const filtered = getFilteredStatements(); const totalIncome = filtered.filter(s => s.type === 'credit').reduce((sum, s) => sum + s.amount, 0); const totalExpenses = filtered.filter(s => s.type === 'debit').reduce((sum, s) => sum + Math.abs(s.amount), 0); const categoryTotals = {}; filtered.forEach(s => { if (s.type === 'debit') { categoryTotals[s.category] = (categoryTotals[s.category] || 0) + Math.abs(s.amount); } }); return { totalIncome, totalExpenses, categoryTotals, netChange: totalIncome - totalExpenses }; }; const stats = statements.length > 0 ? calculateStats() : null; const filteredStatements = getFilteredStatements(); return (
{/* Header */}

Bank Statement Converter

Upload CSV files to analyze and categorize your transactions

{/* Main Content */} {view === 'upload' && (

Upload Your Bank Statement

Supports CSV format

{error && (
{error}
)}

Features:

  • Automatic transaction categorization into 9 categories
  • Spending analytics and income tracking
  • Export categorized data to CSV
  • Filter by category and date range

CSV Format Tips:

Your CSV should have columns like: Date, Description, Amount (or columns named date, description, amount, etc.)

)} {view === 'analysis' && statements.length > 0 && (
{/* Stats Cards */}
Total Income
${stats.totalIncome.toFixed(2)}
{statements.filter(s => s.type === 'credit').length} transactions
Total Expenses
${stats.totalExpenses.toFixed(2)}
{statements.filter(s => s.type === 'debit').length} transactions
Net Change
${stats.netChange.toFixed(2)}
{statements.length} total transactions
{/* Filters */}
setDateRange({...dateRange, start: e.target.value})} className="w-full border rounded-lg px-4 py-2" />
setDateRange({...dateRange, end: e.target.value})} className="w-full border rounded-lg px-4 py-2" />
{(filterCategory !== 'all' || dateRange.start || dateRange.end) && ( )}
{/* Category Breakdown */} {Object.keys(stats.categoryTotals).length > 0 && (

Spending by Category

{Object.entries(stats.categoryTotals) .sort(([,a], [,b]) => b - a) .map(([category, amount]) => (
{category}
${amount.toFixed(2)}
{((amount / stats.totalExpenses) * 100).toFixed(1)}%
))}
)} {/* Export Buttons */}
{/* Transactions Table */}
{filteredStatements.map((txn, idx) => ( ))}
Date Description Category Amount
{txn.date} {txn.description} {txn.category} {txn.type === 'credit' ? '+' : '-'}${Math.abs(txn.amount).toFixed(2)}
{filteredStatements.length === 0 && (
No transactions match your filters
)}
)}
); }; export default BankStatementConverter;

Comments

Popular posts from this blog

Free YouTube Thumbnail Downloader HD – Download Thumbnails Online