bookmywages/lib/view/user_main_screens/main_contoller.dart
2025-10-16 11:21:52 +05:30

378 lines
11 KiB
Dart

import 'dart:convert';
import 'dart:ui';
import 'dart:math' as math;
import 'package:bookmywages/consts_widgets/app_assets.dart';
import 'package:bookmywages/routers/consts_router.dart';
import 'package:bookmywages/viewmodel/api_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // Add this import
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 MainController extends ConsumerStatefulWidget {
final Widget child;
final int? initialBottomIndex;
const MainController({
super.key,
required this.child,
this.initialBottomIndex,
});
@override
ConsumerState<MainController> createState() => _MainControllerState();
}
class _MainControllerState extends ConsumerState<MainController>
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.homescreen) {
_selectedIndex = 0;
} else if (currentRoute == RouterConts.packageList) {
_selectedIndex = 1;
} else if (currentRoute == RouterConts.categorypage) {
_selectedIndex = 2;
} else if (currentRoute == RouterConts.history) {
_selectedIndex = 3;
} else if (currentRoute == RouterConts.profilemainscreen ||
currentRoute == RouterConts.editprofile ||
currentRoute == RouterConts.changepassword) {
_selectedIndex = 0; // No tab selected
}
}
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
}
void _toggleMenu() {
setState(() {
_showMenu = !_showMenu;
_showMenu
? _animationController.forward()
: _animationController.reverse();
});
}
// 🎯 NEW: Handle back button press
Future<bool> _onWillPop() async {
final currentRoute = Get.currentRoute;
// If menu is open, close it first
if (_showMenu) {
_toggleMenu();
return false; // Don't exit
}
// Handle back navigation based on current route
switch (currentRoute) {
case RouterConts.profilemainscreen:
case RouterConts.editprofile:
case RouterConts.changepassword:
// Navigate back to home when coming from profile screens
Get.offAllNamed(RouterConts.homescreen);
return false; // Don't use default back behavior
case RouterConts.packageList:
case RouterConts.categorypage:
case RouterConts.history:
// For other main tabs, go to home first
Get.offAllNamed(RouterConts.homescreen);
return false;
case RouterConts.homescreen:
// If already on home, allow default back behavior (exit app)
return true;
default:
// For any other screens, try to go back to home
try {
Get.back();
} catch (e) {
// If can't go back, navigate to home
Get.offAllNamed(RouterConts.homescreen);
}
return false;
}
}
void _onItemTapped(int index, BuildContext context) {
if (_selectedIndex == index) return;
switch (index) {
case 0:
Get.offAllNamed(RouterConts.homescreen);
break;
case 1:
Get.offAllNamed(RouterConts.packageList);
break;
case 2:
Get.offAllNamed(RouterConts.categorypage);
break;
case 3:
// Navigate to history with default tab (Service Booking)
Get.offAllNamed(
RouterConts.history,
arguments: {
'historyTab': 0, // Default to first tab
},
);
break;
}
}
void changeSelectedIndex(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
final isKeyboardOpen = MediaQuery.of(context).viewInsets.bottom > 0;
// 🎯 Wrap with WillPopScope to handle back button
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
children: [
InheritedIndexController(
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.store,
label: 'Vendor',
color: const Color(0xFF0066FF),
onTap: () async {
_toggleMenu();
try {
await ref.read(getvendorIdProvider.future);
Get.toNamed(RouterConts.vendorwelcome);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Failed to fetch Vendor ID'),
),
);
}
},
),
_buildMenuOption(
icon: Icons.person,
label: 'Profile',
color: const Color(0xFF0066FF),
onTap: () {
_toggleMenu();
Get.toNamed(RouterConts.profilemainscreen);
},
),
],
),
),
),
],
),
floatingActionButton: isKeyboardOpen
? null
: FloatingActionButton(
heroTag: "main_controller_fab",
onPressed: _toggleMenu,
shape: const CircleBorder(),
backgroundColor: const Color(0xFF0066FF),
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
? const Color(0xFF0066FF)
: Colors.grey,
width: 26,
height: 29,
),
const SizedBox(height: 4),
Container(
height: 3,
width: 30,
decoration: BoxDecoration(
color: _selectedIndex == index
? const Color(0xFF0066FF)
: 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: Color(0xFF0066FF),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
],
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
class InheritedIndexController extends InheritedWidget {
final void Function(int) changeIndex;
const InheritedIndexController({
super.key,
required this.changeIndex,
required super.child,
});
static InheritedIndexController? of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<InheritedIndexController>();
}
@override
bool updateShouldNotify(InheritedIndexController oldWidget) {
return oldWidget.changeIndex != changeIndex;
}
}