Files
kent_logistics_app/lib/screens/main_bottom_nav.dart

241 lines
8.9 KiB
Dart
Raw Permalink Normal View History

2025-12-03 11:57:05 +05:30
import 'package:flutter/material.dart';
import '../widgets/main_app_bar.dart';
import 'dashboard_screen.dart';
import 'order_screen.dart';
import 'invoice_screen.dart';
import 'chat_screen.dart';
import 'settings_screen.dart';
2025-12-15 11:10:52 +05:30
import 'package:provider/provider.dart';
import '../providers/chat_unread_provider.dart';
2025-12-03 11:57:05 +05:30
class MainBottomNav extends StatefulWidget {
const MainBottomNav({super.key});
@override
State<MainBottomNav> createState() => MainBottomNavState();
}
class MainBottomNavState extends State<MainBottomNav> {
int _currentIndex = 0;
void setIndex(int index) {
2025-12-11 18:36:11 +05:30
setState(() => _currentIndex = index);
2025-12-03 11:57:05 +05:30
}
2025-12-15 11:10:52 +05:30
final List<Widget> _screens = [
2025-12-03 11:57:05 +05:30
DashboardScreen(),
OrdersScreen(),
InvoiceScreen(),
ChatScreen(),
SettingsScreen(),
];
2025-12-11 18:36:11 +05:30
final List<IconData> _icons = const [
Icons.dashboard_outlined,
Icons.shopping_bag_outlined,
Icons.receipt_long_outlined,
Icons.chat_bubble_outline,
Icons.settings_outlined,
];
final List<String> _labels = const [
"Dashboard",
"Orders",
"Invoice",
"Chat",
"Settings",
];
2025-12-03 11:57:05 +05:30
@override
Widget build(BuildContext context) {
2025-12-11 18:36:11 +05:30
final width = MediaQuery.of(context).size.width;
final scale = (width / 390).clamp(0.85, 1.20);
final containerPadding = 8 * scale;
2025-12-03 11:57:05 +05:30
return Scaffold(
appBar: const MainAppBar(),
body: _screens[_currentIndex],
2025-12-11 18:36:11 +05:30
bottomNavigationBar: Padding(
padding: EdgeInsets.only(
left: 10 * scale,
right: 10 * scale,
bottom: 10 * scale,
),
child: LayoutBuilder(
builder: (context, constraints) {
final totalWidth = constraints.maxWidth;
// inner width (after padding)
final contentWidth = totalWidth - (containerPadding * 2);
final safeContentWidth =
contentWidth > 0 ? contentWidth : totalWidth;
final itemWidth = safeContentWidth / _icons.length;
final indicatorWidth = 70 * scale;
final indicatorHeight = 70 * scale;
double left = (_currentIndex * itemWidth) +
(itemWidth / 2) -
(indicatorWidth / 2);
/// ⭐ FIX: explicitly convert clamp to double
final double safeLeft = left
.clamp(0, safeContentWidth - indicatorWidth)
.toDouble();
return Container(
height: 100 * scale,
padding: EdgeInsets.symmetric(horizontal: containerPadding),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(28 * scale),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 20 * scale,
offset: Offset(0, 8 * scale),
)
],
),
child: Stack(
children: [
/// ⭐ Indicator - safe positioned
AnimatedPositioned(
duration: const Duration(milliseconds: 350),
curve: Curves.easeOut,
top: 10 * scale,
left: safeLeft,
child: Container(
width: indicatorWidth,
height: indicatorHeight,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [
Color(0xFF4F46E5),
Color(0xFF06B6D4),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20 * scale),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
_icons[_currentIndex],
size: 22 * scale,
color: Colors.white,
),
SizedBox(height: 2 * scale),
Text(
_labels[_currentIndex],
style: TextStyle(
fontSize: 10 * scale,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
),
),
/// ⭐ Icon Row
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(_icons.length, (index) {
final selected = index == _currentIndex;
return GestureDetector(
onTap: () => setIndex(index),
child: SizedBox(
width: itemWidth,
height: 100 * scale,
child: Center(
child: AnimatedOpacity(
duration: const Duration(milliseconds: 250),
opacity: selected ? 0 : 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
2025-12-15 11:10:52 +05:30
index == 3
? Consumer<ChatUnreadProvider>(
builder: (_, chat, __) {
return Stack(
clipBehavior: Clip.none,
children: [
Icon(
_icons[index],
size: 22 * scale,
color: Colors.black87,
),
if (chat.unreadCount > 0)
Positioned(
right: -6,
top: -6,
child: Container(
padding: const EdgeInsets.all(4),
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
constraints: const BoxConstraints(
minWidth: 20,
minHeight: 20,
),
child: Center(
child: Text(
chat.unreadCount.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
);
},
)
: Icon(
2025-12-11 18:36:11 +05:30
_icons[index],
size: 22 * scale,
color: Colors.black87,
),
2025-12-15 11:10:52 +05:30
2025-12-11 18:36:11 +05:30
SizedBox(height: 4 * scale),
Text(
_labels[index],
style: TextStyle(
fontSize: 10 * scale,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
],
),
),
),
),
);
}),
),
],
),
);
},
),
2025-12-03 11:57:05 +05:30
),
);
}
}