// The new StatefulWidget class import 'dart:developer'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:beemwidget/text_styles/beem_text_styles.dart'; import 'package:flutter_svg/svg.dart'; import 'package:geolocator/geolocator.dart'; import 'package:provider/provider.dart'; import '../Provider/RideNotification.dart'; import '../Provider/RideProvider.dart'; import '../config/AppSnackbar.dart'; import '../config/constants/app_constant.dart'; import '../utils/DistanceCalculation.dart'; import '../utils/colors.dart'; import 'custom_text.dart'; class PendingRideCard extends StatefulWidget { final dynamic ride; // Consider using a more specific type instead of dynamic const PendingRideCard({super.key, required this.ride}); @override State createState() => _PendingRideCardState(); } // The new State class class _PendingRideCardState extends State { // 1. Declare the Future as an instance variable late Future _distanceFuture; @override void initState() { super.initState(); // 2. Initialize the Future in initState _distanceFuture = _getCalculatedDistanceString(widget.ride.startLocation); } @override Widget build(BuildContext context) { return Card( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Rider Info Section Padding( padding: EdgeInsets.only( left: 35.sp, right: 30.sp, top: 23.sp), child: Row( children: [ ClipOval( child: CachedNetworkImage( imageUrl: '$mediaUrl${widget.ride.userimageurl}', width: 40.sp, height: 40.sp, fit: BoxFit.fill, placeholder: (context, url) => const Center( child: CircularProgressIndicator()), errorWidget: (context, url, error) => Image.asset( 'assets/images/user_avatar.png', fit: BoxFit.cover), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.ride.ridername, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), overflow: TextOverflow.ellipsis, maxLines: 1, ), Row( children: [ const Icon(Icons.star, color: Colors.amber, size: 16), const SizedBox(width: 4), Text( widget.ride.averagedriverrating .toStringAsFixed(1), style: const TextStyle( fontSize: 14, color: Colors.grey), ), ], ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( "${widget.ride.totalPrice?.toStringAsFixed(2) ?? 0} TND", style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), Text( "${widget.ride.durationInMinutes?.toStringAsFixed(0) ?? 0} min", style: const TextStyle( fontSize: 14, color: Colors.grey), ), ], ), ], ), ), // Location Details Padding( padding: EdgeInsets.only(top: 7.sp), child: Container( height: 56.sp, color: Theme.of(context).brightness == Brightness.dark ? AppColors.darkCardColor : AppColors.whiteBackgroundColor, child: Row( children: [ Padding( padding: EdgeInsets.symmetric( horizontal: 13.sp) .copyWith(left: 35.sp), child: SvgPicture.asset( 'assets/icons/currentlocation_map.svg'), ), Flexible( child: Text( widget.ride.startLocationName, maxLines: 1, overflow: TextOverflow.ellipsis, style: BeemTextStyles.poppinsBold12 .copyWith(fontSize: 10), ), ), ], ), ), ), Container( height: 56.sp, color: Theme.of(context).brightness == Brightness.dark ? AppColors.darkCardColor : AppColors.whiteBackgroundColor, child: Row( children: [ Padding( padding: EdgeInsets.symmetric(horizontal: 13.sp) .copyWith(left: 35.sp), child: SvgPicture.asset( 'assets/icons/ic_pin.svg'), ), Flexible( child: Text( widget.ride.endLocationName, maxLines: 2, overflow: TextOverflow.ellipsis, style: BeemTextStyles.poppinsBold12 .copyWith(fontSize: 10), ), ), ], ), ), // Distance Info Padding( padding: EdgeInsets.only( left: 35.sp, right: 30.sp, top: 17.sp), child: Row( children: [ const Icon(Icons.route, color: Colors.orange, size: 20), const SizedBox(width: 8), FutureBuilder( // 3. Use the stored Future instance future: _distanceFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasError) { return const Text("Error", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500)); } else { return Text( snapshot.data ?? "N/A", style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500), ); } }, ), ], ), ), // Action Buttons Padding( padding: EdgeInsets.only( left: 35.sp, right: 30.sp, top: 14.sp, bottom: 16.sp), child: InkWell( borderRadius: BorderRadius.circular(25), onTap: () async { var rideprovider = context.read(); if (await rideprovider.accept_ride_driver_manual(widget.ride.id)) { await rideprovider.finbyidWithUpdate(widget.ride.id); await context.read().locationconnectionservice(); } else { AppSnackbar.showInfo("Ride", "This ride is no longer available."); // Check if the widget is still in the tree before calling setState if (mounted) { setState(() {}); } } }, child: Container( padding: const EdgeInsets.symmetric(vertical: 12), alignment: Alignment.center, decoration: BoxDecoration( color: Theme.of(context).brightness == Brightness.dark ? AppColors.darkPrimaryColor : AppColors.primaryColor, borderRadius: BorderRadius.circular(22), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ if (context.watch().isAcceptLoading) const Padding( padding: EdgeInsets.only(right: 8.0), child: SizedBox( width: 15, height: 15, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 2), ), ), const Txt( text: "Accept", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), ), ], ), ), ), ), ], ), ); } Future _getCalculatedDistanceString(String startLocation) async { try { // ... (your distance calculation logic) final lastKnown = await Geolocator.getLastKnownPosition(); Position? driverLivePosition; if (lastKnown != null) { driverLivePosition = lastKnown; log("📦 Initial Last known position: ${lastKnown.latitude}, ${lastKnown.longitude}"); } else { log("🚫 No last known position available."); } final double? driverLat = driverLivePosition?.latitude; final double? driverLon = driverLivePosition?.longitude; if (driverLat == null || driverLon == null) { return "Locating driver..."; } final String driverLocationString = "$driverLat,$driverLon"; final double? distance = calculateDistanceBetweenDriverAndUser( driverLocationString, startLocation, ); if (distance != null) { return "${distance.toStringAsFixed(1)} Km"; } else { return "Error Km"; } } catch (e) { log("Error in _getCalculatedDistanceString: $e"); return "Error Km"; } } }