Velar/Frontend/monarch/lib/homepage.dart

629 lines
19 KiB
Dart

// ignore_for_file: deprecated_member_use, unused_local_variable, use_super_parameters
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:monarch/add.dart';
import 'package:monarch/navbar.dart';
//import 'package:monarch/static.dart';
class FinTrackHomePage extends StatefulWidget {
const FinTrackHomePage({Key? key}) : super(key: key);
@override
State<FinTrackHomePage> createState() => _FinTrackHomePageState();
}
class _FinTrackHomePageState extends State<FinTrackHomePage>
with TickerProviderStateMixin {
// Modern color palette
final Color backgroundColor = const Color(0xFFF8F9FA); // Light cream/white
final Color primaryColor = const Color(0xFF2D3436); // Deep charcoal
final Color accentColor = const Color(0xFF00B894); // Emerald green
final Color cardColor = const Color(0xFFFFFFFF); // Pure white
final Color textSecondary = const Color(0xFF636E72); // Muted gray
final Color surfaceColor = const Color(0xFFF1F2F6); // Light surface
late AnimationController _fadeController;
late AnimationController _slideController;
late Animation<double> _fadeAnimation;
late Animation<Offset> _slideAnimation;
// Sample data for dashboard
final double totalBalance = 5847.32;
final double monthlyIncome = 8500.00;
final double monthlyExpenses = 2652.68;
final List<Map<String, dynamic>> recentTransactions = [
{
'title': 'Grocery Shopping',
'category': 'Food & Dining',
'amount': -128.50,
'date': 'Today',
'icon': Icons.shopping_cart,
'color': Colors.orange,
},
{
'title': 'Salary Credit',
'category': 'Income',
'amount': 8500.00,
'date': 'Yesterday',
'icon': Icons.account_balance_wallet,
'color': Colors.green,
},
{
'title': 'Netflix Subscription',
'category': 'Entertainment',
'amount': -15.99,
'date': '2 days ago',
'icon': Icons.play_circle,
'color': Colors.red,
},
{
'title': 'Coffee Shop',
'category': 'Food & Dining',
'amount': -4.75,
'date': '3 days ago',
'icon': Icons.local_cafe,
'color': Colors.brown,
},
];
final List<Map<String, dynamic>> categories = [
{
'name': 'Food & Dining',
'amount': 450.32,
'percentage': 28,
'color': Colors.orange,
},
{
'name': 'Transportation',
'amount': 320.15,
'percentage': 20,
'color': Colors.blue,
},
{
'name': 'Entertainment',
'amount': 180.50,
'percentage': 11,
'color': Colors.purple,
},
{
'name': 'Shopping',
'amount': 275.80,
'percentage': 17,
'color': Colors.pink,
},
];
@override
void initState() {
super.initState();
_fadeController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
_slideController = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_fadeAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeOut));
_slideAnimation = Tween<Offset>(
begin: const Offset(0, 0.3),
end: Offset.zero,
).animate(
CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic),
);
// Start animations
_fadeController.forward();
_slideController.forward();
}
@override
void dispose() {
_fadeController.dispose();
_slideController.dispose();
super.dispose();
}
Widget _buildBalanceCard() {
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [accentColor, accentColor.withOpacity(0.8)],
),
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: accentColor.withOpacity(0.3),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total Balance',
style: GoogleFonts.inter(
color: Colors.white.withOpacity(0.9),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
Icon(
Icons.visibility_outlined,
color: Colors.white.withOpacity(0.9),
size: 20,
),
],
),
const SizedBox(height: 8),
Text(
'\$${totalBalance.toStringAsFixed(2)}',
style: GoogleFonts.inter(
color: Colors.white,
fontSize: 36,
fontWeight: FontWeight.w700,
letterSpacing: -1,
),
),
const SizedBox(height: 20),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Income',
style: GoogleFonts.inter(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 4),
Text(
'\$${monthlyIncome.toStringAsFixed(0)}',
style: GoogleFonts.inter(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
),
Container(
width: 1,
height: 40,
color: Colors.white.withOpacity(0.3),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Expenses',
style: GoogleFonts.inter(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 4),
Text(
'\$${monthlyExpenses.toStringAsFixed(0)}',
style: GoogleFonts.inter(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
],
),
],
),
);
}
Widget _buildQuickActions() {
return Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
HapticFeedback.heavyImpact();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const AddExpenseScreen(),
),
);
},
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: primaryColor.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: accentColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(Icons.add, color: accentColor, size: 24),
),
const SizedBox(height: 12),
Text(
'Add Expense',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: GestureDetector(
onTap: () {
HapticFeedback.lightImpact();
// Navigate to Statistics
},
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: primaryColor.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(
Icons.bar_chart,
color: Colors.blue,
size: 24,
),
),
const SizedBox(height: 12),
Text(
'Statistics',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
),
],
);
}
Widget _buildRecentTransactions() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: primaryColor.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Recent Transactions',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
Text(
'View All',
style: GoogleFonts.inter(
color: accentColor,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(height: 16),
...recentTransactions.map(
(transaction) => Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: transaction['color'].withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
transaction['icon'],
color: transaction['color'],
size: 20,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
transaction['title'],
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
'${transaction['category']} • ${transaction['date']}',
style: GoogleFonts.inter(
color: textSecondary,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
],
),
),
Text(
'${transaction['amount'] > 0 ? '+' : ''}\$${transaction['amount'].abs().toStringAsFixed(2)}',
style: GoogleFonts.inter(
color:
transaction['amount'] > 0 ? accentColor : Colors.red,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
],
),
);
}
Widget _buildSpendingCategories() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: cardColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: primaryColor.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Spending by Category',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 20),
...categories.map(
(category) => Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 12,
height: 12,
decoration: BoxDecoration(
color: category['color'],
borderRadius: BorderRadius.circular(6),
),
),
const SizedBox(width: 12),
Text(
category['name'],
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
],
),
Text(
'\$${category['amount'].toStringAsFixed(2)}',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(height: 8),
LinearProgressIndicator(
value: category['percentage'] / 100,
backgroundColor: surfaceColor,
valueColor: AlwaysStoppedAnimation<Color>(
category['color'],
),
borderRadius: BorderRadius.circular(4),
),
],
),
),
),
],
),
);
}
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
body: SafeArea(
child: FadeTransition(
opacity: _fadeAnimation,
child: SlideTransition(
position: _slideAnimation,
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Good Morning! 👋',
style: GoogleFonts.inter(
color: primaryColor,
fontSize: 24,
fontWeight: FontWeight.w700,
),
),
],
),
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: accentColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
),
child: Icon(
Icons.notifications_outlined,
color: accentColor,
size: 24,
),
),
],
),
const SizedBox(height: 32),
// Balance Card
_buildBalanceCard(),
const SizedBox(height: 24),
// Quick Actions
_buildQuickActions(),
const SizedBox(height: 32),
// Recent Transactions
_buildRecentTransactions(),
const SizedBox(height: 24),
// Spending Categories
_buildSpendingCategories(),
const SizedBox(height: 20),
],
),
),
),
),
),
floatingActionButton: CustomNavBar(
currentIndex: _selectedIndex,
onTap: (index) {
setState(() => _selectedIndex = index);
},
backgroundColor: backgroundColor,
accentColor: accentColor,
primaryColor: primaryColor,
cardColor: cardColor,
floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,
),
);
}
}