| 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; |
|
|