FinMK / frontend /src /components /WelcomeBanner.jsx
Kumar
Refactor: Exclude PDF and CSV files from Git to fix HF push error
24e6f5b
import { memo, useState, useEffect } from 'react';
import { ShoppingCart, TrendingUp, Target, FileText } from 'lucide-react';
const WelcomeBanner = memo(({ user, summary, currencySymbol, onNavigate }) => {
const [currentTime, setCurrentTime] = useState(new Date());
useEffect(() => {
const timer = setInterval(() => setCurrentTime(new Date()), 60000);
return () => clearInterval(timer);
}, []);
const getGreeting = () => {
const hour = currentTime.getHours();
if (hour < 12) return 'Good Morning';
if (hour < 17) return 'Good Afternoon';
if (hour < 21) return 'Good Evening';
return 'Good Night';
};
const getMotivationalMessage = () => {
const savingsRate = summary?.total_income > 0
? ((summary.total_income - summary.total_expense) / summary.total_income * 100)
: 0;
if (savingsRate >= 20) return "You're doing great with your savings! 🎉";
if (savingsRate >= 0) return "Keep up the good work! 💪";
return "Let's work on improving your finances! 🚀";
};
const formatDate = () => {
return currentTime.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const quickActions = [
{ icon: <ShoppingCart size={18} />, label: 'Add Expense', action: () => onNavigate('/transactions'), color: '#ef4444' },
{ icon: <TrendingUp size={18} />, label: 'Add Income', action: () => onNavigate('/transactions'), color: '#10b981' },
{ icon: <Target size={18} />, label: 'Set Budget', action: () => onNavigate('/budget'), color: '#6366f1' },
{ icon: <FileText size={18} />, label: 'Web Report', action: () => onNavigate('/report'), color: '#f59e0b' }
];
return (
<div className="glass-panel animate-slide-down" style={{
padding: '2rem',
marginBottom: '2rem',
background: 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.05) 50%, rgba(236, 72, 153, 0.1) 100%)',
border: '1px solid rgba(255, 255, 255, 0.1)',
borderRadius: '1.5rem',
position: 'relative',
overflow: 'hidden',
boxShadow: '0 20px 60px -15px rgba(0, 0, 0, 0.3)'
}}>
{/* Animated Background Gradient */}
<div style={{
position: 'absolute',
top: '-50%',
left: '-50%',
width: '200%',
height: '200%',
background: 'radial-gradient(circle, rgba(99, 102, 241, 0.15) 0%, transparent 50%)',
animation: 'pulse 8s ease-in-out infinite',
pointerEvents: 'none'
}} />
<div style={{ position: 'relative', zIndex: 1 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '1.5rem', flexWrap: 'wrap', gap: '1rem' }}>
{/* Left Section - Greeting */}
<div style={{ flex: 1, minWidth: '300px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '0.5rem' }}>
<div style={{
width: '60px',
height: '60px',
borderRadius: '50%',
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '1.75rem',
fontWeight: 'bold',
color: 'white',
boxShadow: '0 10px 30px -5px rgba(99, 102, 241, 0.5)',
border: '2px solid rgba(255, 255, 255, 0.2)'
}}>
{user?.username?.charAt(0).toUpperCase() || 'U'}
</div>
<div>
<h1 style={{
margin: 0,
fontSize: '2rem',
fontWeight: '700',
background: 'linear-gradient(135deg, #ffffff 0%, #e0e7ff 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text'
}}>
{getGreeting()}, {user?.username ? user.username.toUpperCase() : 'User'}!
</h1>
<p style={{ margin: '0.25rem 0 0 0', color: 'rgba(255, 255, 255, 0.7)', fontSize: '0.9rem' }}>
{formatDate()}
</p>
</div>
</div>
<p style={{
margin: '1rem 0 0 0',
fontSize: '1rem',
color: 'rgba(255, 255, 255, 0.85)',
fontWeight: '500'
}}>
{getMotivationalMessage()}
</p>
</div>
{/* Right Section - Quick Stats */}
<div style={{ display: 'flex', gap: '1.5rem', flexWrap: 'wrap' }}>
<div style={{
padding: '1rem 1.5rem',
background: 'rgba(16, 185, 129, 0.15)',
borderRadius: '1rem',
border: '1px solid rgba(16, 185, 129, 0.3)',
backdropFilter: 'blur(10px)'
}}>
<div style={{ fontSize: '0.75rem', color: 'rgba(255, 255, 255, 0.7)', marginBottom: '0.25rem' }}>Total Balance</div>
<div style={{ fontSize: '1.5rem', fontWeight: '700', color: '#10b981' }}>
{currencySymbol}{((summary?.total_income || 0) - (summary?.total_expense || 0)).toLocaleString()}
</div>
</div>
<div style={{
padding: '1rem 1.5rem',
background: 'rgba(99, 102, 241, 0.15)',
borderRadius: '1rem',
border: '1px solid rgba(99, 102, 241, 0.3)',
backdropFilter: 'blur(10px)'
}}>
<div style={{ fontSize: '0.75rem', color: 'rgba(255, 255, 255, 0.7)', marginBottom: '0.25rem' }}>This Month</div>
<div style={{ fontSize: '1.5rem', fontWeight: '700', color: '#6366f1' }}>
{summary?.monthly_txn_count || 0} txns
</div>
</div>
</div>
</div>
{/* Quick Actions */}
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
{quickActions.map((action, idx) => (
<button
key={idx}
onClick={action.action}
className="hover-scale"
style={{
padding: '0.75rem 1.25rem',
background: 'rgba(255, 255, 255, 0.05)',
border: '1px solid rgba(255, 255, 255, 0.1)',
borderRadius: '0.75rem',
color: 'white',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
fontSize: '0.9rem',
fontWeight: '500',
transition: 'all 0.3s',
backdropFilter: 'blur(10px)'
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = `${action.color}20`;
e.currentTarget.style.borderColor = action.color;
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.05)';
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.1)';
}}
>
<span style={{ color: action.color }}>{action.icon}</span>
{action.label}
</button>
))}
</div>
</div>
</div>
);
});
export default WelcomeBanner;