import 'dart:ui'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:lottie/lottie.dart'; import 'package:nearledaily/view/qr_scaner/qr_scaner.dart'; import '../constants/font_constants.dart'; import '../controllers/cart_controller/cart.dart'; import '../widgets/text_widget.dart'; import 'account/account_view.dart'; import 'cart/cart_view.dart'; import 'dashboard_view/dashboard_view.dart'; import 'orders/orders_by_tenant.dart'; // ─── Colors ─────────────────────────────────────────────────────────────────── const Color _kPrimary = Color(0xFFDE9BFB); const Color _kActive = Colors.white; const Color _kInactive = Color(0xFFCBA8E4); // ─── Screens ────────────────────────────────────────────────────────────────── final List _screens = [ DashboardPage(), const OrdersByStoreScreen(showBackArrow: false), QrScannerPage(), CartPage(), AccountPage(), ]; // ─── Controller ─────────────────────────────────────────────────────────────── class BottomNavController extends GetxController { var isRetrying = false.obs; var currentIndex = 0.obs; var isConnected = true.obs; @override void onInit() { super.onInit(); checkConnection(); Connectivity().onConnectivityChanged.listen((status) async { isConnected.value = status == ConnectivityResult.none ? false : await hasInternet(); }); } Future checkConnection() async { final r = await Connectivity().checkConnectivity(); isConnected.value = r == ConnectivityResult.none ? false : await hasInternet(); } Future hasInternet() async { try { final res = await http .get(Uri.parse('https://www.google.com')) .timeout(const Duration(seconds: 5)); return res.statusCode == 200; } catch (_) { return false; } } } // ─── Root Widget ────────────────────────────────────────────────────────────── class BottomNavigation extends StatelessWidget { final BottomNavController controller = Get.put(BottomNavController()); final CartController cartController = Get.put(CartController()); BottomNavigation({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Obx(() { if (!controller.isConnected.value) { return Scaffold( backgroundColor: const Color(0xFFF3E8FF), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Lottie.asset('assets/lotties/no_internet.json', width: 200, height: 200, fit: BoxFit.contain), const SizedBox(height: 16), ReusableTextWidget( text: 'No Internet Connection', color: Colors.grey, fontFamily: FontConstants.fontFamily, fontSize: 18, fontWeight: FontWeight.bold, overflow: TextOverflow.ellipsis, maxLines: 1, ), const SizedBox(height: 15), Obx(() => ElevatedButton( onPressed: controller.isRetrying.value ? null : () async { controller.isRetrying.value = true; controller.isConnected.value = await controller.hasInternet(); await Future.delayed( const Duration(milliseconds: 800)); controller.isRetrying.value = false; }, style: ElevatedButton.styleFrom( backgroundColor: _kPrimary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric( horizontal: 30, vertical: 12), ), child: controller.isRetrying.value ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2)) : const Text('Retry', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold)), )), ], ), ), ); } return Scaffold( backgroundColor: Colors.white, extendBody: true, bottomNavigationBar: Obx( () => _BottomNavBar( currentIndex: controller.currentIndex.value, cartController: cartController, onTap: (i) => controller.currentIndex.value = i, ), ), body: Obx( () => _screens[controller.currentIndex.value], ), ); }); } } // ─── Bottom Nav Bar (matches image exactly) ─────────────────────────────────── class _BottomNavBar extends StatelessWidget { final int currentIndex; final CartController cartController; final ValueChanged onTap; const _BottomNavBar({ required this.currentIndex, required this.cartController, required this.onTap, }); @override Widget build(BuildContext context) { final double bottomPad = MediaQuery.of(context).padding.bottom; return Container( decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF662582), Color(0xFF662582), Color(0xFF662582), ], stops: [0.0, 0.5, 1.0], ), // borderRadius: const BorderRadius.vertical( // top: Radius.circular(32), // ), ), padding: EdgeInsets.fromLTRB(12, 12, 12, bottomPad + 10), child: _GlassPill( currentIndex: currentIndex, cartController: cartController, onTap: onTap, ), ); } } // ─── Glass Pill ─────────────────────────────────────────────────────────────── class _GlassPill extends StatelessWidget { final int currentIndex; final CartController cartController; final ValueChanged onTap; const _GlassPill({ required this.currentIndex, required this.cartController, required this.onTap, }); @override Widget build(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.circular(60), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), child: Container( height: 72, decoration: BoxDecoration( // Semi-transparent white glass overlay — matches the frosted pill // gradient: LinearGradient( // begin: Alignment.topCenter, // end: Alignment.bottomCenter, // colors: [ // Colors.white.withOpacity(0.28), // Colors.white.withOpacity(0.08), // ], // ), borderRadius: BorderRadius.circular(60), border: Border.all( color: Colors.white.withOpacity(0.35), width: 2.8, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _NavItem( icon: Icons.home_rounded, label: 'Home', isActive: currentIndex == 0, onTap: () => onTap(0), ), _NavItem( icon: Icons.receipt_long_rounded, label: 'Order', isActive: currentIndex == 1, onTap: () => onTap(1), ), _NavItem( icon: Icons.qr_code_scanner_rounded, label: 'Scan', isActive: currentIndex == 2, onTap: () => onTap(2), ), _CartNavItem( isActive: currentIndex == 3, cartController: cartController, onTap: () => onTap(3), ), _NavItem( icon: Icons.person_rounded, label: 'Profile', isActive: currentIndex == 4, onTap: () => onTap(4), ), ], ), ), ), ); } } // ─── Nav Item ───────────────────────────────────────────────────────────────── class _NavItem extends StatelessWidget { final IconData icon; final String label; final bool isActive; final VoidCallback onTap; const _NavItem({ required this.icon, required this.label, required this.isActive, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: SizedBox( width: 64, height: 72, child: Stack( alignment: Alignment.center, children: [ // White radial glow spotlight for active tab (matches image) if (isActive) Container( width: 68, height: 68, decoration: BoxDecoration( shape: BoxShape.circle, // gradient: RadialGradient( // colors: [ // Colors.white.withOpacity(0.55), // Colors.white.withOpacity(0.0), // ], // stops: const [0.0, 1.0], // radius: 0.60, // ), ), ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, color: isActive ? _kActive : _kInactive, size: isActive ? 27 : 22, ), const SizedBox(height: 4), Text( label, style: TextStyle( color: isActive ? _kActive : _kInactive, fontSize: 11, fontWeight: isActive ? FontWeight.w700 : FontWeight.w500, letterSpacing: 0.2, ), ), ], ), ], ), ), ); } } // ─── Cart Nav Item ──────────────────────────────────────────────────────────── class _CartNavItem extends StatelessWidget { final bool isActive; final CartController cartController; final VoidCallback onTap; const _CartNavItem({ required this.isActive, required this.cartController, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: SizedBox( width: 64, height: 72, child: Stack( alignment: Alignment.center, children: [ if (isActive) Container( width: 68, height: 68, decoration: BoxDecoration( shape: BoxShape.circle, // gradient: RadialGradient( // colors: [ // Colors.white.withOpacity(0.55), // Colors.white.withOpacity(0.0), // ], // stops: const [0.0, 1.0], // radius: 0.60, // ), ), ), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Stack( clipBehavior: Clip.none, children: [ Icon( Icons.shopping_cart_rounded, color: isActive ? _kActive : _kInactive, size: isActive ? 27 : 22, ), Obx(() { final int count = cartController.totalItems; if (count == 0) return const SizedBox.shrink(); return Positioned( right: -8, top: -6, child: Container( padding: const EdgeInsets.all(3), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), constraints: const BoxConstraints( minWidth: 17, minHeight: 17), child: Text( '$count', style: const TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ), ); }), ], ), const SizedBox(height: 4), Text( 'Cart', style: TextStyle( color: isActive ? _kActive : _kInactive, fontSize: 11, fontWeight: isActive ? FontWeight.w700 : FontWeight.w500, letterSpacing: 0.2, ), ), ], ), ], ), ), ); } }