diff --git a/sojorn_app/lib/routes/app_routes.dart b/sojorn_app/lib/routes/app_routes.dart index 3aff63e..7c2837d 100644 --- a/sojorn_app/lib/routes/app_routes.dart +++ b/sojorn_app/lib/routes/app_routes.dart @@ -21,7 +21,6 @@ import '../screens/discover/discover_screen.dart'; import '../screens/secure_chat/secure_chat_full_screen.dart'; import '../screens/secure_chat/secure_chat_loader_screen.dart'; import '../screens/post/threaded_conversation_screen.dart'; -import '../screens/notifications/notifications_screen.dart'; /// App routing config (GoRouter). class AppRoutes { @@ -89,7 +88,6 @@ class AppRoutes { authenticatedChild: HomeShell(navigationShell: navigationShell), ), branches: [ - // Tab 0: Home StatefulShellBranch( routes: [ GoRoute( @@ -98,25 +96,25 @@ class AppRoutes { ), ], ), - // Tab 1: Search / Discover StatefulShellBranch( routes: [ GoRoute( - path: '/discover', - builder: (_, __) => const DiscoverScreen(), + path: quips, + builder: (_, state) => QuipsFeedScreen( + initialPostId: state.uri.queryParameters['postId'], + ), ), + ], ), - // Tab 2: Activity / Notifications StatefulShellBranch( routes: [ GoRoute( - path: '/activity', - builder: (_, __) => const NotificationsScreen(), + path: '/beacon', + builder: (_, __) => const BeaconScreen(), ), ], ), - // Tab 3: Profile StatefulShellBranch( routes: [ GoRoute( diff --git a/sojorn_app/lib/screens/home/home_shell.dart b/sojorn_app/lib/screens/home/home_shell.dart index baf107f..e7030f4 100644 --- a/sojorn_app/lib/screens/home/home_shell.dart +++ b/sojorn_app/lib/screens/home/home_shell.dart @@ -206,14 +206,17 @@ class _HomeShellState extends ConsumerState with WidgetsBindingObserv label: 'Home', ), _buildNavBarItem( - icon: Icons.search_outlined, - activeIcon: Icons.search, + icon: Icons.play_circle_outline, + activeIcon: Icons.play_circle, index: 1, - label: 'Search', + label: 'Quips', ), const SizedBox(width: 48), - _buildActivityNavItem( + _buildNavBarItem( + icon: Icons.sensors_outlined, + activeIcon: Icons.sensors, index: 2, + label: 'Beacon', ), _buildNavBarItem( icon: Icons.person_outline, @@ -250,6 +253,17 @@ class _HomeShellState extends ConsumerState with WidgetsBindingObserv ), ), actions: [ + IconButton( + icon: Icon(Icons.search, color: AppTheme.navyBlue), + tooltip: 'Discover', + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => const DiscoverScreen(), + ), + ); + }, + ), IconButton( icon: Consumer( builder: (context, ref, child) { @@ -272,6 +286,27 @@ class _HomeShellState extends ConsumerState with WidgetsBindingObserv ); }, ), + IconButton( + icon: Consumer( + builder: (context, ref, child) { + final badge = ref.watch(currentBadgeProvider); + return Badge( + label: Text(badge.notificationCount.toString()), + isLabelVisible: badge.notificationCount > 0, + backgroundColor: Colors.redAccent, + child: Icon(Icons.notifications_none, color: AppTheme.navyBlue), + ); + }, + ), + tooltip: 'Notifications', + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => const NotificationsScreen(), + ), + ); + }, + ), const SizedBox(width: 4), ], ); @@ -302,37 +337,6 @@ class _HomeShellState extends ConsumerState with WidgetsBindingObserv ), ); } - - Widget _buildActivityNavItem({required int index}) { - final isActive = widget.navigationShell.currentIndex == index; - return Expanded( - child: InkWell( - onTap: () => widget.navigationShell.goBranch( - index, - initialLocation: index == widget.navigationShell.currentIndex, - ), - child: Container( - height: double.infinity, - alignment: Alignment.center, - child: Consumer( - builder: (context, ref, child) { - final badge = ref.watch(currentBadgeProvider); - return Badge( - label: Text(badge.notificationCount.toString()), - isLabelVisible: badge.notificationCount > 0, - backgroundColor: Colors.redAccent, - child: Icon( - isActive ? Icons.favorite : Icons.favorite_border, - color: isActive ? AppTheme.navyBlue : Colors.grey, - size: 26, - ), - ); - }, - ), - ), - ), - ); - } } class _VerticalBorderProgressPainter extends CustomPainter { diff --git a/sojorn_app/lib/screens/notifications/notifications_screen.dart b/sojorn_app/lib/screens/notifications/notifications_screen.dart index f1c17d7..9fe45bd 100644 --- a/sojorn_app/lib/screens/notifications/notifications_screen.dart +++ b/sojorn_app/lib/screens/notifications/notifications_screen.dart @@ -6,9 +6,13 @@ import 'package:timeago/timeago.dart' as timeago; import '../../models/notification.dart'; import '../../providers/api_provider.dart'; import '../../theme/app_theme.dart'; +import '../../widgets/app_scaffold.dart'; import '../../widgets/media/signed_media_image.dart'; import '../profile/viewable_profile_screen.dart'; import '../post/post_detail_screen.dart'; +import '../search/search_screen.dart'; +import '../discover/discover_screen.dart'; +import '../secure_chat/secure_chat_full_screen.dart'; import 'package:go_router/go_router.dart'; import '../../services/notification_service.dart'; @@ -348,59 +352,66 @@ class _NotificationsScreenState extends ConsumerState { } } + void _navigateHome() { + Navigator.of(context).pop(); + } + + void _navigateSearch() { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (_) => const DiscoverScreen()), + ); + } + + void _navigateChat() { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (_) => const SecureChatFullScreen(), + fullscreenDialog: true, + ), + ); + } + @override Widget build(BuildContext context) { final canArchiveAll = _activeTabIndex == 0 && _notifications.isNotEmpty; return DefaultTabController( length: 2, - child: Column( - children: [ - // Tab bar + Archive All button - Material( - color: AppTheme.scaffoldBg, - child: Column( - children: [ - if (canArchiveAll) - Align( - alignment: Alignment.centerRight, - child: Padding( - padding: const EdgeInsets.only(right: 8, top: 4), - child: TextButton( - onPressed: _archiveAllNotifications, - child: Text( - 'Archive All', - style: AppTheme.textTheme.labelMedium?.copyWith( - color: AppTheme.egyptianBlue, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ), - TabBar( - onTap: (index) { - if (index != _activeTabIndex) { - setState(() { - _activeTabIndex = index; - }); - _loadNotifications(refresh: true); - } - }, - indicatorColor: AppTheme.egyptianBlue, - labelColor: AppTheme.egyptianBlue, - unselectedLabelColor: AppTheme.egyptianBlue.withOpacity(0.5), - tabs: const [ - Tab(text: 'Active'), - Tab(text: 'Archived'), - ], + child: AppScaffold( + title: 'Activity', + leading: const SizedBox.shrink(), + actions: [ + if (canArchiveAll) + TextButton( + onPressed: _archiveAllNotifications, + child: Text( + 'Archive All', + style: AppTheme.textTheme.labelMedium?.copyWith( + color: AppTheme.egyptianBlue, + fontWeight: FontWeight.w600, ), - ], + ), ), - ), - // Content - Expanded( - child: _error != null + ], + bottom: TabBar( + onTap: (index) { + if (index != _activeTabIndex) { + setState(() { + _activeTabIndex = index; + }); + _loadNotifications(refresh: true); + } + }, + indicatorColor: AppTheme.egyptianBlue, + labelColor: AppTheme.egyptianBlue, + unselectedLabelColor: AppTheme.egyptianBlue.withOpacity(0.5), + tabs: const [ + Tab(text: 'Active'), + Tab(text: 'Archived'), + ], + ), + bottomNavigationBar: _buildBottomNav(), + body: _error != null ? _ErrorState( message: _error!, onRetry: () => _loadNotifications(refresh: true), @@ -474,8 +485,86 @@ class _NotificationsScreenState extends ConsumerState { }, ), ), + ), + ); + } + + Widget _buildBottomNav() { + return Container( + decoration: BoxDecoration( + color: AppTheme.scaffoldBg, + border: Border( + top: BorderSide( + color: AppTheme.egyptianBlue.withOpacity(0.1), + width: 0.5, ), - ], + ), + ), + child: SafeArea( + top: false, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildNavItem( + icon: Icons.home_outlined, + label: 'Home', + onTap: _navigateHome, + ), + _buildNavItem( + icon: Icons.search, + label: 'Discover', + onTap: _navigateSearch, + ), + _buildNavItem( + icon: Icons.notifications, + label: 'Activity', + isActive: true, + onTap: () {}, + ), + _buildNavItem( + icon: Icons.chat_bubble_outline, + label: 'Chat', + onTap: _navigateChat, + ), + ], + ), + ), + ), + ); + } + + Widget _buildNavItem({ + required IconData icon, + required String label, + required VoidCallback onTap, + bool isActive = false, + }) { + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + icon, + color: isActive ? AppTheme.navyBlue : Colors.grey, + size: 26, + ), + const SizedBox(height: 2), + Text( + label, + style: TextStyle( + fontSize: 10, + color: isActive ? AppTheme.navyBlue : Colors.grey, + fontWeight: isActive ? FontWeight.w600 : FontWeight.normal, + ), + ), + ], + ), ), ); }