import React, { useState } from 'react';
import { Plus, TrendingUp, TrendingDown, User, Home, BarChart3, X, Check, Zap, Trash2, Settings, Sparkles, Coffee, Car, ShoppingBag, Film, Heart, DollarSign, Wallet } from 'lucide-react';
const Flowly = () => {
const [activeTab, setActiveTab] = useState('home');
const [showAddModal, setShowAddModal] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [showOnboarding, setShowOnboarding] = useState(true);
const [onboardingStep, setOnboardingStep] = useState(0);
const [selectedTransaction, setSelectedTransaction] = useState(null);
const [theme, setTheme] = useState('cyan');
const [longPressTimer, setLongPressTimer] = useState(null);
const [touchStart, setTouchStart] = useState(null);
const [touchEnd, setTouchEnd] = useState(null);
const [swipedTxn, setSwipedTxn] = useState(null);
const [numberAnimate, setNumberAnimate] = useState(false);
const [transactions, setTransactions] = useState([
{ id: 1, type: 'expense', amount: 45, category: 'Food', desc: 'Lunch', date: new Date(), currency: 'USD' },
{ id: 2, type: 'income', amount: 3000, category: 'Salary', desc: 'Monthly', date: new Date(Date.now() - 86400000), currency: 'USD' },
{ id: 3, type: 'expense', amount: 12, category: 'Transport', desc: 'Uber', date: new Date(), currency: 'USD' },
]);
const [currency, setCurrency] = useState('USD');
const [monthlyIncome, setMonthlyIncome] = useState(3000);
const [dailyBudget, setDailyBudget] = useState(100);
const [newTransaction, setNewTransaction] = useState({
type: 'expense',
amount: '',
category: 'Food',
desc: ''
});
const [tempMonthlyIncome, setTempMonthlyIncome] = useState('');
const [tempDailyBudget, setTempDailyBudget] = useState('');
const themes = {
cyan: { primary: '#06b6d4', glow: 'rgba(6, 182, 212, 0.5)', gradient: 'from-cyan-500 to-blue-500' },
green: { primary: '#84cc16', glow: 'rgba(132, 204, 22, 0.5)', gradient: 'from-lime-500 to-green-500' },
purple: { primary: '#a855f7', glow: 'rgba(168, 85, 247, 0.5)', gradient: 'from-purple-500 to-pink-500' },
orange: { primary: '#f97316', glow: 'rgba(249, 115, 22, 0.5)', gradient: 'from-orange-500 to-red-500' }
};
const currencies = ['USD', 'EUR', 'GBP', 'INR', 'JPY', 'AUD', 'CAD'];
const currencySymbols = { USD: '$', EUR: '€', GBP: '£', INR: '₹', JPY: '¥', AUD: 'A$', CAD: 'C$' };
const categoryIcons = {
Food: Coffee,
Transport: Car,
Bills: Wallet,
Shopping: ShoppingBag,
Entertainment: Film,
Health: Heart,
Salary: DollarSign,
Other: Sparkles
};
const categories = Object.keys(categoryIcons);
const getTodayTransactions = () => {
const today = new Date().toDateString();
return transactions.filter(t => new Date(t.date).toDateString() === today);
};
const getTodayBalance = () => {
const todayTxns = getTodayTransactions();
const income = todayTxns.filter(t => t.type === 'income').reduce((sum, t) => sum + t.amount, 0);
const expense = todayTxns.filter(t => t.type === 'expense').reduce((sum, t) => sum + t.amount, 0);
return { income, expense, balance: income - expense };
};
const getWeeklyData = () => {
const days = [];
const today = new Date();
for (let i = 6; i >= 0; i--) {
const date = new Date(today);
date.setDate(date.getDate() - i);
const dayTxns = transactions.filter(t =>
new Date(t.date).toDateString() === date.toDateString()
);
const expense = dayTxns.filter(t => t.type === 'expense').reduce((sum, t) => sum + t.amount, 0);
days.push({
day: date.toLocaleDateString('en-US', { weekday: 'short' }),
amount: expense
});
}
return days;
};
const getWeeklyStats = () => {
const weekAgo = new Date(Date.now() - 7 * 86400000);
const weekTxns = transactions.filter(t => new Date(t.date) >= weekAgo);
const categorySpending = {};
weekTxns.filter(t => t.type === 'expense').forEach(t => {
categorySpending[t.category] = (categorySpending[t.category] || 0) + t.amount;
});
return categorySpending;
};
const addTransaction = () => {
if (!newTransaction.amount) return;
const txn = {
id: Date.now(),
...newTransaction,
amount: parseFloat(newTransaction.amount),
date: new Date(),
currency
};
setTransactions([txn, ...transactions]);
setNewTransaction({ type: 'expense', amount: '', category: 'Food', desc: '' });
setShowAddModal(false);
triggerNumberAnimation();
};
const deleteTransaction = (id) => {
setTransactions(transactions.filter(t => t.id !== id));
setShowDeleteConfirm(false);
setSelectedTransaction(null);
triggerNumberAnimation();
};
const editTransaction = () => {
setTransactions(transactions.map(t =>
t.id === selectedTransaction.id ? selectedTransaction : t
));
setShowEditModal(false);
setSelectedTransaction(null);
triggerNumberAnimation();
};
const triggerNumberAnimation = () => {
setNumberAnimate(true);
setTimeout(() => setNumberAnimate(false), 500);
};
const handleLongPressStart = (txn) => {
const timer = setTimeout(() => {
setSelectedTransaction(txn);
setShowDeleteConfirm(true);
}, 500);
setLongPressTimer(timer);
};
const handleLongPressEnd = () => {
if (longPressTimer) {
clearTimeout(longPressTimer);
setLongPressTimer(null);
}
};
const handleTouchStart = (e, txn) => {
setTouchStart(e.targetTouches[0].clientX);
setSwipedTxn(txn.id);
};
const handleTouchMove = (e) => {
setTouchEnd(e.targetTouches[0].clientX);
};
const handleTouchEnd = (txn) => {
if (!touchStart || !touchEnd) return;
const distance = touchStart - touchEnd;
if (distance > 75) {
setSelectedTransaction(txn);
setShowDeleteConfirm(true);
}
setTouchStart(null);
setTouchEnd(null);
setSwipedTxn(null);
};
const handleTransactionClick = (txn) => {
setSelectedTransaction(txn);
setShowEditModal(true);
};
const completeOnboarding = () => {
if (tempMonthlyIncome) setMonthlyIncome(parseFloat(tempMonthlyIncome));
if (tempDailyBudget) setDailyBudget(parseFloat(tempDailyBudget));
setShowOnboarding(false);
};
const today = getTodayBalance();
const dailyProgress = (today.expense / dailyBudget) * 100;
const isOverBudget = today.expense > dailyBudget;
const weeklyData = getWeeklyData();
const weeklyStats = getWeeklyStats();
const maxWeekly = Math.max(...weeklyData.map(d => d.amount), 1);
const CircularProgress = ({ progress, size = 180 }) => {
const strokeWidth = 8;
const radius = (size - strokeWidth * 2) / 2;
const circumference = radius * 2 * Math.PI;
const offset = circumference - (Math.min(progress, 100) / 100) * circumference;
return (
);
};
if (showOnboarding) {
return (
{onboardingStep === 0 && (
Flowly
Your futuristic budgeting companion
setOnboardingStep(1)}
className="w-full py-5 rounded-2xl font-bold text-lg relative overflow-hidden group"
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(20px)',
border: `2px solid ${themes[theme].primary}`,
boxShadow: `0 0 30px ${themes[theme].glow}`,
color: themes[theme].primary
}}
>
Get Started
)}
{onboardingStep === 1 && (
Monthly Income
setTempMonthlyIncome(e.target.value)}
placeholder="3000"
className="w-full px-6 py-5 rounded-2xl text-3xl font-bold text-center focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.4)',
border: `2px solid ${themes[theme].primary}60`,
color: themes[theme].primary
}}
/>
setOnboardingStep(2)}
className="w-full py-4 rounded-2xl font-bold"
style={{
background: `linear-gradient(135deg, ${themes[theme].primary}, ${themes[theme].primary}dd)`,
boxShadow: `0 0 30px ${themes[theme].glow}`
}}
>
Continue
)}
{onboardingStep === 2 && (
Daily Budget
setTempDailyBudget(e.target.value)}
placeholder="100"
className="w-full px-6 py-5 rounded-2xl text-3xl font-bold text-center focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.4)',
border: `2px solid ${themes[theme].primary}60`,
color: themes[theme].primary
}}
/>
Start Tracking
)}
);
}
return (
setCurrency(e.target.value)}
className="px-3 py-1.5 rounded-xl text-sm font-semibold focus:outline-none"
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(10px)',
border: `1px solid ${themes[theme].primary}40`,
color: themes[theme].primary
}}
>
{currencies.map(c => {c} )}
{activeTab === 'home' && (
= 1000 ? 'text-3xl' : Math.abs(today.balance) >= 100 ? 'text-4xl' : 'text-5xl'}`}
style={{
color: today.balance >= 0 ? '#10b981' : '#ef4444',
textShadow: `0 0 30px ${today.balance >= 0 ? 'rgba(16, 185, 129, 0.5)' : 'rgba(239, 68, 68, 0.5)'}`,
wordBreak: 'break-all',
lineHeight: '1.1'
}}>
{today.balance >= 0 ? '+' : ''}{currencySymbols[currency]}{Math.abs(today.balance).toFixed(0)}
Today's Balance
{isOverBudget ? '🔴 Over' : '🟢 Under'}
{
setNewTransaction({...newTransaction, type: 'income'});
setShowAddModal(true);
}}
className="p-6 rounded-2xl text-center transition-all active:scale-95"
style={{
background: 'rgba(16, 185, 129, 0.1)',
backdropFilter: 'blur(20px)',
border: '2px solid rgba(16, 185, 129, 0.3)',
boxShadow: '0 0 30px rgba(16, 185, 129, 0.2)'
}}>
Add Income
{
setNewTransaction({...newTransaction, type: 'expense'});
setShowAddModal(true);
}}
className="p-6 rounded-2xl text-center transition-all active:scale-95"
style={{
background: 'rgba(239, 68, 68, 0.1)',
backdropFilter: 'blur(20px)',
border: '2px solid rgba(239, 68, 68, 0.3)',
boxShadow: '0 0 30px rgba(239, 68, 68, 0.2)'
}}>
Add Expense
{currencySymbols[currency]}{today.income.toFixed(0)}
Income Today
{currencySymbols[currency]}{today.expense.toFixed(0)}
Spent Today
Today's Activity
{getTodayTransactions().length === 0 ? (
) : (
getTodayTransactions().map(txn => {
const Icon = categoryIcons[txn.category] || Sparkles;
return (
handleTransactionClick(txn)}
onTouchStart={(e) => {
handleLongPressStart(txn);
handleTouchStart(e, txn);
}}
onTouchMove={handleTouchMove}
onTouchEnd={() => {
handleLongPressEnd();
handleTouchEnd(txn);
}}
className={`p-4 rounded-2xl flex justify-between items-center transition-all active:scale-95 cursor-pointer ${
swipedTxn === txn.id ? 'scale-95 opacity-50' : ''
}`}
style={{
background: 'rgba(255, 255, 255, 0.03)',
backdropFilter: 'blur(20px)',
border: `1px solid ${themes[theme].primary}30`
}}>
{txn.category}
{txn.desc || 'No note'}
{txn.type === 'income' ? '+' : '-'}{currencySymbols[currency]}{txn.amount}
);
})
)}
)}
{activeTab === 'insights' && (
Insights
Last 7 Days Spending
{weeklyData.map((day, idx) => {
const height = maxWeekly > 0 ? (day.amount / maxWeekly) * 100 : 0;
return (
0 ? `linear-gradient(180deg, ${themes[theme].primary}, ${themes[theme].primary}80)` : 'rgba(255,255,255,0.1)',
boxShadow: day.amount > 0 ? `0 0 20px ${themes[theme].glow}` : 'none',
minHeight: '8px'
}}>
{day.amount > 0 && (
{currencySymbols[currency]}{day.amount.toFixed(0)}
)}
{day.day}
);
})}
Top Categories
{Object.keys(weeklyStats).length === 0 ? (
No spending data yet
Start adding expenses
) : (
{Object.entries(weeklyStats).sort((a, b) => b[1] - a[1]).slice(0, 6).map(([cat, amt]) => {
const Icon = categoryIcons[cat] || Sparkles;
return (
{cat}
{currencySymbols[currency]}{amt.toFixed(0)}
);
})}
)}
Smart Insight
{Object.keys(weeklyStats).length > 0
? `You spent most on ${Object.entries(weeklyStats).sort((a, b) => b[1] - a[1])[0][0]} this week (${currencySymbols[currency]}${Object.entries(weeklyStats).sort((a, b) => b[1] - a[1])[0][1].toFixed(0)})`
: 'Start tracking expenses to see personalized insights'}
)}
{activeTab === 'profile' && (
Settings
Customize your experience
Choose Theme
{Object.entries(themes).map(([key, value]) => (
setTheme(key)}
className={`w-full aspect-square rounded-2xl transition-all ${
theme === key ? 'scale-110' : 'scale-100'
}`}
style={{
background: `linear-gradient(135deg, ${value.primary}, ${value.primary}dd)`,
boxShadow: theme === key ? `0 0 30px ${value.glow}` : 'none',
border: theme === key ? `2px solid ${value.primary}` : 'none'
}}
/>
))}
Monthly Income
setMonthlyIncome(parseFloat(e.target.value) || 0)}
className="w-full px-4 py-4 rounded-xl text-2xl font-bold focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.4)',
border: `2px solid ${themes[theme].primary}40`,
color: themes[theme].primary
}}
/>
Daily Budget Goal
setDailyBudget(parseFloat(e.target.value) || 0)}
className="w-full px-4 py-4 rounded-xl text-2xl font-bold focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.4)',
border: `2px solid ${themes[theme].primary}40`,
color: themes[theme].primary
}}
/>
• Tap transactions to edit instantly
• Swipe left to delete
• Long press for quick actions
• Change theme anytime above
)}
{showAddModal && (
Add {newTransaction.type === 'income' ? 'Income' : 'Expense'}
setShowAddModal(false)}
className="w-12 h-12 rounded-xl flex items-center justify-center transition-all active:scale-95"
style={{
background: 'rgba(255, 255, 255, 0.05)',
border: `1px solid ${themes[theme].primary}40`
}}>
setNewTransaction({...newTransaction, amount: e.target.value})}
placeholder="0.00"
autoFocus
className="w-full px-6 py-5 rounded-2xl text-4xl font-bold text-center focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.6)',
border: `2px solid ${themes[theme].primary}`,
color: themes[theme].primary,
boxShadow: `0 0 30px ${themes[theme].glow}`
}}
/>
{categories.map(cat => {
const Icon = categoryIcons[cat];
return (
setNewTransaction({...newTransaction, category: cat})}
className={`p-3 rounded-xl flex flex-col items-center gap-2 transition-all active:scale-95 ${
newTransaction.category === cat ? 'scale-110' : 'scale-100'
}`}
style={{
background: newTransaction.category === cat
? `linear-gradient(135deg, ${themes[theme].primary}40, ${themes[theme].primary}20)`
: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(10px)',
border: `1px solid ${newTransaction.category === cat ? themes[theme].primary : 'rgba(255,255,255,0.1)'}`,
boxShadow: newTransaction.category === cat ? `0 0 20px ${themes[theme].glow}` : 'none'
}}>
{cat}
);
})}
setNewTransaction({...newTransaction, desc: e.target.value})}
placeholder="Add a note (optional)"
className="w-full px-4 py-4 rounded-xl focus:outline-none"
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(10px)',
border: `1px solid ${themes[theme].primary}40`,
color: 'white'
}}
/>
Add Transaction
)}
{showEditModal && selectedTransaction && (
Edit Transaction
setShowEditModal(false)}
className="w-12 h-12 rounded-xl flex items-center justify-center transition-all active:scale-95"
style={{
background: 'rgba(255, 255, 255, 0.05)',
border: `1px solid ${themes[theme].primary}40`
}}>
setSelectedTransaction({...selectedTransaction, amount: parseFloat(e.target.value) || 0})}
className="w-full px-6 py-5 rounded-2xl text-4xl font-bold text-center focus:outline-none"
style={{
background: 'rgba(0, 0, 0, 0.6)',
border: `2px solid ${themes[theme].primary}`,
color: themes[theme].primary,
boxShadow: `0 0 30px ${themes[theme].glow}`
}}
/>
setSelectedTransaction({...selectedTransaction, category: e.target.value})}
className="w-full px-4 py-4 rounded-xl text-lg focus:outline-none"
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(10px)',
border: `1px solid ${themes[theme].primary}40`,
color: 'white'
}}>
{categories.map(cat => {cat} )}
setSelectedTransaction({...selectedTransaction, desc: e.target.value})}
placeholder="Description"
className="w-full px-4 py-4 rounded-xl focus:outline-none"
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(10px)',
border: `1px solid ${themes[theme].primary}40`,
color: 'white'
}}
/>
Save Changes
)}
{showDeleteConfirm && selectedTransaction && (
Delete Transaction?
{selectedTransaction.category} - {currencySymbols[currency]}{selectedTransaction.amount}
{
setShowDeleteConfirm(false);
setSelectedTransaction(null);
}}
className="flex-1 py-4 rounded-xl font-semibold active:scale-95 transition-all"
style={{
background: 'rgba(255, 255, 255, 0.05)',
border: `1px solid ${themes[theme].primary}40`
}}>
Cancel
deleteTransaction(selectedTransaction.id)}
className="flex-1 py-4 rounded-xl font-bold flex items-center justify-center gap-2 active:scale-95 transition-all"
style={{
background: 'linear-gradient(135deg, #ef4444, #dc2626)',
boxShadow: '0 0 30px rgba(239, 68, 68, 0.5)'
}}>
Delete
)}
setShowAddModal(true)}
className="fixed bottom-28 right-6 w-16 h-16 rounded-2xl flex items-center justify-center active:scale-95 transition-all z-30"
style={{
background: `linear-gradient(135deg, ${themes[theme].primary}, ${themes[theme].primary}dd)`,
boxShadow: `0 0 40px ${themes[theme].glow}, 0 10px 30px rgba(0,0,0,0.5)`
}}>
{[
{ id: 'home', icon: Home, label: 'Home' },
{ id: 'insights', icon: BarChart3, label: 'Insights' },
{ id: 'profile', icon: Settings, label: 'Settings' }
].map(tab => (
setActiveTab(tab.id)}
className={`flex flex-col items-center gap-1 px-8 py-3 rounded-2xl transition-all active:scale-95`}
style={{
color: activeTab === tab.id ? themes[theme].primary : '#6b7280',
background: activeTab === tab.id ? `${themes[theme].primary}20` : 'transparent',
boxShadow: activeTab === tab.id ? `0 0 20px ${themes[theme].glow}` : 'none'
}}>
{tab.label}
))}
);
};
export default Flowly;