From ebc5808aac1cc614c22220072448595c00f4c09e Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Thu, 5 Jun 2025 21:25:00 -0300 Subject: [PATCH 01/11] inital change for drawer --- lib/shared/widgets/mostro_app_drawer.dart | 158 ++++++++++++++-------- 1 file changed, 99 insertions(+), 59 deletions(-) diff --git a/lib/shared/widgets/mostro_app_drawer.dart b/lib/shared/widgets/mostro_app_drawer.dart index 91ac8cb3..57888cd6 100644 --- a/lib/shared/widgets/mostro_app_drawer.dart +++ b/lib/shared/widgets/mostro_app_drawer.dart @@ -7,71 +7,111 @@ class MostroAppDrawer extends StatelessWidget { @override Widget build(BuildContext context) { + // Get the status bar height to position drawer below app bar + final statusBarHeight = MediaQuery.of(context).padding.top; + final appBarHeight = AppBar().preferredSize.height; + return Drawer( - backgroundColor: AppTheme.dark2, - child: ListView( - children: [ - DrawerHeader( - decoration: BoxDecoration( - color: AppTheme.dark1, - image: const DecorationImage( - image: AssetImage('assets/images/logo.png'), - fit: BoxFit.scaleDown)), - child: Stack(), - ), - ListTile( - leading: Icon( - Icons.person_outline_sharp, - color: AppTheme.cream1, + backgroundColor: AppTheme.dark1, // Match bottom navbar color + width: MediaQuery.of(context).size.width * 0.7, // Make drawer more compact + child: Padding( + padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), + child: Column( + children: [ + // Logo header with smaller height + Container( + height: 120, + padding: const EdgeInsets.symmetric(vertical: 16), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/logo.png'), + fit: BoxFit.contain, + ), + ), ), - title: Text( - 'Account', - style: AppTheme.theme.textTheme.headlineMedium, + const Divider(height: 1, color: Colors.transparent), + // Account option + ListTile( + dense: true, // Make more compact + leading: Icon( + Icons.person_outline_rounded, // Using rounded icons to match bottom navbar + color: AppTheme.cream1, + size: 22, // Smaller icon + ), + title: Text( + 'Account', + style: AppTheme.theme.textTheme.bodyLarge?.copyWith( + color: AppTheme.cream1, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + context.push('/key_management'); + Navigator.pop(context); // Close drawer after selection + }, ), - onTap: () { - context.push('/key_management'); - }, - ), - ListTile( - leading: Icon( - Icons.settings_outlined, - color: AppTheme.cream1, + // Settings option + ListTile( + dense: true, // Make more compact + leading: Icon( + Icons.settings_rounded, // Using rounded icons to match bottom navbar + color: AppTheme.cream1, + size: 22, // Smaller icon + ), + title: Text( + 'Settings', + style: AppTheme.theme.textTheme.bodyLarge?.copyWith( + color: AppTheme.cream1, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + context.push('/settings'); + Navigator.pop(context); // Close drawer after selection + }, ), - title: Text( - 'Settings', - style: AppTheme.theme.textTheme.headlineMedium, + // About option + ListTile( + dense: true, // Make more compact + leading: Icon( + Icons.info_rounded, // Using rounded icons to match bottom navbar + color: AppTheme.cream1, + size: 22, // Smaller icon + ), + title: Text( + 'About', + style: AppTheme.theme.textTheme.bodyLarge?.copyWith( + color: AppTheme.cream1, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + context.push('/about'); + Navigator.pop(context); // Close drawer after selection + }, ), - onTap: () { - context.push('/settings'); - }, - ), - ListTile( - leading: Icon( - Icons.info_outlined, - color: AppTheme.cream1, + // Walkthrough option + ListTile( + dense: true, // Make more compact + leading: Icon( + Icons.menu_book_rounded, // Using rounded icons to match bottom navbar + color: AppTheme.cream1, + size: 22, // Smaller icon + ), + title: Text( + 'Walkthrough', + style: AppTheme.theme.textTheme.bodyLarge?.copyWith( + color: AppTheme.cream1, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + context.push('/walkthrough'); + Navigator.pop(context); // Close drawer after selection + }, ), - title: Text( - 'About', - style: AppTheme.theme.textTheme.headlineMedium, - ), - onTap: () { - context.push('/about'); - }, - ), - ListTile( - leading: Icon( - Icons.menu_book_sharp, - color: AppTheme.cream1, - ), - title: Text( - 'Walkthrough', - style: AppTheme.theme.textTheme.headlineMedium, - ), - onTap: () { - context.push('/walkthrough'); - }, - ), - ], + ], + ), ), ); } From be4f905f055847c5b3aeb9a599edfad70b4d5780 Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Mon, 16 Jun 2025 22:44:05 -0300 Subject: [PATCH 02/11] feat: implement custom drawer overlay with slide animation and state management --- .../chat/screens/chat_rooms_list.dart | 43 +++--- lib/features/home/screens/home_screen.dart | 119 +++++++-------- .../trades/screens/trades_screen.dart | 135 +++++++++--------- lib/shared/providers/drawer_provider.dart | 13 ++ lib/shared/widgets/custom_drawer_overlay.dart | 135 ++++++++++++++++++ lib/shared/widgets/mostro_app_bar.dart | 16 ++- 6 files changed, 310 insertions(+), 151 deletions(-) create mode 100644 lib/shared/providers/drawer_provider.dart create mode 100644 lib/shared/widgets/custom_drawer_overlay.dart diff --git a/lib/features/chat/screens/chat_rooms_list.dart b/lib/features/chat/screens/chat_rooms_list.dart index 8bc3c7bd..0655d0b9 100644 --- a/lib/features/chat/screens/chat_rooms_list.dart +++ b/lib/features/chat/screens/chat_rooms_list.dart @@ -10,7 +10,7 @@ import 'package:mostro_mobile/shared/providers/legible_handle_provider.dart'; import 'package:mostro_mobile/shared/providers/session_notifier_provider.dart'; import 'package:mostro_mobile/shared/widgets/bottom_nav_bar.dart'; import 'package:mostro_mobile/shared/widgets/mostro_app_bar.dart'; -import 'package:mostro_mobile/shared/widgets/mostro_app_drawer.dart'; +import 'package:mostro_mobile/shared/widgets/custom_drawer_overlay.dart'; class ChatRoomsScreen extends ConsumerWidget { const ChatRoomsScreen({super.key}); @@ -22,27 +22,28 @@ class ChatRoomsScreen extends ConsumerWidget { return Scaffold( backgroundColor: AppTheme.dark1, appBar: const MostroAppBar(), - drawer: const MostroAppDrawer(), - body: Container( - margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), - decoration: BoxDecoration( - color: const Color(0xFF303544), - borderRadius: BorderRadius.circular(20), - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'CHAT', - style: TextStyle(color: AppTheme.mostroGreen), + body: CustomDrawerOverlay( + child: Container( + margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), + decoration: BoxDecoration( + color: const Color(0xFF303544), + borderRadius: BorderRadius.circular(20), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + 'CHAT', + style: TextStyle(color: AppTheme.mostroGreen), + ), ), - ), - Expanded( - child: _buildBody(chatListState), - ), - const BottomNavBar(), - ], + Expanded( + child: _buildBody(chatListState), + ), + const BottomNavBar(), + ], + ), ), ), ); diff --git a/lib/features/home/screens/home_screen.dart b/lib/features/home/screens/home_screen.dart index e495a610..39e18cd8 100644 --- a/lib/features/home/screens/home_screen.dart +++ b/lib/features/home/screens/home_screen.dart @@ -9,7 +9,7 @@ import 'package:mostro_mobile/shared/widgets/add_order_button.dart'; import 'package:mostro_mobile/shared/widgets/bottom_nav_bar.dart'; import 'package:mostro_mobile/shared/widgets/mostro_app_bar.dart'; import 'package:mostro_mobile/shared/widgets/order_filter.dart'; -import 'package:mostro_mobile/shared/widgets/mostro_app_drawer.dart'; +import 'package:mostro_mobile/shared/widgets/custom_drawer_overlay.dart'; class HomeScreen extends ConsumerWidget { const HomeScreen({super.key}); @@ -21,69 +21,70 @@ class HomeScreen extends ConsumerWidget { return Scaffold( backgroundColor: AppTheme.backgroundDark, appBar: MostroAppBar(), - drawer: const MostroAppDrawer(), - body: Stack( - children: [ - RefreshIndicator( - onRefresh: () async { - return await ref.refresh(filteredOrdersProvider); - }, - child: Column( - children: [ - _buildTabs(ref), - _buildFilterButton(context, ref), - Expanded( - child: Container( - color: const Color(0xFF1D212C), - child: filteredOrders.isEmpty - ? const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.search_off, - color: Colors.white30, - size: 48, - ), - SizedBox(height: 16), - Text( - 'No orders available', - style: TextStyle( - color: Colors.white60, - fontSize: 16, + body: CustomDrawerOverlay( + child: Stack( + children: [ + RefreshIndicator( + onRefresh: () async { + return await ref.refresh(filteredOrdersProvider); + }, + child: Column( + children: [ + _buildTabs(ref), + _buildFilterButton(context, ref), + Expanded( + child: Container( + color: const Color(0xFF1D212C), + child: filteredOrders.isEmpty + ? const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.search_off, + color: Colors.white30, + size: 48, ), - ), - Text( - 'Try changing filter settings or check back later', - style: TextStyle( - color: Colors.white38, - fontSize: 14, + SizedBox(height: 16), + Text( + 'No orders available', + style: TextStyle( + color: Colors.white60, + fontSize: 16, + ), ), - textAlign: TextAlign.center, - ), - ], + Text( + 'Try changing filter settings or check back later', + style: TextStyle( + color: Colors.white38, + fontSize: 14, + ), + textAlign: TextAlign.center, + ), + ], + ), + ) + : ListView.builder( + itemCount: filteredOrders.length, + padding: const EdgeInsets.only(bottom: 155, top: 6), + itemBuilder: (context, index) { + final order = filteredOrders[index]; + return OrderListItem(order: order); + }, ), - ) - : ListView.builder( - itemCount: filteredOrders.length, - padding: const EdgeInsets.only(bottom: 155, top: 6), - itemBuilder: (context, index) { - final order = filteredOrders[index]; - return OrderListItem(order: order); - }, - ), + ), ), - ), - const BottomNavBar(), - ], + const BottomNavBar(), + ], + ), ), - ), - Positioned( - bottom: 80 + MediaQuery.of(context).viewPadding.bottom + 16, - right: 16, - child: const AddOrderButton(), - ), - ], + Positioned( + bottom: 80 + MediaQuery.of(context).viewPadding.bottom + 16, + right: 16, + child: const AddOrderButton(), + ), + ], + ), ), ); } diff --git a/lib/features/trades/screens/trades_screen.dart b/lib/features/trades/screens/trades_screen.dart index afc56b2f..70c846fd 100644 --- a/lib/features/trades/screens/trades_screen.dart +++ b/lib/features/trades/screens/trades_screen.dart @@ -9,7 +9,7 @@ import 'package:mostro_mobile/features/trades/providers/trades_provider.dart'; import 'package:mostro_mobile/features/trades/widgets/trades_list.dart'; import 'package:mostro_mobile/shared/widgets/bottom_nav_bar.dart'; import 'package:mostro_mobile/shared/widgets/mostro_app_bar.dart'; -import 'package:mostro_mobile/shared/widgets/mostro_app_drawer.dart'; +import 'package:mostro_mobile/shared/widgets/custom_drawer_overlay.dart'; class TradesScreen extends ConsumerWidget { const TradesScreen({super.key}); @@ -22,76 +22,77 @@ class TradesScreen extends ConsumerWidget { return Scaffold( backgroundColor: AppTheme.dark1, appBar: const MostroAppBar(), - drawer: const MostroAppDrawer(), - body: RefreshIndicator( - onRefresh: () async { - // Force reload the orders repository first - ref.read(orderRepositoryProvider).reloadData(); - // Then refresh the filtered trades provider - ref.invalidate(filteredTradesProvider); - }, - child: Container( - margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), - decoration: BoxDecoration( - color: AppTheme.dark2, - borderRadius: BorderRadius.circular(20), - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'MY TRADES', - style: TextStyle(color: AppTheme.mostroGreen), - ), - ), - // Use the async value pattern to handle different states - tradesAsync.when( - data: (trades) => _buildFilterButton(context, ref, trades), - loading: () => _buildFilterButton(context, ref, []), - error: (error, _) => _buildFilterButton(context, ref, []), - ), - const SizedBox(height: 6.0), - Expanded( - child: tradesAsync.when( - data: (trades) => _buildOrderList(trades), - loading: () => const Center( - child: CircularProgressIndicator(), + body: CustomDrawerOverlay( + child: RefreshIndicator( + onRefresh: () async { + // Force reload the orders repository first + ref.read(orderRepositoryProvider).reloadData(); + // Then refresh the filtered trades provider + ref.invalidate(filteredTradesProvider); + }, + child: Container( + margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), + decoration: BoxDecoration( + color: AppTheme.dark2, + borderRadius: BorderRadius.circular(20), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + 'MY TRADES', + style: TextStyle(color: AppTheme.mostroGreen), ), - error: (error, _) => Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.error_outline, - color: Colors.red, - size: 60, - ), - const SizedBox(height: 16), - Text( - 'Error loading trades', - style: TextStyle(color: AppTheme.cream1), - ), - Text( - error.toString(), - style: TextStyle(color: AppTheme.cream1, fontSize: 12), - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - ElevatedButton( - onPressed: () { - ref.invalidate(orderEventsProvider); - ref.invalidate(filteredTradesProvider); - }, - child: const Text('Retry'), - ), - ], + ), + // Use the async value pattern to handle different states + tradesAsync.when( + data: (trades) => _buildFilterButton(context, ref, trades), + loading: () => _buildFilterButton(context, ref, []), + error: (error, _) => _buildFilterButton(context, ref, []), + ), + const SizedBox(height: 6.0), + Expanded( + child: tradesAsync.when( + data: (trades) => _buildOrderList(trades), + loading: () => const Center( + child: CircularProgressIndicator(), + ), + error: (error, _) => Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + const SizedBox(height: 16), + Text( + 'Error loading trades', + style: TextStyle(color: AppTheme.cream1), + ), + Text( + error.toString(), + style: TextStyle(color: AppTheme.cream1, fontSize: 12), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + ref.invalidate(orderEventsProvider); + ref.invalidate(filteredTradesProvider); + }, + child: const Text('Retry'), + ), + ], + ), ), ), ), - ), - const BottomNavBar(), - ], + const BottomNavBar(), + ], + ), ), ), ), diff --git a/lib/shared/providers/drawer_provider.dart b/lib/shared/providers/drawer_provider.dart new file mode 100644 index 00000000..d474c76b --- /dev/null +++ b/lib/shared/providers/drawer_provider.dart @@ -0,0 +1,13 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class DrawerNotifier extends StateNotifier { + DrawerNotifier() : super(false); + + void openDrawer() => state = true; + void closeDrawer() => state = false; + void toggleDrawer() => state = !state; +} + +final drawerProvider = StateNotifierProvider((ref) { + return DrawerNotifier(); +}); diff --git a/lib/shared/widgets/custom_drawer_overlay.dart b/lib/shared/widgets/custom_drawer_overlay.dart new file mode 100644 index 00000000..f4ef4a27 --- /dev/null +++ b/lib/shared/widgets/custom_drawer_overlay.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:lucide_icons/lucide_icons.dart'; +import 'package:mostro_mobile/core/app_theme.dart'; +import 'package:mostro_mobile/shared/providers/drawer_provider.dart'; + +class CustomDrawerOverlay extends ConsumerWidget { + final Widget child; + + const CustomDrawerOverlay({super.key, required this.child}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isDrawerOpen = ref.watch(drawerProvider); + final statusBarHeight = MediaQuery.of(context).padding.top; + final appBarHeight = AppBar().preferredSize.height; + + return Stack( + children: [ + // Main content + child, + + // Overlay background + if (isDrawerOpen) + GestureDetector( + onTap: () => ref.read(drawerProvider.notifier).closeDrawer(), + child: Container( + width: double.infinity, + height: double.infinity, + color: Colors.black.withOpacity(0.3), + ), + ), + + // Drawer + AnimatedPositioned( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + left: isDrawerOpen ? 0 : -MediaQuery.of(context).size.width * 0.7, + top: 0, + bottom: 0, + child: Container( + width: MediaQuery.of(context).size.width * 0.7, + decoration: BoxDecoration( + color: AppTheme.dark1, + border: Border( + right: BorderSide( + color: Colors.white.withAlpha(10), + width: 1.0, + ), + ), + ), + child: Padding( + padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), + child: Column( + children: [ + // Logo header + Container( + height: 80, + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/logo.png'), + fit: BoxFit.contain, + ), + ), + ), + const Divider(height: 1, color: Colors.transparent), + + // Menu items + _buildMenuItem( + context, + ref, + icon: LucideIcons.user, + title: 'Account', + route: '/key_management', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.settings, + title: 'Settings', + route: '/settings', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.info, + title: 'About', + route: '/about', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.bookOpen, + title: 'Walkthrough', + route: '/walkthrough', + ), + ], + ), + ), + ), + ), + ], + ); + } + + Widget _buildMenuItem( + BuildContext context, + WidgetRef ref, { + required IconData icon, + required String title, + required String route, + }) { + return ListTile( + dense: true, + leading: Icon( + icon, + color: AppTheme.cream1, + size: 22, + ), + title: Text( + title, + style: AppTheme.theme.textTheme.bodyLarge?.copyWith( + color: AppTheme.cream1, + fontWeight: FontWeight.w500, + ), + ), + onTap: () { + ref.read(drawerProvider.notifier).closeDrawer(); + context.push(route); + }, + ); + } +} diff --git a/lib/shared/widgets/mostro_app_bar.dart b/lib/shared/widgets/mostro_app_bar.dart index 361044f7..ac413b21 100644 --- a/lib/shared/widgets/mostro_app_bar.dart +++ b/lib/shared/widgets/mostro_app_bar.dart @@ -1,8 +1,8 @@ -// lib/shared/widgets/mostro_app_bar.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:heroicons/heroicons.dart'; import 'package:mostro_mobile/core/app_theme.dart'; +import 'package:mostro_mobile/shared/providers/drawer_provider.dart'; class MostroAppBar extends ConsumerWidget implements PreferredSizeWidget { const MostroAppBar({super.key}); @@ -10,9 +10,17 @@ class MostroAppBar extends ConsumerWidget implements PreferredSizeWidget { @override Widget build(BuildContext context, WidgetRef ref) { return AppBar( - backgroundColor: AppTheme.dark1, + backgroundColor: AppTheme.backgroundDark, elevation: 0, leadingWidth: 70, + // Add bottom border similar to bottom navbar + bottom: PreferredSize( + preferredSize: const Size.fromHeight(1.0), + child: Container( + height: 1.0, + color: Colors.white.withValues(alpha: 0.1), + ), + ), // Use a custom IconButton with specific padding leading: Padding( padding: const EdgeInsets.only(left: 16.0), @@ -24,7 +32,7 @@ class MostroAppBar extends ConsumerWidget implements PreferredSizeWidget { size: 28, ), onPressed: () { - Scaffold.of(context).openDrawer(); + ref.read(drawerProvider.notifier).toggleDrawer(); }, ), ), @@ -52,5 +60,5 @@ class MostroAppBar extends ConsumerWidget implements PreferredSizeWidget { } @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); + Size get preferredSize => const Size.fromHeight(kToolbarHeight + 1.0); } From 112bcc9ed6986be8cd7a0741f3478881eda179cc Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Mon, 16 Jun 2025 22:53:17 -0300 Subject: [PATCH 03/11] Update lib/shared/widgets/mostro_app_bar.dart Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- lib/shared/widgets/mostro_app_bar.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/shared/widgets/mostro_app_bar.dart b/lib/shared/widgets/mostro_app_bar.dart index ac413b21..74a57812 100644 --- a/lib/shared/widgets/mostro_app_bar.dart +++ b/lib/shared/widgets/mostro_app_bar.dart @@ -18,7 +18,7 @@ class MostroAppBar extends ConsumerWidget implements PreferredSizeWidget { preferredSize: const Size.fromHeight(1.0), child: Container( height: 1.0, - color: Colors.white.withValues(alpha: 0.1), + color: Colors.white.withOpacity(0.1), ), ), // Use a custom IconButton with specific padding From 29aaf124f376926f1e6e119f7e4a76c37d97cd73 Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Mon, 16 Jun 2025 22:55:07 -0300 Subject: [PATCH 04/11] feat: add back button handling to close drawer before exiting app --- lib/shared/widgets/custom_drawer_overlay.dart | 128 ++++++++++-------- 1 file changed, 69 insertions(+), 59 deletions(-) diff --git a/lib/shared/widgets/custom_drawer_overlay.dart b/lib/shared/widgets/custom_drawer_overlay.dart index f4ef4a27..c1f35c10 100644 --- a/lib/shared/widgets/custom_drawer_overlay.dart +++ b/lib/shared/widgets/custom_drawer_overlay.dart @@ -33,70 +33,80 @@ class CustomDrawerOverlay extends ConsumerWidget { ), // Drawer - AnimatedPositioned( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - left: isDrawerOpen ? 0 : -MediaQuery.of(context).size.width * 0.7, - top: 0, - bottom: 0, - child: Container( - width: MediaQuery.of(context).size.width * 0.7, - decoration: BoxDecoration( - color: AppTheme.dark1, - border: Border( - right: BorderSide( - color: Colors.white.withAlpha(10), - width: 1.0, + WillPopScope( + onWillPop: () async { + if (isDrawerOpen) { + // Close drawer if it's open + ref.read(drawerProvider.notifier).closeDrawer(); + return false; // Prevent route pop + } + return true; // Allow route pop + }, + child: AnimatedPositioned( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + left: isDrawerOpen ? 0 : -MediaQuery.of(context).size.width * 0.7, + top: 0, + bottom: 0, + child: Container( + width: MediaQuery.of(context).size.width * 0.7, + decoration: BoxDecoration( + color: AppTheme.dark1, + border: Border( + right: BorderSide( + color: Colors.white.withValues(alpha: 0.1), + width: 1.0, + ), ), ), - ), - child: Padding( - padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), - child: Column( - children: [ - // Logo header - Container( - height: 80, - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/logo.png'), - fit: BoxFit.contain, + child: Padding( + padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), + child: Column( + children: [ + // Logo header + Container( + height: 80, + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/logo.png'), + fit: BoxFit.contain, + ), ), ), - ), - const Divider(height: 1, color: Colors.transparent), + const Divider(height: 1, color: Colors.transparent), - // Menu items - _buildMenuItem( - context, - ref, - icon: LucideIcons.user, - title: 'Account', - route: '/key_management', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.settings, - title: 'Settings', - route: '/settings', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.info, - title: 'About', - route: '/about', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.bookOpen, - title: 'Walkthrough', - route: '/walkthrough', - ), - ], + // Menu items + _buildMenuItem( + context, + ref, + icon: LucideIcons.user, + title: 'Account', + route: '/key_management', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.settings, + title: 'Settings', + route: '/settings', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.info, + title: 'About', + route: '/about', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.bookOpen, + title: 'Walkthrough', + route: '/walkthrough', + ), + ], + ), ), ), ), From ea53dda26eb435b1040a604cbaa70cec549c82dd Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Mon, 16 Jun 2025 22:57:50 -0300 Subject: [PATCH 05/11] remove: delete unused MostroAppDrawer widget component --- lib/shared/widgets/mostro_app_drawer.dart | 118 ---------------------- 1 file changed, 118 deletions(-) delete mode 100644 lib/shared/widgets/mostro_app_drawer.dart diff --git a/lib/shared/widgets/mostro_app_drawer.dart b/lib/shared/widgets/mostro_app_drawer.dart deleted file mode 100644 index 57888cd6..00000000 --- a/lib/shared/widgets/mostro_app_drawer.dart +++ /dev/null @@ -1,118 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:mostro_mobile/core/app_theme.dart'; - -class MostroAppDrawer extends StatelessWidget { - const MostroAppDrawer({super.key}); - - @override - Widget build(BuildContext context) { - // Get the status bar height to position drawer below app bar - final statusBarHeight = MediaQuery.of(context).padding.top; - final appBarHeight = AppBar().preferredSize.height; - - return Drawer( - backgroundColor: AppTheme.dark1, // Match bottom navbar color - width: MediaQuery.of(context).size.width * 0.7, // Make drawer more compact - child: Padding( - padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), - child: Column( - children: [ - // Logo header with smaller height - Container( - height: 120, - padding: const EdgeInsets.symmetric(vertical: 16), - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/logo.png'), - fit: BoxFit.contain, - ), - ), - ), - const Divider(height: 1, color: Colors.transparent), - // Account option - ListTile( - dense: true, // Make more compact - leading: Icon( - Icons.person_outline_rounded, // Using rounded icons to match bottom navbar - color: AppTheme.cream1, - size: 22, // Smaller icon - ), - title: Text( - 'Account', - style: AppTheme.theme.textTheme.bodyLarge?.copyWith( - color: AppTheme.cream1, - fontWeight: FontWeight.w500, - ), - ), - onTap: () { - context.push('/key_management'); - Navigator.pop(context); // Close drawer after selection - }, - ), - // Settings option - ListTile( - dense: true, // Make more compact - leading: Icon( - Icons.settings_rounded, // Using rounded icons to match bottom navbar - color: AppTheme.cream1, - size: 22, // Smaller icon - ), - title: Text( - 'Settings', - style: AppTheme.theme.textTheme.bodyLarge?.copyWith( - color: AppTheme.cream1, - fontWeight: FontWeight.w500, - ), - ), - onTap: () { - context.push('/settings'); - Navigator.pop(context); // Close drawer after selection - }, - ), - // About option - ListTile( - dense: true, // Make more compact - leading: Icon( - Icons.info_rounded, // Using rounded icons to match bottom navbar - color: AppTheme.cream1, - size: 22, // Smaller icon - ), - title: Text( - 'About', - style: AppTheme.theme.textTheme.bodyLarge?.copyWith( - color: AppTheme.cream1, - fontWeight: FontWeight.w500, - ), - ), - onTap: () { - context.push('/about'); - Navigator.pop(context); // Close drawer after selection - }, - ), - // Walkthrough option - ListTile( - dense: true, // Make more compact - leading: Icon( - Icons.menu_book_rounded, // Using rounded icons to match bottom navbar - color: AppTheme.cream1, - size: 22, // Smaller icon - ), - title: Text( - 'Walkthrough', - style: AppTheme.theme.textTheme.bodyLarge?.copyWith( - color: AppTheme.cream1, - fontWeight: FontWeight.w500, - ), - ), - onTap: () { - context.push('/walkthrough'); - Navigator.pop(context); // Close drawer after selection - }, - ), - ], - ), - ), - ); - } -} From e10a3627c880c4d2df9170678847f37cf7be1401 Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Tue, 24 Jun 2025 02:24:49 -0300 Subject: [PATCH 06/11] feat: add horizontal swipe gestures for order type switching and drawer closing --- lib/features/home/screens/home_screen.dart | 99 +++++++------ lib/shared/widgets/custom_drawer_overlay.dart | 130 +++++++++++------- 2 files changed, 132 insertions(+), 97 deletions(-) diff --git a/lib/features/home/screens/home_screen.dart b/lib/features/home/screens/home_screen.dart index 39e18cd8..76ef4e69 100644 --- a/lib/features/home/screens/home_screen.dart +++ b/lib/features/home/screens/home_screen.dart @@ -28,54 +28,65 @@ class HomeScreen extends ConsumerWidget { onRefresh: () async { return await ref.refresh(filteredOrdersProvider); }, - child: Column( - children: [ - _buildTabs(ref), - _buildFilterButton(context, ref), - Expanded( - child: Container( - color: const Color(0xFF1D212C), - child: filteredOrders.isEmpty - ? const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.search_off, - color: Colors.white30, - size: 48, - ), - SizedBox(height: 16), - Text( - 'No orders available', - style: TextStyle( - color: Colors.white60, - fontSize: 16, + child: GestureDetector( + onHorizontalDragEnd: (details) { + // Si el gesto es hacia la izquierda (velocidad negativa), cambiamos a SELL BTC + if (details.primaryVelocity != null && details.primaryVelocity! < 0) { + ref.read(homeOrderTypeProvider.notifier).state = OrderType.buy; + } + // Si el gesto es hacia la derecha (velocidad positiva), cambiamos a BUY BTC + else if (details.primaryVelocity != null && details.primaryVelocity! > 0) { + ref.read(homeOrderTypeProvider.notifier).state = OrderType.sell; + } + }, + child: Column( + children: [ + _buildTabs(ref), + _buildFilterButton(context, ref), + Expanded( + child: Container( + color: const Color(0xFF1D212C), + child: filteredOrders.isEmpty + ? const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.search_off, + color: Colors.white30, + size: 48, ), - ), - Text( - 'Try changing filter settings or check back later', - style: TextStyle( - color: Colors.white38, - fontSize: 14, + SizedBox(height: 16), + Text( + 'No orders available', + style: TextStyle( + color: Colors.white60, + fontSize: 16, + ), ), - textAlign: TextAlign.center, - ), - ], + Text( + 'Try changing filter settings or check back later', + style: TextStyle( + color: Colors.white38, + fontSize: 14, + ), + textAlign: TextAlign.center, + ), + ], + ), + ) + : ListView.builder( + itemCount: filteredOrders.length, + padding: const EdgeInsets.only(bottom: 155, top: 6), + itemBuilder: (context, index) { + final order = filteredOrders[index]; + return OrderListItem(order: order); + }, ), - ) - : ListView.builder( - itemCount: filteredOrders.length, - padding: const EdgeInsets.only(bottom: 155, top: 6), - itemBuilder: (context, index) { - final order = filteredOrders[index]; - return OrderListItem(order: order); - }, - ), + ), ), - ), - const BottomNavBar(), - ], + ], + ), ), ), Positioned( diff --git a/lib/shared/widgets/custom_drawer_overlay.dart b/lib/shared/widgets/custom_drawer_overlay.dart index c1f35c10..b1f5adfb 100644 --- a/lib/shared/widgets/custom_drawer_overlay.dart +++ b/lib/shared/widgets/custom_drawer_overlay.dart @@ -48,64 +48,88 @@ class CustomDrawerOverlay extends ConsumerWidget { left: isDrawerOpen ? 0 : -MediaQuery.of(context).size.width * 0.7, top: 0, bottom: 0, - child: Container( - width: MediaQuery.of(context).size.width * 0.7, - decoration: BoxDecoration( - color: AppTheme.dark1, - border: Border( - right: BorderSide( - color: Colors.white.withValues(alpha: 0.1), - width: 1.0, + child: GestureDetector( + onHorizontalDragEnd: (details) { + if (details.primaryVelocity != null && + details.primaryVelocity! < 0) { + ref.read(drawerProvider.notifier).closeDrawer(); + } + }, + child: Container( + width: MediaQuery.of(context).size.width * 0.7, + decoration: BoxDecoration( + color: AppTheme.dark1, + border: Border( + right: BorderSide( + color: Colors.white.withValues(alpha: 0.1), + width: 1.0, + ), ), ), - ), - child: Padding( - padding: EdgeInsets.only(top: statusBarHeight + appBarHeight), - child: Column( - children: [ - // Logo header - Container( - height: 80, - padding: const EdgeInsets.symmetric(vertical: 12), - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/logo.png'), - fit: BoxFit.contain, + child: Padding( + padding: EdgeInsets.only(top: statusBarHeight), + child: Column( + children: [ + // Espacio superior para el logo + SizedBox(height: 24), + + // Logo header + Container( + height: 60, + width: double.infinity, + alignment: Alignment.center, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/logo.png'), + fit: BoxFit.contain, + ), ), ), - ), - const Divider(height: 1, color: Colors.transparent), - // Menu items - _buildMenuItem( - context, - ref, - icon: LucideIcons.user, - title: 'Account', - route: '/key_management', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.settings, - title: 'Settings', - route: '/settings', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.info, - title: 'About', - route: '/about', - ), - _buildMenuItem( - context, - ref, - icon: LucideIcons.bookOpen, - title: 'Walkthrough', - route: '/walkthrough', - ), - ], + // Espacio después del logo + SizedBox(height: 24), + + // Línea divisoria + Divider( + height: 1, + thickness: 1, + color: Colors.white.withOpacity(0.1), + ), + + // Espacio después de la línea divisoria + SizedBox(height: 16), + + // Menu items + _buildMenuItem( + context, + ref, + icon: LucideIcons.user, + title: 'Account', + route: '/key_management', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.settings, + title: 'Settings', + route: '/settings', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.info, + title: 'About', + route: '/about', + ), + _buildMenuItem( + context, + ref, + icon: LucideIcons.bookOpen, + title: 'Walkthrough', + route: '/walkthrough', + ), + ], + ), ), ), ), From 41426c6fd3bdf6190ebf7e34050f6c0df4f4a6aa Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Wed, 25 Jun 2025 14:18:23 -0300 Subject: [PATCH 07/11] refactor: reorganize home screen layout and simplify bottom navigation bar --- lib/features/home/screens/home_screen.dart | 136 ++++++++++-------- lib/shared/widgets/bottom_nav_bar.dart | 93 ++++++------ lib/shared/widgets/custom_drawer_overlay.dart | 4 - 3 files changed, 122 insertions(+), 111 deletions(-) diff --git a/lib/features/home/screens/home_screen.dart b/lib/features/home/screens/home_screen.dart index 76ef4e69..d62a52b0 100644 --- a/lib/features/home/screens/home_screen.dart +++ b/lib/features/home/screens/home_screen.dart @@ -24,71 +24,89 @@ class HomeScreen extends ConsumerWidget { body: CustomDrawerOverlay( child: Stack( children: [ - RefreshIndicator( - onRefresh: () async { - return await ref.refresh(filteredOrdersProvider); - }, - child: GestureDetector( - onHorizontalDragEnd: (details) { - // Si el gesto es hacia la izquierda (velocidad negativa), cambiamos a SELL BTC - if (details.primaryVelocity != null && details.primaryVelocity! < 0) { - ref.read(homeOrderTypeProvider.notifier).state = OrderType.buy; - } - // Si el gesto es hacia la derecha (velocidad positiva), cambiamos a BUY BTC - else if (details.primaryVelocity != null && details.primaryVelocity! > 0) { - ref.read(homeOrderTypeProvider.notifier).state = OrderType.sell; - } - }, - child: Column( - children: [ - _buildTabs(ref), - _buildFilterButton(context, ref), - Expanded( - child: Container( - color: const Color(0xFF1D212C), - child: filteredOrders.isEmpty - ? const Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.search_off, - color: Colors.white30, - size: 48, - ), - SizedBox(height: 16), - Text( - 'No orders available', - style: TextStyle( - color: Colors.white60, - fontSize: 16, - ), - ), - Text( - 'Try changing filter settings or check back later', - style: TextStyle( - color: Colors.white38, - fontSize: 14, + // Main content column with bottom navigation + Column( + children: [ + // Content area that expands to fill available space + Expanded( + child: RefreshIndicator( + onRefresh: () async { + return await ref.refresh(filteredOrdersProvider); + }, + child: GestureDetector( + onHorizontalDragEnd: (details) { + // Si el gesto es hacia la izquierda (velocidad negativa), cambiamos a SELL BTC + if (details.primaryVelocity != null && + details.primaryVelocity! < 0) { + ref.read(homeOrderTypeProvider.notifier).state = + OrderType.buy; + } + // Si el gesto es hacia la derecha (velocidad positiva), cambiamos a BUY BTC + else if (details.primaryVelocity != null && + details.primaryVelocity! > 0) { + ref.read(homeOrderTypeProvider.notifier).state = + OrderType.sell; + } + }, + child: Column( + children: [ + _buildTabs(ref), + _buildFilterButton(context, ref), + Expanded( + child: Container( + color: const Color(0xFF1D212C), + child: filteredOrders.isEmpty + ? const Center( + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.search_off, + color: Colors.white30, + size: 48, + ), + SizedBox(height: 16), + Text( + 'No orders available', + style: TextStyle( + color: Colors.white60, + fontSize: 16, + ), + ), + Text( + 'Try changing filter settings or check back later', + style: TextStyle( + color: Colors.white38, + fontSize: 14, + ), + textAlign: TextAlign.center, + ), + ], ), - textAlign: TextAlign.center, + ) + : ListView.builder( + itemCount: filteredOrders.length, + // Adjusted padding to account for bottom nav bar + padding: const EdgeInsets.only( + bottom: 100, top: 6), + itemBuilder: (context, index) { + final order = filteredOrders[index]; + return OrderListItem(order: order); + }, ), - ], - ), - ) - : ListView.builder( - itemCount: filteredOrders.length, - padding: const EdgeInsets.only(bottom: 155, top: 6), - itemBuilder: (context, index) { - final order = filteredOrders[index]; - return OrderListItem(order: order); - }, - ), + ), + ), + ], ), ), - ], + ), ), - ), + // Bottom navigation bar fixed at the bottom + const BottomNavBar(), + ], ), + // Floating action button positioned above bottom nav bar Positioned( bottom: 80 + MediaQuery.of(context).viewPadding.bottom + 16, right: 16, diff --git a/lib/shared/widgets/bottom_nav_bar.dart b/lib/shared/widgets/bottom_nav_bar.dart index 64825d5a..6c133399 100644 --- a/lib/shared/widgets/bottom_nav_bar.dart +++ b/lib/shared/widgets/bottom_nav_bar.dart @@ -70,58 +70,55 @@ class BottomNavBar extends ConsumerWidget { Color textColor = isActive ? AppTheme.activeColor : Colors.white; return Expanded( - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => _onItemTapped(context, index), - child: SizedBox( - height: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 2), - SizedBox( - height: 24, - width: 24, - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Icon( - icon, - color: iconColor, - size: 24, - ), - if (notificationCount != null && notificationCount > 0) - Positioned( - top: -2, - right: -2, - child: Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, - ), + child: GestureDetector( + onTap: () => _onItemTapped(context, index), + child: SizedBox( + height: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 2), + SizedBox( + height: 24, + width: 24, + child: Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Icon( + icon, + color: iconColor, + size: 24, + ), + if (notificationCount != null && notificationCount > 0) + Positioned( + top: -2, + right: -2, + child: Container( + width: 6, + height: 6, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, ), ), - ], - ), + ), + ], ), - const SizedBox(height: 4), - Text( - label, - style: GoogleFonts.inter( - fontSize: 12, - fontWeight: FontWeight.w400, - color: textColor, - height: 1.0, - letterSpacing: -0.2, - ), + ), + const SizedBox(height: 4), + Text( + label, + style: GoogleFonts.inter( + fontSize: 12, + fontWeight: FontWeight.w400, + color: textColor, + height: 1.0, + letterSpacing: -0.2, ), - const SizedBox(height: 2), - ], - ), + ), + const SizedBox(height: 2), + ], ), ), ), diff --git a/lib/shared/widgets/custom_drawer_overlay.dart b/lib/shared/widgets/custom_drawer_overlay.dart index b1f5adfb..fe09dfb6 100644 --- a/lib/shared/widgets/custom_drawer_overlay.dart +++ b/lib/shared/widgets/custom_drawer_overlay.dart @@ -70,7 +70,6 @@ class CustomDrawerOverlay extends ConsumerWidget { padding: EdgeInsets.only(top: statusBarHeight), child: Column( children: [ - // Espacio superior para el logo SizedBox(height: 24), // Logo header @@ -86,17 +85,14 @@ class CustomDrawerOverlay extends ConsumerWidget { ), ), - // Espacio después del logo SizedBox(height: 24), - // Línea divisoria Divider( height: 1, thickness: 1, color: Colors.white.withOpacity(0.1), ), - // Espacio después de la línea divisoria SizedBox(height: 16), // Menu items From d0c62729eb418a7b28af565b39b79e0fd036ab4d Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Wed, 25 Jun 2025 14:29:49 -0300 Subject: [PATCH 08/11] feat: wrap trades screen with CustomDrawerOverlay and remove standalone drawer --- lib/features/trades/screens/trades_screen.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/features/trades/screens/trades_screen.dart b/lib/features/trades/screens/trades_screen.dart index 92f79075..f918d7e2 100644 --- a/lib/features/trades/screens/trades_screen.dart +++ b/lib/features/trades/screens/trades_screen.dart @@ -21,8 +21,8 @@ class TradesScreen extends ConsumerWidget { backgroundColor: AppTheme.backgroundDark, appBar: const MostroAppBar(), - drawer: const MostroAppDrawer(), - body: RefreshIndicator( + body: CustomDrawerOverlay( + child: RefreshIndicator( onRefresh: () async { // Force reload the orders repository first ref.read(orderRepositoryProvider).reloadData(); @@ -114,6 +114,7 @@ class TradesScreen extends ConsumerWidget { ), ), + ), ); } From 0571683304c8477d8ff51bf258463e5a64b23d45 Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Wed, 25 Jun 2025 14:54:43 -0300 Subject: [PATCH 09/11] refactor: improve accessibility and remove unused code in trades screen and bottom nav bar --- .../trades/screens/trades_screen.dart | 164 +++++++++--------- lib/shared/widgets/bottom_nav_bar.dart | 136 ++++++++------- 2 files changed, 150 insertions(+), 150 deletions(-) diff --git a/lib/features/trades/screens/trades_screen.dart b/lib/features/trades/screens/trades_screen.dart index f918d7e2..38eea5a7 100644 --- a/lib/features/trades/screens/trades_screen.dart +++ b/lib/features/trades/screens/trades_screen.dart @@ -20,106 +20,102 @@ class TradesScreen extends ConsumerWidget { return Scaffold( backgroundColor: AppTheme.backgroundDark, appBar: const MostroAppBar(), - body: CustomDrawerOverlay( child: RefreshIndicator( - onRefresh: () async { - // Force reload the orders repository first - ref.read(orderRepositoryProvider).reloadData(); - // Then refresh the filtered trades provider - ref.invalidate(filteredTradesProvider); - }, - child: Column( - children: [ - Expanded( - child: Column( - children: [ - // Header with dark background - Container( - width: double.infinity, - padding: const EdgeInsets.all(16.0), - decoration: BoxDecoration( - color: AppTheme.backgroundDark, - border: Border( - bottom: BorderSide(color: Colors.white24, width: 0.5), + onRefresh: () async { + // Force reload the orders repository first + ref.read(orderRepositoryProvider).reloadData(); + // Then refresh the filtered trades provider + ref.invalidate(filteredTradesProvider); + }, + child: Column( + children: [ + Expanded( + child: Column( + children: [ + // Header with dark background + Container( + width: double.infinity, + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + color: AppTheme.backgroundDark, + border: Border( + bottom: BorderSide(color: Colors.white24, width: 0.5), + ), ), - ), - child: const Text( - 'My Active Trades', - style: TextStyle( - color: Colors.white, - fontSize: 20, - fontWeight: FontWeight.bold, + child: const Text( + 'My Active Trades', + style: TextStyle( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.bold, + ), ), ), - ), - // Content area with dark background - Expanded( - child: Container( - decoration: const BoxDecoration( - color: AppTheme.backgroundDark, - ), - child: Column( - children: [ - // Espacio superior - const SizedBox(height: 16.0), - Expanded( - child: tradesAsync.when( - data: (trades) => _buildOrderList(trades), - loading: () => const Center( - child: CircularProgressIndicator(), - ), - error: (error, _) => Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.error_outline, - color: Colors.red, - size: 60, - ), - const SizedBox(height: 16), - Text( - 'Error loading trades', - style: TextStyle(color: AppTheme.cream1), - ), - Text( - error.toString(), - style: TextStyle( - color: AppTheme.cream1, fontSize: 12), - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - ElevatedButton( - onPressed: () { - ref.invalidate(orderEventsProvider); - ref.invalidate(filteredTradesProvider); - }, - child: const Text('Retry'), - ), - ], + // Content area with dark background + Expanded( + child: Container( + decoration: const BoxDecoration( + color: AppTheme.backgroundDark, + ), + child: Column( + children: [ + // Espacio superior + const SizedBox(height: 16.0), + Expanded( + child: tradesAsync.when( + data: (trades) => _buildOrderList(trades), + loading: () => const Center( + child: CircularProgressIndicator(), + ), + error: (error, _) => Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + const SizedBox(height: 16), + Text( + 'Error loading trades', + style: TextStyle(color: AppTheme.cream1), + ), + Text( + error.toString(), + style: TextStyle( + color: AppTheme.cream1, fontSize: 12), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + ref.invalidate(orderEventsProvider); + ref.invalidate(filteredTradesProvider); + }, + child: const Text('Retry'), + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - const BottomNavBar(), - ], - + const BottomNavBar(), + ], + ), ), ), - ), ); } - // Función eliminada: _buildFilterButton - Widget _buildOrderList(List trades) { if (trades.isEmpty) { return const Center( diff --git a/lib/shared/widgets/bottom_nav_bar.dart b/lib/shared/widgets/bottom_nav_bar.dart index 6c133399..11dd8fd3 100644 --- a/lib/shared/widgets/bottom_nav_bar.dart +++ b/lib/shared/widgets/bottom_nav_bar.dart @@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:mostro_mobile/core/app_theme.dart'; -import 'package:google_fonts/google_fonts.dart'; final chatCountProvider = StateProvider((ref) => 0); final orderBookNotificationCountProvider = StateProvider((ref) => 0); @@ -35,26 +34,26 @@ class BottomNavBar extends ConsumerWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - _buildNavItem( - context, - LucideIcons.book, - 'Order Book', - 0, - ), - _buildNavItem( - context, - LucideIcons.zap, - 'My Trades', - 1, - notificationCount: orderNotificationCount, - ), - _buildNavItem( - context, - LucideIcons.messageSquare, - 'Chat', - 2, - notificationCount: chatCount, - ), + _buildNavItem( + context, + LucideIcons.book, + 'Order Book', + 0, + ), + _buildNavItem( + context, + LucideIcons.zap, + 'My Trades', + 1, + notificationCount: orderNotificationCount, + ), + _buildNavItem( + context, + LucideIcons.messageSquare, + 'Chat', + 2, + notificationCount: chatCount, + ), ], ), ), @@ -70,55 +69,60 @@ class BottomNavBar extends ConsumerWidget { Color textColor = isActive ? AppTheme.activeColor : Colors.white; return Expanded( - child: GestureDetector( - onTap: () => _onItemTapped(context, index), - child: SizedBox( - height: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 2), - SizedBox( - height: 24, - width: 24, - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Icon( - icon, - color: iconColor, - size: 24, - ), - if (notificationCount != null && notificationCount > 0) - Positioned( - top: -2, - right: -2, - child: Container( - width: 6, - height: 6, - decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, + child: Semantics( + button: true, + enabled: true, + label: 'Navigate to $label', + child: GestureDetector( + onTap: () => _onItemTapped(context, index), + child: SizedBox( + height: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 2), + SizedBox( + height: 24, + width: 24, + child: Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Icon( + icon, + color: iconColor, + size: 24, + ), + if (notificationCount != null && notificationCount > 0) + Positioned( + top: -2, + right: -2, + child: Container( + width: 6, + height: 6, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), ), ), - ), - ], + ], + ), ), - ), - const SizedBox(height: 4), - Text( - label, - style: GoogleFonts.inter( - fontSize: 12, - fontWeight: FontWeight.w400, - color: textColor, - height: 1.0, - letterSpacing: -0.2, + const SizedBox(height: 4), + Text( + label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: textColor, + height: 1.0, + letterSpacing: -0.2, + ), ), - ), - const SizedBox(height: 2), - ], + const SizedBox(height: 2), + ], + ), ), ), ), From ea91c380e3116e8f7e3a9adfe7fff171f9316e7c Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Wed, 25 Jun 2025 14:57:22 -0300 Subject: [PATCH 10/11] refactor: remove comments and improve code formatting in home and trades screens --- lib/features/home/screens/home_screen.dart | 6 +----- lib/features/trades/screens/trades_screen.dart | 10 ++++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/features/home/screens/home_screen.dart b/lib/features/home/screens/home_screen.dart index d62a52b0..349a4339 100644 --- a/lib/features/home/screens/home_screen.dart +++ b/lib/features/home/screens/home_screen.dart @@ -35,14 +35,11 @@ class HomeScreen extends ConsumerWidget { }, child: GestureDetector( onHorizontalDragEnd: (details) { - // Si el gesto es hacia la izquierda (velocidad negativa), cambiamos a SELL BTC if (details.primaryVelocity != null && details.primaryVelocity! < 0) { ref.read(homeOrderTypeProvider.notifier).state = OrderType.buy; - } - // Si el gesto es hacia la derecha (velocidad positiva), cambiamos a BUY BTC - else if (details.primaryVelocity != null && + } else if (details.primaryVelocity != null && details.primaryVelocity! > 0) { ref.read(homeOrderTypeProvider.notifier).state = OrderType.sell; @@ -87,7 +84,6 @@ class HomeScreen extends ConsumerWidget { ) : ListView.builder( itemCount: filteredOrders.length, - // Adjusted padding to account for bottom nav bar padding: const EdgeInsets.only( bottom: 100, top: 6), itemBuilder: (context, index) { diff --git a/lib/features/trades/screens/trades_screen.dart b/lib/features/trades/screens/trades_screen.dart index 38eea5a7..723f8614 100644 --- a/lib/features/trades/screens/trades_screen.dart +++ b/lib/features/trades/screens/trades_screen.dart @@ -60,7 +60,6 @@ class TradesScreen extends ConsumerWidget { ), child: Column( children: [ - // Espacio superior const SizedBox(height: 16.0), Expanded( child: tradesAsync.when( @@ -80,19 +79,22 @@ class TradesScreen extends ConsumerWidget { const SizedBox(height: 16), Text( 'Error loading trades', - style: TextStyle(color: AppTheme.cream1), + style: + TextStyle(color: AppTheme.cream1), ), Text( error.toString(), style: TextStyle( - color: AppTheme.cream1, fontSize: 12), + color: AppTheme.cream1, + fontSize: 12), textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton( onPressed: () { ref.invalidate(orderEventsProvider); - ref.invalidate(filteredTradesProvider); + ref.invalidate( + filteredTradesProvider); }, child: const Text('Retry'), ), From 0103e66b2e1dedd29726128bc86cbc8be4391a0f Mon Sep 17 00:00:00 2001 From: Andrea Diaz Correia Date: Mon, 30 Jun 2025 14:52:30 -0300 Subject: [PATCH 11/11] fix: add bottom safe area to navigation bar for proper padding --- lib/shared/widgets/bottom_nav_bar.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/shared/widgets/bottom_nav_bar.dart b/lib/shared/widgets/bottom_nav_bar.dart index 11dd8fd3..1a8f6cc3 100644 --- a/lib/shared/widgets/bottom_nav_bar.dart +++ b/lib/shared/widgets/bottom_nav_bar.dart @@ -19,6 +19,7 @@ class BottomNavBar extends ConsumerWidget { return SafeArea( top: false, + bottom: true, child: Container( width: double.infinity, height: 80,