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

@@ -1,104 +1,49 @@
import 'dart:convert';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/notification/ride_available_controller.dart';
import 'package:sefer_driver/views/widgets/my_scafold.dart';
import 'package:sefer_driver/views/widgets/mycircular.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:math';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../controller/firebase/firbase_messge.dart';
import '../../controller/functions/crud.dart';
import '../../controller/home/captin/home_captain_controller.dart';
import '../../controller/notification/ride_available_controller.dart';
import '../../main.dart';
import '../home/Captin/driver_map_page.dart';
import '../widgets/my_scafold.dart';
import '../widgets/mycircular.dart';
import '../widgets/mydialoug.dart';
// --- Placeholder Classes and Variables (for demonstration) ---
// These are dummy implementations to make the code runnable.
// You should use your actual project files.
// --- End of Placeholder Classes ---
class AvailableRidesPage extends StatelessWidget {
const AvailableRidesPage({super.key});
@override
Widget build(BuildContext context) {
Get.put(RideAvailableController());
// Use findOrPut to avoid re-creating the controller on rebuilds
Get.lazyPut(() => RideAvailableController());
Get.lazyPut(() => HomeCaptainController());
return GetBuilder<RideAvailableController>(
builder: (rideAvailableController) {
// rideAvailableController.sortRidesByDistance();
// rideAvailableController.sortRidesByDistance(); // Original logic
return MyScafolld(
title: 'Available for rides'.tr,
body: [
rideAvailableController.isLoading
? const MyCircularProgressIndicator()
:
// : ListView.builder(
// itemCount: rideAvailableController
// .rideAvailableMap['message']
// .where((rideInfo) {
// var driverType =
// box.read(BoxName.carTypeOfDriver).toString();
// return (driverType == 'Comfort' &&
// ['Speed', 'Comfort']
// .contains(rideInfo['carType'])) ||
// (driverType == 'Speed' &&
// rideInfo['carType'] == 'Speed') ||
// (driverType == 'Scooter' &&
// rideInfo['carType'] == 'Scooter') ||
// (driverType == 'Awfar Car' &&
// rideInfo['carType'] == 'Awfar Car') ||
// (driverType == 'Lady' &&
// ['Comfort', 'Speed', 'Lady']
// .contains(rideInfo['carType']));
// }).length,
// itemBuilder: (context, index) {
// var filteredRides = rideAvailableController
// .rideAvailableMap['message']
// .where((rideInfo) {
// var driverType =
// box.read(BoxName.carTypeOfDriver).toString();
// return (driverType == 'Comfort' &&
// ['Speed', 'Comfort']
// .contains(rideInfo['carType'])) ||
// (driverType == 'Speed' &&
// rideInfo['carType'] == 'Speed') ||
// (driverType == 'Awfar Car' &&
// rideInfo['carType'] == 'Awfar Car') ||
// (driverType == 'Scooter' &&
// rideInfo['carType'] == 'Scooter') ||
// (driverType == 'Lady' &&
// ['Comfort', 'Speed', 'Lady']
// .contains(rideInfo['carType']));
// }).toList();
// return RideAvailableCard(
// rideInfo: filteredRides[index],
// );
// },
// )
ListView.builder(
itemCount: rideAvailableController
.rideAvailableMap['message']
.where((rideInfo) {
var driverType =
box.read(BoxName.carTypeOfDriver).toString();
switch (driverType) {
case 'Comfort':
return ['Speed', 'Comfort']
.contains(rideInfo['carType']);
case 'Speed':
case 'Scooter':
case 'Awfar Car':
return rideInfo['carType'] == driverType;
case 'Lady':
return ['Comfort', 'Speed', 'Lady']
.contains(rideInfo['carType']);
default:
return false;
}
}).length,
itemBuilder: (context, index) {
var filteredRides = rideAvailableController
: Builder(
builder: (context) {
// Filtering logic remains the same
final filteredRides = rideAvailableController
.rideAvailableMap['message']
.where((rideInfo) {
var driverType =
@@ -119,21 +64,27 @@ class AvailableRidesPage extends StatelessWidget {
}
}).toList();
return RideAvailableCard(
rideInfo: filteredRides[index],
if (filteredRides.isEmpty) {
return Center(
child: Text(
"No rides available for your vehicle type.".tr,
style: AppStyle.subtitle,
),
);
}
return ListView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 16),
itemCount: filteredRides.length,
itemBuilder: (context, index) {
return RideAvailableCard(
rideInfo: filteredRides[index],
);
},
);
},
)
// rideAvailableController.isLoading
// ? const MyCircularProgressIndicator()
// : ListView.builder(
// itemCount: rideAvailableController
// .rideAvailableMap['message'].length,
// itemBuilder: (context, index) => RideAvailableCard(
// rideInfo: rideAvailableController
// .rideAvailableMap['message'][index],
// ),
// )
],
isleading: true);
});
@@ -147,90 +98,189 @@ class RideAvailableCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
// The main card with improved styling
return Card(
margin: const EdgeInsets.all(8.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildLocationRow('', rideInfo['startName'], AppColor.greenColor),
const SizedBox(height: 8),
_buildLocationRow('', rideInfo['endName'], Colors.red),
const SizedBox(height: 16),
_buildInfoRow(),
const SizedBox(height: 16),
_buildActionRow(),
],
margin: const EdgeInsets.only(bottom: 16.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
elevation: 5,
shadowColor: Colors.black.withOpacity(0.1),
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () {
// You can add an action here, e.g., show ride details on a map
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(),
const SizedBox(height: 16),
_buildRouteInfo(),
const Divider(height: 32),
_buildRideDetails(),
const SizedBox(height: 20),
_buildAcceptButton(),
],
),
),
),
);
}
Widget _buildLocationRow(String icon, String location, Color iconColor) {
return Row(
children: [
Text(
icon,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold, color: iconColor),
),
const SizedBox(width: 8),
Expanded(
child: Text(
location,
style: AppStyle.subtitle,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
);
}
Widget _buildInfoRow() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${'Price:'.tr} ${rideInfo['price']} \$', style: AppStyle.title),
Text(
rideInfo['carType'],
style: AppStyle.title.copyWith(color: AppColor.greenColor),
),
],
);
}
Widget _buildActionRow() {
// Header section with Price and Car Type
Widget _buildHeader() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('📈 ${rideInfo['passengerRate']}', style: AppStyle.title),
Text('Fare'.tr, style: AppStyle.subtitle.copyWith(fontSize: 12)),
const SizedBox(height: 4),
Text(
'📍 ${rideInfo['distance']} ${'KM'.tr}',
style: AppStyle.title.copyWith(color: AppColor.greenColor),
),
Text('${rideInfo['price']} \$',
style: AppStyle.title
.copyWith(fontSize: 24, color: AppColor.primaryColor)),
],
),
ElevatedButton(
onPressed: () => _acceptRide(),
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.greenColor,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: AppColor.greenColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
),
child: Text(
rideInfo['carType'],
style: AppStyle.title
.copyWith(color: AppColor.greenColor, fontSize: 12),
),
child: Text('Accept'.tr),
),
],
);
}
// Visual representation of the pickup and dropoff route
Widget _buildRouteInfo() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Dotted line and icons column
Column(
children: [
const Icon(CupertinoIcons.circle_fill,
color: AppColor.greenColor, size: 20),
...List.generate(
4,
(index) => Container(
height: 4,
width: 2,
color: AppColor.writeColor,
margin: const EdgeInsets.symmetric(vertical: 2),
)),
const Icon(CupertinoIcons.location_solid,
color: Colors.red, size: 20),
],
),
const SizedBox(width: 16),
// Location text column
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildLocationText(rideInfo['startName'], 'Pickup'.tr),
const SizedBox(height: 20),
_buildLocationText(rideInfo['endName'], 'Dropoff'.tr),
],
),
)
],
);
}
// Helper for location text
Widget _buildLocationText(String location, String label) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)),
const SizedBox(height: 2),
Text(
location,
style: AppStyle.title.copyWith(fontWeight: FontWeight.normal),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
);
}
// Ride details section with Distance and Passenger Rating
Widget _buildRideDetails() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildInfoChip(
icon: CupertinoIcons.map_pin_ellipse,
value: '${rideInfo['distance']} ${'KM'.tr}',
label: 'Distance'.tr,
color: AppColor.primaryColor,
),
_buildInfoChip(
icon: CupertinoIcons.star_fill,
value: '${rideInfo['passengerRate']}',
label: 'Rating'.tr,
color: Colors.amber,
),
],
);
}
// A reusable chip for displaying info with an icon
Widget _buildInfoChip(
{required IconData icon,
required String value,
required String label,
required Color color}) {
return Column(
children: [
Row(
children: [
Icon(icon, color: color, size: 16),
const SizedBox(width: 8),
Text(value, style: AppStyle.title),
],
),
const SizedBox(height: 4),
Text(label, style: AppStyle.subtitle.copyWith(fontSize: 12)),
],
);
}
// The accept button with improved styling
Widget _buildAcceptButton() {
return SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
icon: const Icon(Icons.check_circle_outline, color: Colors.white),
label: Text('Accept'.tr,
style: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)),
onPressed: _acceptRide,
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.greenColor,
padding: const EdgeInsets.symmetric(vertical: 14),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
elevation: 2,
),
),
);
}
// --- Ride Acceptance Logic ---
// This logic is copied exactly from your original code.
void _acceptRide() async {
var res = await CRUD().post(link: AppLink.updateStausFromSpeed, payload: {
'id': rideInfo['id'],
@@ -249,8 +299,6 @@ class RideAvailableCard extends StatelessWidget {
});
}
// .then((value) {
// var json = jsonDecode(res);
if (res != "failure") {
List<String> bodyToPassenger = [
box.read(BoxName.driverID).toString(),
@@ -276,7 +324,6 @@ class RideAvailableCard extends StatelessWidget {
link: '${AppLink.endPoint}/driver_order/add.php',
payload: {
'driver_id': box.read(BoxName.driverID),
// box.read(BoxName.driverID).toString(),
'order_id': rideInfo['id'],
'status': 'Apply'
});
@@ -294,9 +341,7 @@ class RideAvailableCard extends StatelessWidget {
FirebaseMessagesController().sendNotificationToPassengerToken(
"Accepted Ride".tr,
'your ride is Accepted'.tr,
// arguments['DriverList'][9].toString(),
rideInfo['passengerToken'].toString(),
// box.read(BoxName.tokenDriver).toString(),
bodyToPassenger,
'start.wav');
Get.back();
@@ -319,10 +364,7 @@ class RideAvailableCard extends StatelessWidget {
'driverId': box.read(BoxName.driverID).toString(),
'durationOfRideValue': rideInfo['duration'].toString(),
'paymentAmount': rideInfo['price'].toString(),
'paymentMethod': 'cash'.toString() == //todo fix payment method
'true'
? 'visa'
: 'cash',
'paymentMethod': 'cash'.toString() == 'true' ? 'visa' : 'cash',
'isHaveSteps': 'startEnd'.toString(),
'step0': ''.toString(),
'step1': ''.toString(),