25-10-5/1

This commit is contained in:
Hamza-Ayed
2025-10-05 14:57:32 +03:00
parent 95fb065bdb
commit 1cc66029a3
28 changed files with 1347 additions and 666 deletions

View File

@@ -3,21 +3,20 @@ import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/functions/location_controller.dart';
import 'package:flutter/widgets.dart'; // Import for WidgetsBinding
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/widgets/mydialoug.dart';
import '../functions/crud.dart';
import '../functions/location_controller.dart';
class RideAvailableController extends GetxController {
bool isLoading = false;
Map rideAvailableMap = {};
// FIX 1: Initialize the map with a default structure.
// This prevents `rideAvailableMap['message']` from ever being null in the UI.
Map rideAvailableMap = {'message': []};
late LatLng southwest;
late LatLng northeast;
@@ -30,19 +29,15 @@ class RideAvailableController extends GetxController {
double minLat = lat - latDelta;
double maxLat = lat + latDelta;
double minLng = lng - lngDelta;
double maxLng = lng + lngDelta;
// Ensure the latitude is between -90 and 90
minLat = max(-90.0, minLat);
maxLat = min(90.0, maxLat);
// Ensure the longitude is between -180 and 180
minLng = (minLng + 180) % 360 - 180;
maxLng = (maxLng + 180) % 360 - 180;
// Ensure the bounds are in the correct order
if (minLng > maxLng) {
double temp = minLng;
minLng = maxLng;
@@ -60,7 +55,6 @@ class RideAvailableController extends GetxController {
double startLatitude = double.parse(startLocationParts[0]);
double startLongitude = double.parse(startLocationParts[1]);
// Assuming currentLocation is the driver's location
double currentLatitude = Get.find<LocationController>().myLocation.latitude;
double currentLongitude =
Get.find<LocationController>().myLocation.longitude;
@@ -73,22 +67,28 @@ class RideAvailableController extends GetxController {
);
}
// void sortRidesByDistance() {
// rideAvailableMap['message'].sort((a, b) {
// double distanceA = calculateDistance(a['start_location']);
// double distanceB = calculateDistance(b['start_location']);
// return distanceA.compareTo(distanceB);
// });
// }
// A helper function to safely show dialogs after the build cycle is complete.
void _showDialogAfterBuild(Widget dialog) {
// FIX 2: Use addPostFrameCallback to ensure dialogs are shown after the build process.
// This resolves the "visitChildElements() called during build" error.
WidgetsBinding.instance.addPostFrameCallback((_) {
Get.dialog(
dialog,
barrierDismissible: true,
transitionCurve: Curves.easeOutBack,
transitionDuration: const Duration(milliseconds: 200),
);
});
}
getRideAvailable() async {
Future<void> getRideAvailable() async {
try {
isLoading = true;
update();
LatLngBounds bounds = calculateBounds(
Get.find<LocationController>().myLocation!.latitude,
Get.find<LocationController>().myLocation!.longitude,
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
4000);
var payload = {
@@ -101,85 +101,108 @@ class RideAvailableController extends GetxController {
var res =
await CRUD().get(link: AppLink.getRideWaiting, payload: payload);
isLoading = false; // Request is complete, stop loading indicator.
if (res != 'failure') {
rideAvailableMap = jsonDecode(res);
isLoading = false;
update();
final decodedResponse = jsonDecode(res);
// Check for valid response structure
if (decodedResponse is Map &&
decodedResponse.containsKey('message') &&
decodedResponse['message'] is List) {
rideAvailableMap = decodedResponse;
// If the list of rides is empty, show the "No Rides" dialog
if ((rideAvailableMap['message'] as List).isEmpty) {
_showDialogAfterBuild(_buildNoRidesDialog());
}
} else {
// If response format is unexpected, treat as no rides and show dialog
rideAvailableMap = {'message': []};
_showDialogAfterBuild(_buildNoRidesDialog());
}
update(); // Update the UI with new data (or empty list)
} else {
// This block now handles network/server errors correctly
HapticFeedback.lightImpact();
Get.dialog(
CupertinoAlertDialog(
title: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
CupertinoIcons.car,
size: 44,
color: CupertinoColors.systemGrey,
),
const SizedBox(height: 12),
Text(
"No Rides Available".tr,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
],
),
content: Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"Please check back later for available rides.".tr,
style: const TextStyle(
fontSize: 13,
color: CupertinoColors.systemGrey,
),
),
),
actions: [
CupertinoDialogAction(
onPressed: () {
Get.back();
Get.back();
},
child: Text('OK'.tr),
),
],
),
barrierDismissible: true,
transitionCurve: Curves.easeOutBack,
transitionDuration: const Duration(milliseconds: 200),
);
update(); // Update UI to turn off loader
// Show a proper error dialog instead of "No Rides"
_showDialogAfterBuild(
_buildErrorDialog("Failed to fetch rides. Please try again.".tr));
}
} catch (e) {
isLoading = false;
update();
Get.dialog(
CupertinoAlertDialog(
title: const Icon(
CupertinoIcons.exclamationmark_triangle_fill,
color: CupertinoColors.systemRed,
size: 44,
),
content: Text(
"Error fetching rides. Please try again.".tr,
style: const TextStyle(fontSize: 14),
),
actions: [
CupertinoDialogAction(
onPressed: () => Get.back(),
child: Text('OK'.tr),
),
],
),
);
// This catches other exceptions like JSON parsing errors
_showDialogAfterBuild(
_buildErrorDialog("An unexpected error occurred.".tr));
}
}
// Extracted dialogs into builder methods for cleanliness.
Widget _buildNoRidesDialog() {
return CupertinoAlertDialog(
title: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
CupertinoIcons.car,
size: 44,
color: CupertinoColors.systemGrey,
),
const SizedBox(height: 12),
Text(
"No Rides Available".tr,
style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600),
),
],
),
content: Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
"Please check back later for available rides.".tr,
style:
const TextStyle(fontSize: 13, color: CupertinoColors.systemGrey),
),
),
actions: [
CupertinoDialogAction(
onPressed: () {
Get.back(); // Close dialog
Get.back(); // Go back from AvailableRidesPage
},
child: Text('OK'.tr),
),
],
);
}
Widget _buildErrorDialog(String error) {
// You can log the error here for debugging.
// print("Error fetching rides: $error");
return CupertinoAlertDialog(
title: const Icon(
CupertinoIcons.exclamationmark_triangle_fill,
color: CupertinoColors.systemRed,
size: 44,
),
content: Text(
error, // Display the specific error message passed to the function
style: const TextStyle(fontSize: 14),
),
actions: [
CupertinoDialogAction(
onPressed: () {
Get.back(); // Close dialog
Get.back(); // Go back from AvailableRidesPage
},
child: Text('OK'.tr),
),
],
);
}
@override
void onInit() {
getRideAvailable();
super.onInit();
getRideAvailable();
}
}