From 3f8f73890a06efcdcc1942bc35086354ee824685 Mon Sep 17 00:00:00 2001 From: lokeshramchand-ctrl Date: Fri, 22 Aug 2025 19:42:09 +0530 Subject: [PATCH] OHO-18(Perfect Homepage) --- .../transaction_rules.cpython-313.pyc | Bin 8482 -> 8495 bytes Backend/index.js | 6 +- Frontend/analysis_options.yaml | 3 + Frontend/lib/main.dart | 104 +-- .../lib/main_pages/HomePage/homepage.dart | 826 +++++++++++++++--- .../{ => Budget}/budget_manager.dart | 0 .../{ => Budget}/update_budget.dart | 0 .../lib/main_pages/Statistics/statistics.dart | 4 +- Frontend/lib/other_pages/enviroment.dart | 2 +- 9 files changed, 722 insertions(+), 223 deletions(-) rename Frontend/lib/main_pages/Statistics/{ => Budget}/budget_manager.dart (100%) rename Frontend/lib/main_pages/Statistics/{ => Budget}/update_budget.dart (100%) diff --git a/AI/Rules/__pycache__/transaction_rules.cpython-313.pyc b/AI/Rules/__pycache__/transaction_rules.cpython-313.pyc index 103ddc532cf8fd2d8c1356a1371282b1c8aa1ca4..f2faf1dce4c1d419512ed883b3e4cc8c9c1f2eef 100644 GIT binary patch literal 8495 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 ZaUf0)3=G7X%b9_(m&ZSoqE~+Ce*l)&b4~yN literal 8482 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 Xh|>cD194_OGcfkb_-9k}$`AbyC(>-w diff --git a/Backend/index.js b/Backend/index.js index eca7bfd..b170d96 100644 --- a/Backend/index.js +++ b/Backend/index.js @@ -160,7 +160,7 @@ app.post('/api/transaction/add', async (req, res) => { const { description, amount, userId } = req.body; if (!userId) return res.status(400).json({ error: 'Missing userId' }); - const predictRes = await axios.post('http://10.231.41.181:5000/api/predict', { + const predictRes = await axios.post('http://192.168.1.9:5000/api/predict', { description, }); const category = predictRes.data.category || 'Other'; @@ -227,7 +227,7 @@ app.post('/api/transactions/voice', async (req, res) => { .trim(); const description = cleaned || 'misc'; // Step 3: Predict category using your Flask API - const predictRes = await axios.post('http://192.168.1.101:5000/api/predict', { + const predictRes = await axios.post('http://192.168.1.9:5000/api/predict', { description, }); const category = predictRes.data?.category || 'Other'; @@ -429,7 +429,7 @@ app.post('/api/sync-gmail', async (req, res) => { let category = 'Other'; try { - const predictRes = await axios.post('http://10.231.41.181:5000/api/predict', { + const predictRes = await axios.post('http://192.168.1.9:5000/api/predict', { description: parsed.vendor || "Unknown" }, { timeout: 5000 }); // Optional timeout diff --git a/Frontend/analysis_options.yaml b/Frontend/analysis_options.yaml index 0d29021..0f9a8d6 100644 --- a/Frontend/analysis_options.yaml +++ b/Frontend/analysis_options.yaml @@ -7,6 +7,9 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. +analyzer: + errors: + unused_field: ignore include: package:flutter_lints/flutter.yaml linter: diff --git a/Frontend/lib/main.dart b/Frontend/lib/main.dart index ffab003..d1142c4 100644 --- a/Frontend/lib/main.dart +++ b/Frontend/lib/main.dart @@ -8,7 +8,7 @@ import 'package:http/http.dart' as http; import 'package:monarch/login.dart'; import 'package:monarch/speech.dart'; import 'package:monarch/support/add.dart'; -import 'package:monarch/main_pages/Statistics/update_budget.dart'; +import 'package:monarch/main_pages/Statistics/Budget/update_budget.dart'; import 'package:monarch/main_pages/HomePage/homepage.dart'; import 'package:monarch/main_pages/Statistics/statistics.dart'; @@ -25,109 +25,9 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.blue), - home: const LoginScreen(), + home: const FinTrackHomePage(), // home: const SpeechInputPage(), ); } } - -class AddTransactionPage extends StatefulWidget { - const AddTransactionPage({super.key}); - - @override - _AddTransactionPageState createState() => _AddTransactionPageState(); -} - -class _AddTransactionPageState extends State { - final TextEditingController descriptionController = TextEditingController(); - final TextEditingController amountController = TextEditingController(); - final baseUrl = dotenv.env['BASE_URL']; - - Future addTransaction() async { - // Show loading indicator - showDialog( - context: context, - barrierDismissible: false, - builder: (_) => const Center(child: CircularProgressIndicator()), - ); - - try { - final response = await http.post( - Uri.parse('$baseUrl/api/transaction/add'), - headers: {'Content-Type': 'application/json'}, - body: json.encode({ - 'description': descriptionController.text, - 'amount': double.tryParse(amountController.text), - }), - ); - - Navigator.of(context).pop(); // Close loading dialog - - if (response.statusCode == 200) { - final responseData = json.decode(response.body); - final predictedCategory = responseData['data']['category']; - - // Clear the input fields - descriptionController.clear(); - amountController.clear(); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - '✅ Transaction added and categorized as: $predictedCategory', - ), - ), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('❌ Failed to add transaction: ${response.body}'), - ), - ); - } - } catch (e) { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Statistics()), - ); - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text('⚠️ Error: $e'))); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('Add Transaction')), - body: Padding( - padding: EdgeInsets.all(16), - child: Column( - children: [ - TextField( - controller: descriptionController, - decoration: InputDecoration(labelText: 'Description'), - ), - TextField( - controller: amountController, - keyboardType: TextInputType.number, - decoration: InputDecoration(labelText: 'Amount'), - ), - SizedBox(height: 20), - ElevatedButton(onPressed: addTransaction, child: Text('Submit')), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => const Statistics()), - ); - }, - child: const Text('NextPage'), - ), - ], - ), - ), - ); - } -} diff --git a/Frontend/lib/main_pages/HomePage/homepage.dart b/Frontend/lib/main_pages/HomePage/homepage.dart index ce78539..4cb06d5 100644 --- a/Frontend/lib/main_pages/HomePage/homepage.dart +++ b/Frontend/lib/main_pages/HomePage/homepage.dart @@ -1,11 +1,244 @@ -// ignore_for_file: deprecated_member_use, unused_local_variable, use_super_parameters, avoid_print +// // ignore_for_file: deprecated_member_use, unused_local_variable, use_super_parameters, avoid_print +// import 'package:flutter/material.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// import 'package:monarch/other_pages/colors.dart'; +// import 'package:monarch/support/fetch_service.dart'; +// import 'package:monarch/main_pages/HomePage/hero_card.dart'; +// import 'package:monarch/main_pages/HomePage/navbar.dart'; +// import 'package:monarch/main_pages/HomePage/quick_actions.dart'; +// import 'package:monarch/support/transcations_recent.dart'; + +// class FinTrackHomePage extends StatefulWidget { +// const FinTrackHomePage({Key? key}) : super(key: key); + +// @override +// State createState() => _FinTrackHomePageState(); +// } + +// class _FinTrackHomePageState extends State +// with TickerProviderStateMixin { + +// // Animation Controllers +// late AnimationController _fadeController; +// late AnimationController _slideController; +// late Animation _fadeAnimation; +// late Animation _slideAnimation; + +// // Navigation State +// int _selectedIndex = 0; + +// @override +// void initState() { +// super.initState(); +// _initializeData(); +// _setupAnimations(); +// } + +// @override +// void dispose() { +// _fadeController.dispose(); +// _slideController.dispose(); +// super.dispose(); +// } + +// // Initialize data fetching +// void _initializeData() { +// fetchRecentTransactions().then((transactions) { +// // Handle transactions data +// }); +// } + +// // Setup animation controllers and animations +// void _setupAnimations() { +// _fadeController = AnimationController( +// duration: const Duration(milliseconds: 1200), +// vsync: this, +// ); + +// _slideController = AnimationController( +// duration: const Duration(milliseconds: 800), +// vsync: this, +// ); + +// _fadeAnimation = Tween( +// begin: 0.0, +// end: 1.0, +// ).animate(CurvedAnimation( +// parent: _fadeController, +// curve: Curves.easeOut, +// )); + +// _slideAnimation = Tween( +// begin: const Offset(0, 0.3), +// end: Offset.zero, +// ).animate(CurvedAnimation( +// parent: _slideController, +// curve: Curves.easeOutCubic, +// )); + +// // Start animations +// _fadeController.forward(); +// _slideController.forward(); +// } + +// // Build greeting header with enhanced styling +// Widget _buildGreetingHeader() { +// return Container( +// margin: const EdgeInsets.only(bottom: 24), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// // Greeting Section +// Expanded( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// 'Good Morning! 👋', +// style: GoogleFonts.inter( +// color: primaryColor, +// fontSize: 28, +// fontWeight: FontWeight.w700, +// height: 1.2, +// ), +// ), +// const SizedBox(height: 4), +// Text( +// 'Welcome back to your financial dashboard', +// style: GoogleFonts.inter( +// color: primaryColor.withOpacity(0.7), +// fontSize: 14, +// fontWeight: FontWeight.w400, +// ), +// ), +// ], +// ), +// ), + +// // Notification Button with enhanced design +// Container( +// width: 52, +// height: 52, +// decoration: BoxDecoration( +// color: cardColor, +// borderRadius: BorderRadius.circular(18), +// boxShadow: [ +// BoxShadow( +// color: accentColor.withOpacity(0.1), +// blurRadius: 12, +// offset: const Offset(0, 4), +// ), +// ], +// border: Border.all( +// color: accentColor.withOpacity(0.1), +// width: 1, +// ), +// ), +// child: Material( +// color: Colors.transparent, +// child: InkWell( +// borderRadius: BorderRadius.circular(18), +// onTap: () { +// // Handle notification tap +// }, +// child: Icon( +// Icons.notifications_outlined, +// color: accentColor, +// size: 26, +// ), +// ), +// ), +// ), +// ], +// ), +// ); +// } + +// // Build main content sections +// Widget _buildMainContent() { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// // Balance Card Section +// Container( +// margin: const EdgeInsets.only(bottom: 28), +// child: const BalanceCardPage(), +// ), + +// // Quick Actions Section +// Container( +// margin: const EdgeInsets.only(bottom: 28), +// child: QuickActionsPage(), +// ), + +// // Recent Transactions Section +// Container( +// margin: const EdgeInsets.only(bottom: 32), +// child: RecentTransactionsWidget( +// recentTransactions: fetchRecentTransactions(), +// ), +// ), + +// // Bottom spacing for FAB +// const SizedBox(height: 100), +// ], +// ); +// } + +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// backgroundColor: backgroundColor, +// body: SafeArea( +// child: FadeTransition( +// opacity: _fadeAnimation, +// child: SlideTransition( +// position: _slideAnimation, +// child: CustomScrollView( +// physics: const BouncingScrollPhysics(), +// slivers: [ +// SliverToBoxAdapter( +// child: Padding( +// padding: const EdgeInsets.fromLTRB(20, 16, 20, 0), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// _buildGreetingHeader(), +// _buildMainContent(), +// ], +// ), +// ), +// ), +// ], +// ), +// ), +// ), +// ), + +// // Enhanced Floating Action Button +// floatingActionButton: CustomNavBar( +// currentIndex: _selectedIndex, +// onTap: (index) { +// setState(() => _selectedIndex = index); +// }, +// backgroundColor: backgroundColor, +// accentColor: accentColor, +// primaryColor: primaryColor, +// cardColor: cardColor, +// floatingActionButtonLocation: FloatingActionButtonLocation.centerTop, +// ), +// ); +// } +// } +// ignore_for_file: deprecated_member_use, unused_local_variable, use_super_parameters, avoid_print import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:monarch/main_pages/HomePage/navbar.dart'; import 'package:monarch/other_pages/colors.dart'; import 'package:monarch/support/fetch_service.dart'; import 'package:monarch/main_pages/HomePage/hero_card.dart'; -import 'package:monarch/main_pages/HomePage/navbar.dart'; import 'package:monarch/main_pages/HomePage/quick_actions.dart'; import 'package:monarch/support/transcations_recent.dart'; @@ -18,27 +251,36 @@ class FinTrackHomePage extends StatefulWidget { class _FinTrackHomePageState extends State with TickerProviderStateMixin { - // Animation Controllers late AnimationController _fadeController; late AnimationController _slideController; + late AnimationController _scaleController; + + // Animations late Animation _fadeAnimation; late Animation _slideAnimation; + late Animation _scaleAnimation; // Navigation State + // ignore: prefer_final_fields int _selectedIndex = 0; + // Time-based greeting data + String _greetingText = ''; + @override void initState() { super.initState(); _initializeData(); _setupAnimations(); + _updateGreeting(); } @override void dispose() { _fadeController.dispose(); _slideController.dispose(); + _scaleController.dispose(); super.dispose(); } @@ -49,144 +291,469 @@ class _FinTrackHomePageState extends State }); } - // Setup animation controllers and animations + // Update greeting based on current time + void _updateGreeting() { + final now = DateTime.now(); + final hour = now.hour; + + if (hour >= 5 && hour < 12) { + _greetingText = 'Good Morning'; + } else if (hour >= 12 && hour < 17) { + _greetingText = 'Good Afternoon'; + } else if (hour >= 17 && hour < 21) { + _greetingText = 'Good Evening'; + } else { + _greetingText = 'Good Night'; + } + } + + // Setup enhanced animation controllers void _setupAnimations() { _fadeController = AnimationController( - duration: const Duration(milliseconds: 1200), + duration: const Duration(milliseconds: 1500), vsync: this, ); _slideController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _scaleController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); - _fadeAnimation = Tween( - begin: 0.0, - end: 1.0, - ).animate(CurvedAnimation( - parent: _fadeController, - curve: Curves.easeOut, - )); + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeOutQuart), + ); _slideAnimation = Tween( - begin: const Offset(0, 0.3), + begin: const Offset(0, 0.2), end: Offset.zero, - ).animate(CurvedAnimation( - parent: _slideController, - curve: Curves.easeOutCubic, - )); + ).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); - // Start animations + _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( + CurvedAnimation(parent: _scaleController, curve: Curves.elasticOut), + ); + + // Staggered animation start _fadeController.forward(); - _slideController.forward(); + Future.delayed(const Duration(milliseconds: 200), () { + _slideController.forward(); + }); + Future.delayed(const Duration(milliseconds: 400), () { + _scaleController.forward(); + }); } - // Build greeting header with enhanced styling + // Enhanced greeting header with time-based content Widget _buildGreetingHeader() { return Container( - margin: const EdgeInsets.only(bottom: 24), + margin: const EdgeInsets.only(bottom: 28), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Greeting Section + // Enhanced Greeting Section Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Good Morning! 👋', - style: GoogleFonts.inter( - color: primaryColor, - fontSize: 28, - fontWeight: FontWeight.w700, - height: 1.2, - ), - ), - const SizedBox(height: 4), - Text( - 'Welcome back to your financial dashboard', - style: GoogleFonts.inter( - color: primaryColor.withOpacity(0.7), - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), + child: AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, child) { + return Transform.scale( + scale: _scaleAnimation.value, + alignment: Alignment.centerLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Main greeting with emoji + Row( + children: [ + Text( + '$_greetingText ', + style: GoogleFonts.inter( + color: primaryColor, + fontSize: 32, + fontWeight: FontWeight.w800, + height: 1.1, + letterSpacing: -0.5, + ), + ), + ], + ), + const SizedBox(height: 6), - // Notification Button with enhanced design - Container( - width: 52, - height: 52, - decoration: BoxDecoration( - color: cardColor, - borderRadius: BorderRadius.circular(18), - boxShadow: [ - BoxShadow( - color: accentColor.withOpacity(0.1), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ], - border: Border.all( - color: accentColor.withOpacity(0.1), - width: 1, - ), - ), - child: Material( - color: Colors.transparent, - child: InkWell( - borderRadius: BorderRadius.circular(18), - onTap: () { - // Handle notification tap - }, - child: Icon( - Icons.notifications_outlined, - color: accentColor, - size: 26, - ), - ), + // Enhanced sub-greeting + const SizedBox(height: 8), + // Date indicator + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: accentColor.withOpacity(0.08), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: accentColor.withOpacity(0.15), + width: 1, + ), + ), + child: Text( + _getFormattedDate(), + style: GoogleFonts.inter( + color: accentColor, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ); + }, ), ), + const SizedBox(width: 16), + // Enhanced notification button + _buildTransactionButtons(), ], ), ); } - // Build main content sections + // Get formatted date string + String _getFormattedDate() { + final now = DateTime.now(); + final weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + final months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]; + + return '${weekdays[now.weekday - 1]}, ${now.day} ${months[now.month - 1]}'; + } + + // Enhanced Transaction Entry Buttons with perfect UX + Widget _buildTransactionButtons() { + return AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, child) { + return Transform.scale( + scale: _scaleAnimation.value, + child: Row( + children: [ + // Gmail Transaction Button + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: accentColor.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, + ), + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + border: Border.all( + color: accentColor.withOpacity(0.08), + width: 1.5, + ), + ), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(20), + child: InkWell( + borderRadius: BorderRadius.circular(20), + onTap: () { + _showTransactionEntryDialog('email'); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + ), + child: Icon( + Icons.mail_outline, + color: accentColor, + size: 28, + ), + ), + ), + ), + ), + + const SizedBox(width: 12), + + // Voice Transaction Button + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: accentColor.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, + ), + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + border: Border.all( + color: accentColor.withOpacity(0.08), + width: 1.5, + ), + ), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(20), + child: InkWell( + borderRadius: BorderRadius.circular(20), + onTap: () { + _showTransactionEntryDialog('voice'); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + ), + child: Icon( + Icons.mic_outlined, + color: accentColor, + size: 28, + ), + ), + ), + ), + ), + ], + ), + ); + }, + ); + } + + // Transaction Entry Dialog (placeholder for functionality) + void _showTransactionEntryDialog(String type) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: + (context) => Container( + height: MediaQuery.of(context).size.height * 0.7, + decoration: BoxDecoration( + color: cardColor, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(28), + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 32, + offset: const Offset(0, -8), + ), + ], + ), + child: Column( + children: [ + // Handle Bar + Container( + width: 48, + height: 4, + margin: const EdgeInsets.only(top: 16, bottom: 24), + decoration: BoxDecoration( + color: primaryColor.withOpacity(0.2), + borderRadius: BorderRadius.circular(2), + ), + ), + + // Dialog Content + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: accentColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: accentColor.withOpacity(0.2), + width: 1, + ), + ), + child: Icon( + type == 'email' + ? Icons.mail_outline + : Icons.mic_outlined, + color: accentColor, + size: 24, + ), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + type == 'email' + ? 'Email Transaction' + : 'Voice Transaction', + style: GoogleFonts.inter( + color: primaryColor, + fontSize: 20, + fontWeight: FontWeight.w700, + ), + ), + Text( + type == 'email' + ? 'Forward receipts to add transactions' + : 'Speak to record your transaction', + style: GoogleFonts.inter( + color: primaryColor.withOpacity(0.6), + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], + ), + + const SizedBox(height: 32), + + // Placeholder content + Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + type == 'email' ? Icons.email : Icons.mic, + size: 64, + color: accentColor.withOpacity(0.3), + ), + const SizedBox(height: 16), + Text( + type == 'email' + ? 'Email integration coming soon!' + : 'Voice recording coming soon!', + style: GoogleFonts.inter( + color: primaryColor.withOpacity(0.6), + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } + + // Enhanced main content with better spacing Widget _buildMainContent() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Balance Card Section - Container( - margin: const EdgeInsets.only(bottom: 28), - child: const BalanceCardPage(), - ), - - // Quick Actions Section - Container( - margin: const EdgeInsets.only(bottom: 28), - child: QuickActionsPage(), - ), - - // Recent Transactions Section - Container( - margin: const EdgeInsets.only(bottom: 32), - child: RecentTransactionsWidget( - recentTransactions: fetchRecentTransactions(), + // Balance Card Section with staggered animation + _buildAnimatedSection( + delay: 600, + child: Container( + margin: const EdgeInsets.only(bottom: 32), + child: const BalanceCardPage(), ), ), - // Bottom spacing for FAB - const SizedBox(height: 100), + // Quick Actions Section with staggered animation + _buildAnimatedSection( + delay: 800, + child: Container( + margin: const EdgeInsets.only(bottom: 32), + child: QuickActionsPage(), + ), + ), + + // Recent Transactions Section with staggered animation + _buildAnimatedSection( + delay: 1000, + child: Container( + margin: const EdgeInsets.only(bottom: 32), + child: RecentTransactionsWidget( + recentTransactions: fetchRecentTransactions(), + ), + ), + ), + + // Bottom spacing for FAB and navigation + const SizedBox(height: 120), ], ); } + // Helper method for staggered animations + Widget _buildAnimatedSection({required int delay, required Widget child}) { + return FutureBuilder( + future: Future.delayed(Duration(milliseconds: delay)), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Opacity(opacity: 0, child: child); + } + return AnimatedOpacity( + opacity: 1, + duration: const Duration(milliseconds: 600), + curve: Curves.easeOut, + child: AnimatedSlide( + offset: + snapshot.connectionState == ConnectionState.done + ? Offset.zero + : const Offset(0, 0.1), + duration: const Duration(milliseconds: 600), + curve: Curves.easeOutCubic, + child: child, + ), + ); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -196,28 +763,57 @@ class _FinTrackHomePageState extends State opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, - child: CustomScrollView( - physics: const BouncingScrollPhysics(), - slivers: [ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.fromLTRB(20, 16, 20, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildGreetingHeader(), - _buildMainContent(), - ], + child: RefreshIndicator( + onRefresh: () async { + // Add refresh functionality + _initializeData(); + _updateGreeting(); + setState(() {}); + // Add haptic feedback + // HapticFeedback.lightImpact(); + }, + color: accentColor, + backgroundColor: cardColor, + strokeWidth: 2.5, + displacement: 60, + child: CustomScrollView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + slivers: [ + SliverToBoxAdapter( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + backgroundColor, + backgroundColor.withOpacity(0.95), + ], + stops: const [0.0, 1.0], + ), + ), + child: Padding( + padding: const EdgeInsets.fromLTRB(24, 20, 24, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildGreetingHeader(), + _buildMainContent(), + ], + ), + ), ), ), - ), - ], + ], + ), ), ), + + // Enhanced Floating Action Button ), ), - - // Enhanced Floating Action Button floatingActionButton: CustomNavBar( currentIndex: _selectedIndex, onTap: (index) { diff --git a/Frontend/lib/main_pages/Statistics/budget_manager.dart b/Frontend/lib/main_pages/Statistics/Budget/budget_manager.dart similarity index 100% rename from Frontend/lib/main_pages/Statistics/budget_manager.dart rename to Frontend/lib/main_pages/Statistics/Budget/budget_manager.dart diff --git a/Frontend/lib/main_pages/Statistics/update_budget.dart b/Frontend/lib/main_pages/Statistics/Budget/update_budget.dart similarity index 100% rename from Frontend/lib/main_pages/Statistics/update_budget.dart rename to Frontend/lib/main_pages/Statistics/Budget/update_budget.dart diff --git a/Frontend/lib/main_pages/Statistics/statistics.dart b/Frontend/lib/main_pages/Statistics/statistics.dart index 3e26433..2becd4a 100644 --- a/Frontend/lib/main_pages/Statistics/statistics.dart +++ b/Frontend/lib/main_pages/Statistics/statistics.dart @@ -9,8 +9,8 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:monarch/support/add.dart'; import 'package:monarch/other_pages/enviroment.dart'; -import 'package:monarch/main_pages/Statistics/update_budget.dart'; -import 'package:monarch/main_pages/Statistics/budget_manager.dart'; +import 'package:monarch/main_pages/Statistics/Budget/update_budget.dart'; +import 'package:monarch/main_pages/Statistics/Budget/budget_manager.dart'; import 'package:monarch/main_pages/HomePage/homepage.dart'; import 'package:monarch/main_pages/HomePage/navbar.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/Frontend/lib/other_pages/enviroment.dart b/Frontend/lib/other_pages/enviroment.dart index 6e546ae..9d0169f 100644 --- a/Frontend/lib/other_pages/enviroment.dart +++ b/Frontend/lib/other_pages/enviroment.dart @@ -1,5 +1,5 @@ class Environment { - static const String baseUrl = 'http://10.231.41.181:3000'; + static const String baseUrl = 'http://192.168.1.9:3000'; static const String serverClientId = "278433619849-cg6f7gk5cc45rgu1ojrlkf794lm4udgn.apps.googleusercontent.com"; }