You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
basedFood-app/lib/ui/navigation/main_navigation_scaffold.dart

296 lines
9.0 KiB

// ignore_for_file: deprecated_member_use, duplicate_ignore
import 'package:flutter/material.dart';
import '../../core/service_locator.dart';
import '../home/home_screen.dart';
import '../recipes/recipes_screen.dart';
import '../favourites/favourites_screen.dart';
import '../session/session_screen.dart';
import 'app_router.dart';
/// Main navigation scaffold with bottom navigation bar and centered Add button.
class MainNavigationScaffold extends StatefulWidget {
const MainNavigationScaffold({super.key});
@override
State<MainNavigationScaffold> createState() => _MainNavigationScaffoldState();
}
class _MainNavigationScaffoldState extends State<MainNavigationScaffold> {
int _currentIndex = 0;
bool _wasLoggedIn = false;
bool get _isLoggedIn => ServiceLocator.instance.sessionService?.isLoggedIn ?? false;
@override
void initState() {
super.initState();
_wasLoggedIn = _isLoggedIn;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Check if login state changed and rebuild if needed
_checkLoginState();
}
void _checkLoginState() {
final isLoggedIn = _isLoggedIn;
if (isLoggedIn != _wasLoggedIn) {
_wasLoggedIn = isLoggedIn;
// Rebuild after a short delay to ensure state is fully updated
Future.delayed(const Duration(milliseconds: 100), () {
if (mounted) {
setState(() {
// Trigger rebuild to update navigation bar
});
}
});
}
}
void _onSessionChanged() {
// Called when login/logout happens - rebuild immediately
if (mounted) {
setState(() {
_wasLoggedIn = _isLoggedIn;
});
// Also check after a short delay to catch any async state changes
Future.delayed(const Duration(milliseconds: 200), () {
if (mounted) {
setState(() {
_wasLoggedIn = _isLoggedIn;
});
}
});
}
}
void _onItemTapped(int index) {
final isLoggedIn = _isLoggedIn;
// Only allow navigation to Recipes (1) and Favourites (2) if logged in
if (!isLoggedIn && (index == 1 || index == 2)) {
// Redirect to User/Session tab to prompt login
setState(() {
_currentIndex = 3; // User/Session tab
});
return;
}
setState(() {
_currentIndex = index;
});
}
void _onAddRecipePressed(BuildContext context) async {
final isLoggedIn = _isLoggedIn;
// Only allow adding recipes if logged in
if (!isLoggedIn) {
// Redirect to User/Session tab to prompt login
setState(() {
_currentIndex = 3; // User/Session tab
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please log in to add recipes'),
duration: Duration(seconds: 2),
),
);
return;
}
// Navigate to Add Recipe screen and reload recipes when returning
final result = await Navigator.pushNamed(context, AppRoutes.addRecipe);
// If recipe was saved, result will be true
// Switch to Recipes tab to show the new recipe
if (result == true) {
setState(() {
_currentIndex = 1; // Switch to Recipes tab
});
}
}
Widget _buildScreen(int index) {
switch (index) {
case 0:
return const HomeScreen();
case 1:
// Recipes - only show if logged in, otherwise show login prompt
// Use a key based on login state to force rebuild when login changes
return RecipesScreen(
key: _isLoggedIn
? const ValueKey('recipes_logged_in')
: const ValueKey('recipes_logged_out'),
);
case 2:
// Favourites - only show if logged in, otherwise show login prompt
// Use a key based on login state to force rebuild when login changes
return FavouritesScreen(key: ValueKey(_isLoggedIn));
case 3:
return SessionScreen(onSessionChanged: _onSessionChanged);
default:
return const SizedBox();
}
}
@override
Widget build(BuildContext context) {
// Rebuild when login state changes by checking it in build
final isLoggedIn = _isLoggedIn;
// Check login state in build to trigger rebuilds
_checkLoginState();
// Ensure current index is valid (if logged out, don't allow Recipes/Favourites)
if (!isLoggedIn && (_currentIndex == 1 || _currentIndex == 2)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
_currentIndex = 0; // Switch to Home if trying to access protected tabs
});
}
});
}
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: List.generate(4, (index) => _buildScreen(index)),
),
bottomNavigationBar: _buildCustomBottomNav(context),
);
}
Widget _buildCustomBottomNav(BuildContext context) {
final isLoggedIn = _isLoggedIn;
return Container(
decoration: BoxDecoration(
color: Theme.of(context).bottomNavigationBarTheme.backgroundColor ??
Theme.of(context).scaffoldBackgroundColor,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, -2),
),
],
),
child: SafeArea(
child: Container(
height: kBottomNavigationBarHeight,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// Home
_buildNavItem(
icon: Icons.home,
label: 'Home',
index: 0,
onTap: () => _onItemTapped(0),
),
// Recipes - only show if logged in
if (isLoggedIn)
_buildNavItem(
icon: Icons.menu_book,
label: 'Recipes',
index: 1,
onTap: () => _onItemTapped(1),
),
// Center Add Recipe button - only show if logged in
if (isLoggedIn)
Container(
width: 56,
height: 56,
margin: const EdgeInsets.only(bottom: 8),
child: Material(
color: Theme.of(context).primaryColor,
shape: const CircleBorder(),
child: InkWell(
onTap: () => _onAddRecipePressed(context),
customBorder: const CircleBorder(),
child: const Icon(
Icons.add,
color: Colors.white,
size: 28,
),
),
),
),
// Favourites - only show if logged in
if (isLoggedIn)
_buildNavItem(
icon: Icons.favorite,
label: 'Favourites',
index: 2,
onTap: () => _onItemTapped(2),
),
// User
_buildNavItem(
icon: Icons.person,
label: 'User',
index: 3,
onTap: () => _onItemTapped(3),
),
],
),
),
),
);
}
Widget _buildNavItem({
required IconData icon,
required String label,
required int index,
required VoidCallback onTap,
}) {
final isSelected = _currentIndex == index;
return Expanded(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: isSelected
? (Theme.of(context).brightness == Brightness.dark
? Colors.blue.shade300 // Lighter blue for dark mode
: Theme.of(context).primaryColor)
: Theme.of(context).iconTheme.color?.withOpacity(0.6),
size: 24,
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
fontSize: 12,
color: isSelected
? (Theme.of(context).brightness == Brightness.dark
? Colors.blue.shade300 // Lighter blue for dark mode
: Theme.of(context).primaryColor)
// ignore: deprecated_member_use
: Theme.of(context)
.textTheme
.bodySmall
?.color
?.withOpacity(0.6),
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
],
),
),
),
);
}
}

Powered by TurnKey Linux.