import 'dart:async'; import 'dart:math'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'package:muaawana/models/chat_v2/chat_room.dart'; import 'package:muaawana/models/chat_v2/message_list.dart'; import 'package:muaawana/providers/auth_provider.dart'; import 'package:muaawana/views/client_view/booking/widgets/step_divider.dart'; import 'package:muaawana/views/client_view/booking/widgets/ticket_step.dart'; import '../../../config/lang_enum.dart'; import '../../../config/provider.dart'; import '../../../config/style.dart'; import '../../../providers/chat_v2/user_conversation.dart'; import '../../../providers/language_provider.dart'; import '../../../providers/navbar_provider/client_bottom_nav_provider.dart'; import '../../../services/chat_v2/all_conversations.dart'; import '../../../utils/utils_singleton.dart'; import '../main_screen.dart'; import '../messages/msg_v2/discussion.dart'; import '../rating/rating_screen.dart'; import 'booking_dashboard.dart'; import 'widgets/dot_indicator_widget.dart'; import '../../../config/app_constant.dart'; import '../../../config/size.dart'; import '../../../providers/request_status_provider.dart'; import '../../../utils/text_style.dart'; import '../../../utils/text_widget.dart'; import '../../../widgets/custom_app_bar.dart'; import '../../../widgets/custom_botton_widget.dart'; class BookingScreen extends StatefulWidget { const BookingScreen({Key? key}) : super(key: key); @override State createState() => _BookingScreenState(); } class _BookingScreenState extends State with WidgetsBindingObserver { final hm = SizeConfig.heightMultiplier; final wm = SizeConfig.widthMultiplier; final tm = SizeConfig.textMultiplier; final List filterItems = [ 'Products & Services', 'Products', 'Services' ]; String? selectedItem; /// Index of the Booking tab in ClientBottomNavigationProvider's screen list. static const int _bookingTabIndex = 1; int? _lastNavIndex; @override void initState() { super.initState(); selectedItem = filterItems.first; WidgetsBinding.instance.addObserver(this); _lastNavIndex = clientNavProvider.currentIndex; clientNavProvider.addListener(_onNavIndexChanged); } @override void dispose() { clientNavProvider.removeListener(_onNavIndexChanged); WidgetsBinding.instance.removeObserver(this); super.dispose(); } /// This screen's State survives tab switches (the shell keeps it alive), so /// initState runs only once and the list would otherwise never re-fetch when /// the user comes back to the Booking tab. Re-fetch on each re-entry. void _onNavIndexChanged() { final index = clientNavProvider.currentIndex; if (index == _lastNavIndex) return; final reEnteredBooking = index == _bookingTabIndex && _lastNavIndex != _bookingTabIndex; _lastNavIndex = index; if (reEnteredBooking && mounted) { context .read() .fetchAllRequest(selectedItem ?? filterItems.first); } } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // The list is otherwise only fetched when this screen is first built, so a // booking that changed server-side while the app was backgrounded (a // technician assigned, a status advanced, a request archived) would stay // stale until the user pulled to refresh. Re-fetch on resume, keeping // whatever filter is currently selected. if (state == AppLifecycleState.resumed && mounted) { context .read() .fetchAllRequest(selectedItem ?? filterItems.first); } } @override Widget build(BuildContext context) { final langProvider = Provider.of(context); final bottomNavProvider = Provider.of(context); return Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Column( children: [ // Modern Header Section Container( decoration: BoxDecoration( color: Theme.of(context).cardColor, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(Theme.of(context).brightness == Brightness.dark ? 0.4 : 0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: SafeArea( bottom: false, child: Padding( padding: EdgeInsets.symmetric(horizontal: wm * 4, vertical: hm * 2), child: Column( children: [ // Header with title and new request button Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( languageSingleton.translate('Booking'), style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface, ), ), GestureDetector( onTap: () { // Don't use Navigator.pushReplacement - this breaks the widget tree // Instead, just change the bottom nav index final bottomNavProvider = Provider.of(context, listen: false); bottomNavProvider.setCurrentIndex(0); // If you need to navigate, use Navigator.pop() or just rely on bottom nav // Navigator.pop(context); // Only if you're in a pushed screen }, child: Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( gradient: LinearGradient( colors: [AppNewStyle.mediumPriorityColor, AppNewStyle.mediumPriorityColor.withOpacity(0.85)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(25), boxShadow: [ BoxShadow( color: AppNewStyle.mediumPriorityColor.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.add, color: Colors.white, size: 16), SizedBox(width: 4), Text( languageSingleton.translate("New Request"), style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600, ), ), ], ), ), ), ], ), SizedBox(height: hm * 3), // Modern Dropdown Container( decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppNewStyle.primaryButton.withOpacity(0.2)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(Theme.of(context).brightness == Brightness.dark ? 0.4 : 0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: DropdownButtonHideUnderline( child: DropdownButton2( value: selectedItem, items: filterItems.map((String item) { return DropdownMenuItem( value: item, child: Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ Expanded( child: Text( languageSingleton.translate(item), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), ), if (item == selectedItem) Container( padding: EdgeInsets.all(2), decoration: BoxDecoration( color: AppNewStyle.primaryButton, shape: BoxShape.circle, ), child: Icon(Icons.check, color: Colors.white, size: 12), ), ], ), ), ); }).toList(), onChanged: (String? newValue) { if (newValue != null) { setState(() { selectedItem = newValue; }); Timer.run(() async { context.read().fetchAllRequest(selectedItem!); }); } }, dropdownStyleData: DropdownStyleData( maxHeight: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: Theme.of(context).cardColor, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(Theme.of(context).brightness == Brightness.dark ? 0.4 : 0.1), blurRadius: 20, offset: const Offset(0, 8), ), ], ), elevation: 0, offset: const Offset(0, 4), ), menuItemStyleData: MenuItemStyleData( height: 50, padding: EdgeInsets.zero, ), customButton: Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ Icon(Icons.filter_list, color: AppNewStyle.primaryButton, size: 20), SizedBox(width: 12), Expanded( child: Text( languageSingleton.translate(selectedItem!), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface, ), ), ), Icon(Icons.keyboard_arrow_down, color: AppNewStyle.primaryButton), ], ), ), ), ), ), ], ), ), ), ), SizedBox(height: hm * 2), // Tab Section const Expanded(child: TabScreens()), ], ), ); } } class TabScreens extends StatefulWidget { const TabScreens({Key? key}) : super(key: key); @override State createState() => _TabScreensState(); } class _TabScreensState extends State with SingleTickerProviderStateMixin { late TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); _tabController.animateTo(0); } @override void dispose() { super.dispose(); _tabController.dispose(); } @override Widget build(BuildContext context) { final langProvider = Provider.of(context); final hm = SizeConfig.heightMultiplier; final wm = SizeConfig.widthMultiplier; return Column( children: [ // Modern Tab Bar Container( margin: EdgeInsets.symmetric(horizontal: wm * 4), padding: EdgeInsets.all(4), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(Theme.of(context).brightness == Brightness.dark ? 0.4 : 0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: TabBar( controller: _tabController, tabs: langProvider.currentLangCode == Language.en ? _tabs : _tabsAr, labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ), unselectedLabelColor: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), labelColor: Theme.of(context).colorScheme.onPrimary, dividerColor: Colors.transparent, indicator: BoxDecoration( gradient: LinearGradient( colors: [AppNewStyle.primaryButton, AppNewStyle.primaryButton.withOpacity(0.8)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: AppNewStyle.primaryButton.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), ], ), indicatorSize: TabBarIndicatorSize.tab, ), ), SizedBox(height: hm * 2), // Tab Content Expanded( child: TabBarView( controller: _tabController, children: const [ ServiceProductListWidget(), ServiceProductListWidget(isDone: true), ], ), ), SizedBox(height: hm * 10), ], ); } static const List _tabsAr = [ Tab(text: "في تقدم"), Tab(text: "اكتمل"), ]; static const List _tabs = [ Tab(text: "In Progress"), Tab(text: "Done"), ]; } class ServiceProductListWidget extends StatefulWidget { const ServiceProductListWidget({Key? key, this.isDone = false}) : super(key: key); final bool isDone; @override State createState() => _ServiceProductListWidgetState(); } class _ServiceProductListWidgetState extends State { final hm = SizeConfig.heightMultiplier; final wm = SizeConfig.widthMultiplier; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().fetchAllRequest('Products & Services'); }); } @override Widget build(BuildContext context) { final bookingListProvider = Provider.of(context); if (bookingListProvider.loader && bookingListProvider.bookingList.isEmpty && bookingListProvider.bookingListCompleted.isEmpty) { return Center( child: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).cardColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(Theme.of(context).brightness == Brightness.dark ? 0.4 : 0.1), blurRadius: 20, offset: const Offset(0, 4), ), ], ), child: CircularProgressIndicator( strokeWidth: 3, valueColor: AlwaysStoppedAnimation(AppNewStyle.primaryButton), ), ), ); } final isEmpty = widget.isDone ? bookingListProvider.bookingListCompleted.isEmpty : bookingListProvider.bookingList.isEmpty; if (!bookingListProvider.loader && isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: EdgeInsets.all(30), decoration: BoxDecoration( color: Colors.grey[100], shape: BoxShape.circle, ), child: Icon( widget.isDone ? Icons.check_circle_outline : Icons.pending_outlined, size: 60, color: Colors.grey[400], ), ), SizedBox(height: 20), Text( languageSingleton.translate('No Booking found.'), style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.grey[600], ), ), SizedBox(height: 8), Text( widget.isDone ? 'Completed bookings will appear here' : 'Your active bookings will appear here', style: TextStyle( fontSize: 14, color: Colors.grey[500], ), ), ], ), ); } final bookingList = widget.isDone ? bookingListProvider.bookingListCompleted : bookingListProvider.bookingList; return RefreshIndicator( color: AppNewStyle.primaryButton, onRefresh: () async { context.read().fetchAllRequest('Products & Services'); }, child: ListView.builder( padding: EdgeInsets.symmetric(horizontal: wm * 2), itemCount: bookingList.length, itemBuilder: (context, index) { return TicketWidget(item: bookingList[index]); }, ), ); } } class TicketWidget extends StatelessWidget { final ViewListModel item; const TicketWidget({Key? key, required this.item}) : super(key: key); @override Widget build(BuildContext context) { final langProvider = Provider.of(context); final isArabic = langProvider.currentLangCode == Language.ar; final hm = SizeConfig.heightMultiplier; final wm = SizeConfig.widthMultiplier; return Container( margin: EdgeInsets.symmetric(horizontal: wm * 2, vertical: hm * 1), child: Card( elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Container( decoration: BoxDecoration( color:Theme.of(context).brightness == Brightness.dark ? AppNewStyle.darkAppBackground : AppNewStyle.whiteAppBackground, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.withOpacity(0.1)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () { context.read().removeNotificationRequest( item.id, item.bookingType == BookingType.service, item.bookingStatus == BookingStatus.done); Navigator.push( context, MaterialPageRoute( builder: (context) => BookingDashboard(item: item))); }, child: Padding( padding: EdgeInsets.all(wm * 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(context), SizedBox(height: hm * 2), _buildServiceInfo(), SizedBox(height: hm ), _buildTimeInfo(context), SizedBox(height: hm *1.3), _buildStatusSteps(langProvider, isArabic,context), SizedBox(height: hm * 1.5), _buildActionButton(context,langProvider), ], ), ), ), ), ), ); } Widget _buildHeader(context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( gradient: LinearGradient( colors:Theme.of(context).brightness == Brightness.dark ? [ AppNewStyle.whiteAppBackground.withOpacity(0.3), AppNewStyle.whiteAppBackground.withOpacity(0.1) ]:[ AppNewStyle.primaryButton.withOpacity(0.1), AppNewStyle.primaryButton.withOpacity(0.05) ], ), borderRadius: BorderRadius.circular(20), border: Border.all ( color:Theme.of(context).brightness == Brightness.dark ? AppNewStyle.whiteAppBackground.withOpacity(0.3): AppNewStyle.primaryButton.withOpacity(0.2) ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.calendar_today, size: 12, color: AppNewStyle.primaryButton), SizedBox(width: 4), Text( item.date, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: AppNewStyle.primaryButton, ), ), ], ), ), if (item.notification == true) Container( padding: EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), child: Container( width: 6, height: 6, decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), ), ), ], ); } Widget _buildServiceInfo() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.name, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, // color: AppStyle.black, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ); } Widget _buildTimeInfo(context) { return Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color:Theme.of(context).brightness == Brightness.dark ? Theme.of(context).cardColor: Colors.grey[50], borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey.withOpacity(0.1)), ), child: Row( children: [ Icon(Icons.access_time, size: 16, ), SizedBox(width: 8), // A clock range needs three things to survive the app's global RTL // Directionality, each learned the hard way: // 1. pin the fragment to LTR, else "9:00 AM to 9:30 AM" renders as // "AM to 9:30 AM 9:00"; // 2. use a direction-neutral separator - a translated connector // ("إلى") is an RTL run and scrambles the range again; // 3. isolate each time, because the Arabic AM/PM marker (ص/م) is // itself RTL and otherwise reorders the numbers around it. // An en dash reads correctly as a range separator in both languages. Directionality( textDirection: TextDirection.ltr, child: Text( // \u2066 LRI ... \u2069 PDI isolates each clock time so its Arabic AM/PM // marker (\u0635/\u0645) cannot reorder the range around it. "\u2066${item.startTime}\u2069 \u2013 \u2066${item.endTime}\u2069", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), ); } Widget _buildStatusSteps(LanguageProvider langProvider, bool isArabic,context) { final steps = [ { 'title': langProvider.translate('Request has been submitted'), 'isActive': item.status == 'SUBMITTED', 'isCompleted': _isStepCompleted('SUBMITTED'), }, { 'title': langProvider.translate('Technician assigned'), 'isActive': item.status == 'ASSIGNED' || item.status == 'REJECTED', 'isCompleted': _isStepCompleted('ASSIGNED'), }, { 'title': langProvider.translate('Your technician is on the way'), 'isActive': item.status == 'ACCEPTED', 'isCompleted': _isStepCompleted('ACCEPTED'), }, { 'title': langProvider.translate('In Progress'), 'isActive': item.status == 'IN_PROGRESS', 'isCompleted': _isStepCompleted('IN_PROGRESS'), }, { 'title': langProvider.translate('Job Completed'), 'isActive': item.status == 'COMPLETED', 'isCompleted': _isStepCompleted('COMPLETED'), }, ]; return Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( color:Theme.of(context).brightness == Brightness.dark ? Theme.of(context).cardColor : Colors.grey[50], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey.withOpacity(0.1)), ), child: Column( children: steps.asMap().entries.map((entry) { final index = entry.key; final step = entry.value; final isLast = index == steps.length - 1; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( children: [ Container( width: 24, height: 20, decoration: BoxDecoration( shape: BoxShape.circle, color: step['isCompleted'] as bool || step['isActive'] as bool ? AppNewStyle.primaryButton : Colors.grey.withOpacity(0.3), boxShadow: step['isActive'] as bool ? [ BoxShadow( color: AppNewStyle.primaryButton.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), ] : null, ), child: step['isCompleted'] as bool ? Icon(Icons.check, size: 14, color: Colors.white) : Center( child: Container( width: 8, height: 8, decoration: BoxDecoration( shape: BoxShape.circle, color: step['isActive'] as bool ? Colors.white : Colors.transparent, ), ), ), ), if (!isLast) Container( width: 2, height: 30, margin: EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( color: step['isCompleted'] as bool ? AppNewStyle.primaryButton : Colors.grey.withOpacity(0.3), borderRadius: BorderRadius.circular(1), ), ), ], ), SizedBox(width: 16), Expanded( child: Padding( padding: EdgeInsets.only(top: 1, bottom: isLast ? 0 : 20), child: Text( step['title'] as String, style: TextStyle( fontSize: 13, fontWeight: step['isActive'] as bool || step['isCompleted'] as bool ? FontWeight.w600 : FontWeight.w500, color: step['isActive'] as bool || step['isCompleted'] as bool ? Theme.of(context).brightness == Brightness.dark ? AppNewStyle.whiteAppBackground : AppStyle.black : Theme.of(context).brightness == Brightness.dark ? Colors.white70 : Colors.grey[600], ), ), ), ), ], ); }).toList(), ), ); } bool _isStepCompleted(String stepStatus) { final statusOrder = ['SUBMITTED', 'ASSIGNED', 'ACCEPTED', 'IN_PROGRESS', 'COMPLETED']; final currentIndex = statusOrder.indexOf(item.status); final stepIndex = statusOrder.indexOf(stepStatus); return currentIndex > stepIndex; } Widget _buildActionButton(BuildContext context,langProvider) { String buttonText; Color buttonColor; Color textColor; IconData? buttonIcon; switch (item.status) { case 'COMPLETED': buttonText = langProvider.translate('Leave Review'); buttonColor = AppNewStyle.primaryButton; textColor = Colors.white; buttonIcon = Icons.star_outline; break; case 'SUBMITTED': buttonText = langProvider.translate('Waiting'); buttonColor = Theme.of(context).brightness == Brightness.dark ? Colors.black : Colors.white; textColor = Theme.of(context).brightness == Brightness.dark ? Colors.white : AppNewStyle.primaryButton; buttonIcon = Icons.schedule; break; case 'CANCELLED': buttonText = langProvider.translate('Cancelled'); buttonColor = Theme.of(context).brightness == Brightness.dark ? Colors.black : Colors.white; textColor = Colors.red; buttonIcon = Icons.cancel_outlined; break; default: buttonText = langProvider.translate('Send Message'); buttonColor = AppNewStyle.primaryButton; textColor = Colors.white; buttonIcon = Icons.chat_bubble_outline; } return Container( width: double.infinity, decoration: BoxDecoration( gradient:LinearGradient( colors: [buttonColor, buttonColor.withOpacity(0.8)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), color: buttonColor == Colors.white ? Colors.white : null, borderRadius: BorderRadius.circular(12), border: Border.all( color: item.status == 'CANCELLED' ? Colors.red : AppNewStyle.primaryButton, width: 1.5, ), boxShadow: buttonColor != Colors.white ? [ BoxShadow( color: buttonColor.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ] : null, ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(12), onTap: () => _handleButtonTap(context), child: Padding( padding: EdgeInsets.symmetric(vertical: 14), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ if (buttonIcon != null) ...[ Icon(buttonIcon, color: textColor, size: 18), SizedBox(width: 8), ], Text( buttonText, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: textColor, ), ), ], ), ), ), ), ); } void _handleButtonTap(BuildContext context) async { if (item.status == 'COMPLETED') { Navigator.push( context, MaterialPageRoute( builder: (context) => RatingScreen( bookingType: item.bookingType, id: item.bookingId, technicianId: item.technician?.id, ), ), ); } else if (item.status == 'SUBMITTED') { Get.showSnackbar( const GetSnackBar( title: "Order submitted successfully", message: 'Your order has been submitted. A technician will be assigned to you briefly.', duration: Duration(seconds: 2), ), ); } else if (item.status == 'CANCELLED') { Get.showSnackbar( const GetSnackBar( title: "Order cancelled successfully", message: 'Your order has been cancelled, You can request a new one.', duration: Duration(seconds: 2), ), ); } else { AllConversationsService allConversationsService = AllConversationsService(); MessageListModel? conversation; await allConversationsService.getAllConversations(page: 0, size: 100); conversation = userConversationSingleton.allConversations.firstWhere( (element) => element.chatroom!.recipient!.id == item.technician!.userId || element.chatroom!.sender!.id == item.technician!.id, orElse: () { final messageListModel = MessageListModel( chatroom: ChatRoomModel( id: Random().nextInt(999999999), chatId: "${item.technician!.userId}_${util.user!.id}", ), lastmessagetimestmp: DateTime.now().millisecondsSinceEpoch, ); userConversationSingleton.allConversations.add(messageListModel); return messageListModel; }, ); Navigator.push( context, MaterialPageRoute( builder: (context) => Discussion( senderId: context.read().profile!.id!, recipientId: item.technician!.userId, senderName: context.read().profile!.name!, recipientName: item.technician!.userName, recipientImage: item.technician!.photoUrl, fromOrderScreen: true, messageList: conversation, isDarck: Theme.of(context).brightness == Brightness.dark, ), ), ); // Don't set bottom nav index after navigation - this can cause context issues // Instead, set it before navigation or handle it in the Discussion screen // context.read().setCurrentIndex(3); } } }