import 'dart:convert'; import 'dart:ui'; import 'dart:math' as math; import 'package:bookmywages/consts_widgets/app_assets.dart'; import 'package:bookmywages/consts_widgets/app_colors.dart'; import 'package:bookmywages/routers/consts_router.dart'; import 'package:bookmywages/viewmodel/api_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; class VendorController extends ConsumerStatefulWidget { final Widget child; final int? initialBottomIndex; const VendorController({ super.key, required this.child, this.initialBottomIndex, }); @override ConsumerState createState() => _VendorControllerState(); } class _VendorControllerState extends ConsumerState with SingleTickerProviderStateMixin { int _selectedIndex = 0; bool _showMenu = false; late AnimationController _animationController; @override void initState() { super.initState(); // Set bottom navigation index if (widget.initialBottomIndex != null) { _selectedIndex = widget.initialBottomIndex!; } else { // Auto-detect based on current route final currentRoute = Get.currentRoute; if (currentRoute == RouterConts.vendorhomepage) { _selectedIndex = 0; } else if (currentRoute == RouterConts.vendorpackage) { _selectedIndex = 1; } else if (currentRoute == RouterConts.vendorcategory) { _selectedIndex = 2; } else if (currentRoute == RouterConts.vendorhistory) { _selectedIndex = 3; } } _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); } void _toggleMenu() { setState(() { _showMenu = !_showMenu; _showMenu ? _animationController.forward() : _animationController.reverse(); }); } void _onItemTapped(int index, BuildContext context) { if (_selectedIndex == index) return; switch (index) { case 0: Get.offAllNamed(RouterConts.vendorhomepage); break; case 1: Get.offAllNamed(RouterConts.vendorpackage); break; case 2: Get.offAllNamed(RouterConts.vendorcategory); break; case 3: // Navigate to vendor history with default tab Get.offAllNamed( RouterConts.vendorhistory, arguments: { 'historyTab': 0, // Default to first tab }, ); break; } } void changeSelectedIndex(int index) { setState(() { _selectedIndex = index; }); } // Handle back button press bool _onWillPop() { if (_showMenu) { // If menu is open, close it first _toggleMenu(); return false; } else if (_selectedIndex != 0) { // If not on home tab, go to home tab _onItemTapped(0, context); return false; } else { // If on home tab, allow app to exit return true; } } // Check if current route should show FAB bool _shouldShowFAB() { final currentRoute = Get.currentRoute; // Hide FAB on edit profile and other specific routes final hideFABRoutes = [ '/vendor-edit-profile', // Add your edit profile route here '/profile-edit', // Add other routes where you don't want FAB ]; return !hideFABRoutes.contains(currentRoute); } @override Widget build(BuildContext context) { final isKeyboardOpen = MediaQuery.of(context).viewInsets.bottom > 0; final currentRoute = Get.currentRoute; return PopScope( canPop: _selectedIndex == 0 && !_showMenu, onPopInvoked: (bool didPop) { if (!didPop) { _onWillPop(); } }, child: Scaffold( resizeToAvoidBottomInset: false, body: Stack( children: [ InheritedVendorIndexController( changeIndex: changeSelectedIndex, child: widget.child, ), if (_showMenu && !isKeyboardOpen) AnimatedOpacity( opacity: 1.0, duration: const Duration(milliseconds: 300), child: GestureDetector( onTap: _toggleMenu, child: Container( alignment: Alignment.center, child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0), child: Container( color: Colors.black.withOpacity(0.2), width: double.infinity, height: double.infinity, ), ), ), ), ), if (_showMenu && !isKeyboardOpen) Positioned( bottom: 60, left: 0, right: 0, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 110), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildMenuOption( icon: Icons.person, label: 'User', color: AppColors.primary, onTap: () { _toggleMenu(); Get.offNamed(RouterConts.homescreen); }, ), _buildMenuOption( icon: Icons.person, label: 'Profile', color: AppColors.primary, onTap: () { _toggleMenu(); Get.toNamed(RouterConts.profilemainvendor); }, ), ], ), ), ), ], ), floatingActionButton: (isKeyboardOpen || !_shouldShowFAB()) ? null : FloatingActionButton( // 🔧 FIXED: Dynamic hero tag based on route and timestamp heroTag: "vendor_controller_fab_${currentRoute}_${DateTime.now().millisecondsSinceEpoch}", onPressed: _toggleMenu, shape: const CircleBorder(), backgroundColor: AppColors.primary, child: AnimatedBuilder( animation: _animationController, builder: (context, child) { return Transform.rotate( angle: _animationController.value * 0.75 * math.pi, child: Icon( _animationController.value > 0.5 ? Icons.close : Icons.add, color: Colors.white, ), ); }, ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, bottomNavigationBar: BottomAppBar( notchMargin: 8, color: Colors.white, elevation: 8, child: SizedBox( height: 60, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _bottomNavItem(0, AppAssets.home), _bottomNavItem(1, AppAssets.package), const Expanded(child: SizedBox()), _bottomNavItem(2, AppAssets.categories), _bottomNavItem(3, AppAssets.history), ], ), ), ), ), ); } Widget _bottomNavItem(int index, String assetPath) { return Expanded( child: InkWell( onTap: () => _onItemTapped(index, context), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( assetPath, color: _selectedIndex == index ? AppColors.primary : Colors.grey, width: 26, height: 29, ), const SizedBox(height: 4), Container( height: 3, width: 30, decoration: BoxDecoration( color: _selectedIndex == index ? AppColors.primary : Colors.transparent, borderRadius: BorderRadius.circular(2), ), ), ], ), ), ); } Widget _buildMenuOption({ required IconData icon, required String label, required Color color, required VoidCallback onTap, }) { return ScaleTransition( scale: CurvedAnimation( parent: _animationController, curve: Curves.easeOut, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 50, height: 50, decoration: BoxDecoration( color: color, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 3, spreadRadius: 1, offset: const Offset(0, 1), ), ], ), child: IconButton( icon: Icon(icon, color: Colors.white), onPressed: onTap, padding: EdgeInsets.zero, ), ), const SizedBox(height: 5), Text( label, style: const TextStyle( color: AppColors.primary, fontWeight: FontWeight.bold, fontSize: 12, ), ), ], ), ); } @override void dispose() { _animationController.dispose(); super.dispose(); } } class InheritedVendorIndexController extends InheritedWidget { final void Function(int) changeIndex; const InheritedVendorIndexController({ super.key, required this.changeIndex, required super.child, }); static InheritedVendorIndexController? of(BuildContext context) { return context .dependOnInheritedWidgetOfExactType(); } @override bool updateShouldNotify(InheritedVendorIndexController oldWidget) { return oldWidget.changeIndex != changeIndex; } }