import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:taxglide/consts/app_style.dart'; import 'package:get/get.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/screens/history/detail_screen.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart'; import 'package:taxglide/services/razorpay_service.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/controller/api_repository.dart'; class PendingScreen extends ConsumerStatefulWidget { final String status; const PendingScreen({super.key, required this.status}); @override ConsumerState createState() => _PendingScreenState(); } class _PendingScreenState extends ConsumerState { late RazorpayService _razorpayService; @override void initState() { super.initState(); _razorpayService = RazorpayService( onSuccess: _handlePaymentSuccess, onFailure: _handlePaymentFailure, ); } void _handlePaymentSuccess(PaymentSuccessResponse response) { ValidationPopup().showSuccessMessage( context, "Payment successful! ID: ${response.paymentId}", ); ref .read(serviceHistoryNotifierProvider(widget.status).notifier) .fetchServiceHistory(); } void _handlePaymentFailure(PaymentFailureResponse response) { ValidationPopup().showErrorMessage( context, "Payment failed: ${response.message}", ); } @override void dispose() { _razorpayService.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final pendingAsync = ref.watch( serviceHistoryNotifierProvider(widget.status), ); final size = MediaQuery.of(context).size; final width = size.width; final height = size.height; // 🔄 Silent refresh when notification trigger changes ref.listen(notificationTriggerProvider, (previous, next) { if (previous != null && next != previous) { debugPrint( "🔔 Silent refresh triggered for PendingScreen (${widget.status})", ); ref .read(serviceHistoryNotifierProvider(widget.status).notifier) .fetchServiceHistory(isSilent: true); ref.invalidate(countProvider); } }); return pendingAsync.when( data: (data) { final list = data.data ?? []; if (list.isEmpty) { // Using Get's capitalize extension explicitly return Center( child: Text("No ${widget.status.capitalizeFirst} Requests"), ); } return ListView.separated( physics: const BouncingScrollPhysics(), padding: EdgeInsets.fromLTRB( width * 0.04, height * 0.01, width * 0.04, 80.0 + MediaQuery.of(context).padding.bottom, ), itemCount: list.length, separatorBuilder: (_, __) => SizedBox(height: height * 0.01), itemBuilder: (context, index) { final item = list[index]; return Container( width: double.infinity, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color: const Color(0xFFE1E1E1), width: 1), boxShadow: [ BoxShadow( color: const Color.fromARGB(117, 192, 192, 189), blurRadius: 15, offset: const Offset(0, 1), ), ], ), padding: EdgeInsets.all(width * 0.03), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 🔹 File ID Row Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ /// 🔹 File ID RichText( text: TextSpan( children: [ TextSpan( text: 'File ID : ', style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), ), TextSpan( text: '${item.id}', style: AppTextStyles.medium.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), ), ], ), ), /// 🔥 Status + Chat Icon Row( children: [ /// 🔴 Waiting / Pending / Cancelled if (item.status == 'Waiting for Admin' || item.status == 'Payment Pending' || item.status == 'Cancelled By Admin') Container( width: width * 0.4, height: height * 0.04, decoration: BoxDecoration( color: const Color(0xFFFFE8E8), borderRadius: BorderRadius.circular(5.52), border: Border.all( color: const Color(0xFFFFD7D7), width: 1.84, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.17, offset: const Offset(0, 3.68), ), ], ), child: Center( child: Text( item.status.toString(), style: AppTextStyles.regular.copyWith( fontSize: 11.03, color: const Color(0xFFFF0F0F), ), ), ), ), /// 🟢 In Progress if (item.status == 'In Progress') Container( width: 98, height: 34.9, decoration: BoxDecoration( color: const Color(0xFFEAFAE6), borderRadius: BorderRadius.circular(6.21), border: Border.all( color: const Color(0xFFDDFFDD), width: 2.07, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 8.08, offset: const Offset(0, 4.14), ), ], ), child: Center( child: Text( 'In Progress', style: AppTextStyles.regular.copyWith( fontSize: 12.43, color: const Color(0xFF12800C), ), ), ), ), /// 🟡 Completed if (item.status == 'Completed') Container( width: 87, height: 31, decoration: BoxDecoration( color: const Color(0xFFFAF7E6), borderRadius: BorderRadius.circular(5.52), border: Border.all( color: const Color(0xFFFFE9DD), width: 1.84, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.17, offset: const Offset(0, 3.68), ), ], ), child: Center( child: Text( 'Completed', style: AppTextStyles.regular.copyWith( fontSize: 11.03, color: const Color(0xFFFF630F), ), ), ), ), /// 🔥 Space between status & icon const SizedBox(width: 8), if ((item.status == 'Completed' || item.status == 'Cancelled By Admin' || item.status == 'In Progress') && item.chatId != null && item.chatId.toString().isNotEmpty && item.chatId.toString() != "0") ...[ /// 💬 Chat Icon with Badge Builder( builder: (context) { final chatIdStr = item.chatId.toString(); final countAsync = ref.watch( countProvider(chatIdStr), ); return GestureDetector( onTap: () { final chatid = int.tryParse(chatIdStr) ?? 0; if (chatid == 0) return; if (item.status == 'In Progress') { Get.to( () => LiveChatScreen( fileid: item.id.toString(), chatid: chatid, ), )?.then((_) { ref .read( notificationTriggerProvider .notifier, ) .state++; ref.invalidate( chatMessagesProvider(chatid), ); ref.invalidate( countProvider(chatIdStr), ); }); } else { Get.to( () => CompletedLiveChatScreen( fileid: item.id.toString(), chatid: chatid, ), )?.then((_) { ref .read( notificationTriggerProvider .notifier, ) .state++; ref.invalidate( chatMessagesProvider(chatid), ); ref.invalidate( countProvider(chatIdStr), ); }); } }, child: Stack( clipBehavior: Clip.none, children: [ /// 🔵 Chat Icon Container( width: 39, height: 39, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF61277A), boxShadow: [ BoxShadow( color: Colors.black.withOpacity( 0.25, ), blurRadius: 8.08, offset: const Offset(0, 4.14), ), ], ), child: const Center( child: Icon( Icons.message, color: Colors.white, size: 20, ), ), ), /// 🔴 Badge countAsync.when( data: (countData) => countData.count > 0 ? Positioned( top: -4, right: -4, child: Container( padding: const EdgeInsets.all( 4, ), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), constraints: const BoxConstraints( minWidth: 16, minHeight: 16, ), child: Text( '${countData.count}', textAlign: TextAlign.center, style: const TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), ), ), ) : const SizedBox.shrink(), loading: () => const SizedBox.shrink(), error: (_, __) => const SizedBox.shrink(), ), ], ), ); }, ), ], ], ), ], ), SizedBox(height: height * 0.015), // 🔹 Request Type RichText( text: TextSpan( children: [ TextSpan( text: 'Request Type : ', style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), TextSpan( text: item.service, style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), ], ), ), SizedBox(height: height * 0.015), // 🔹 Date and Time Row Row( children: [ RichText( text: TextSpan( children: [ TextSpan( text: 'Date : ', style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), TextSpan( text: item.createdDate, style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), ], ), ), SizedBox(width: width * 0.05), RichText( text: TextSpan( children: [ TextSpan( text: 'Time : ', style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), TextSpan( text: item.createdTime, style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), ], ), ), ], ), SizedBox(height: height * 0.015), // 🔹 Message RichText( text: TextSpan( children: [ TextSpan( text: 'Message : ', style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), TextSpan( text: item.message, style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), ), ], ), ), SizedBox(height: height * 0.015), const Divider(), SizedBox(height: height * 0.015), // 🔹 Conditional Buttons & Amount if (item.paymentStatus == "Unpaid") ...[ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Total Amount", style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.038, color: const Color(0xFF111827), ), ), Text( '₹ ${item.paymentAmount.toString()}', style: TextStyle( fontFamily: 'Roboto', fontWeight: FontWeight.w600, fontSize: width * 0.05, color: const Color(0xFF111827), ), ), ], ), SizedBox(height: height * 0.015), Row( children: [ Expanded( child: GestureDetector( onTap: () async { try { final response = await ref .read(apiRepositoryProvider) .payNow( id: int.parse(item.id.toString()), ); if (response['status'] == 'success') { _razorpayService.openCheckout( key: response['razorpay_key'], amount: response['amount'], orderId: response['order_id'], description: "Payment for Service ID: ${item.id}", ); } else { ValidationPopup().showErrorMessage( context, "Failed to initiate payment", ); } } catch (e) { // Error handled in repository/notifier or via snackbar Get.snackbar( 'Error', e.toString(), backgroundColor: Colors.red, colorText: Colors.white, ); } }, child: Container( height: height * 0.055, decoration: BoxDecoration( color: const Color(0xFFF7E9FF), borderRadius: BorderRadius.circular(6), border: Border.all( color: const Color(0xFFD39FEA), width: 1, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.8, offset: const Offset(0, 4), ), ], ), child: Center( child: Text( "Pay Now", style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: const Color(0xFF61277A), ), ), ), ), ), ), SizedBox(width: width * 0.03), Expanded( child: GestureDetector( onTap: () { ref.invalidate(serviceDetailProvider); Get.offAll( () => MainController( initialIndex: 2, // ✅ History tab child: DetailScreen( id: int.parse(item.id.toString()), sourceTabIndex: 2, // ✅ Remember source ), ), ); }, child: Container( height: height * 0.055, decoration: BoxDecoration( color: const Color(0xFF5F297B), borderRadius: BorderRadius.circular(6), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.8, offset: const Offset(0, 4), ), ], ), child: Center( child: Text( "View Details", style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), ), ), ), ), ), ], ), ] else if (item.paymentStatus == "Paid") ...[ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( width: 149, height: 33, decoration: BoxDecoration( color: const Color(0xFF04690B), borderRadius: BorderRadius.circular(4.53), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 5.89, offset: const Offset(0, 3.02), ), ], ), alignment: Alignment.center, child: Text( "Payment Status: Paid", textAlign: TextAlign.center, style: AppTextStyles.regular.copyWith( fontSize: 12.08, letterSpacing: 0.04, height: 1.3, color: Colors.white, ), ), ), GestureDetector( onTap: () { ref.invalidate(serviceDetailProvider); Get.offAll( () => MainController( initialIndex: 2, // ✅ History tab child: DetailScreen( id: int.parse(item.id.toString()), sourceTabIndex: 2, // ✅ Remember source ), ), ); }, child: Container( height: height * 0.055, width: width * 0.35, decoration: BoxDecoration( color: const Color(0xFF5F297B), borderRadius: BorderRadius.circular(6), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.8, offset: const Offset(0, 4), ), ], ), child: Center( child: Text( "View Details", style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), ), ), ), ), ], ), ] else if (item.paymentStatus == "Waiting") ...[ Align( alignment: Alignment.centerRight, child: GestureDetector( onTap: () { ref.invalidate(serviceDetailProvider); Get.offAll( () => MainController( initialIndex: 2, // ✅ History tab child: DetailScreen( id: int.parse(item.id.toString()), sourceTabIndex: 2, // ✅ Remember source ), ), ); }, child: Container( height: height * 0.055, width: width * 0.35, decoration: BoxDecoration( color: const Color(0xFF5F297B), borderRadius: BorderRadius.circular(6), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.25), blurRadius: 7.8, offset: const Offset(0, 4), ), ], ), child: Center( child: Text( "View Details", style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), ), ), ), ), ), ], SizedBox(height: height * 0.02), ], ), ); }, ); }, loading: () => const Center(child: CircularProgressIndicator()), error: (error, _) => Center( child: Text("Error: $error", style: const TextStyle(color: Colors.red)), ), ); } }