Files
tripz/lib/views/home/map_widget.dart/apply_order_widget.dart
Hamza-Ayed 3162b1bec6 25-2/24/1
2025-02-24 23:38:42 +03:00

406 lines
13 KiB
Dart

import 'package:Tripz/constant/colors.dart';
import 'package:Tripz/constant/links.dart';
import 'package:Tripz/constant/style.dart';
import 'package:Tripz/controller/firebase/firbase_messge.dart';
import 'package:Tripz/controller/home/map_passenger_controller.dart';
import 'package:Tripz/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../../constant/box_name.dart';
import '../../../controller/functions/launch.dart';
import '../../widgets/my_textField.dart';
class ApplyOrderWidget extends StatelessWidget {
const ApplyOrderWidget({super.key});
@override
Widget build(BuildContext context) {
Color _parseColor(String colorHex) {
if (colorHex.isEmpty) return Colors.grey;
String processedHex = colorHex.replaceFirst('#', '0xff').trim();
return Color(int.parse(processedHex.startsWith('0xff')
? processedHex
: '0xff$processedHex'));
}
return GetBuilder<MapPassengerController>(builder: (controller) {
if (controller.statusRide == 'Apply' && !controller.isSearchingWindow) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
// More modern BoxDecoration
color: Theme.of(context).cardColor,
borderRadius:
const BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [BoxShadow(blurRadius: 10, color: Colors.black12)],
),
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildPriceInfo(context, controller),
const SizedBox(height: 16),
_buildDriverInfoCard(context, controller, _parseColor),
],
),
),
);
} else {
return const SizedBox();
}
});
}
Widget _buildPriceInfo(
BuildContext context, MapPassengerController controller) {
return InkWell(
onTap: () {
String message;
if (box.read(BoxName.carType) == 'Speed' ||
box.read(BoxName.carType) == 'Awfar Car' ||
box.read(BoxName.carType) == 'Delivery') {
message =
'This ride type does not allow changes to the destination or additional stops'
.tr;
} else {
message =
'This ride type allows changes, but the price may increase'.tr;
}
Get.snackbar(
'This price is'.tr +
' ${controller.totalPassenger.toStringAsFixed(2)}'.tr,
message,
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 2),
backgroundColor:
AppColor.yellowColor.withOpacity(0.8), // More subtle background
);
},
child: Center(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'The driver accepted your order for'.tr} ',
style: AppStyle.title),
TextSpan(
text: controller.totalPassenger.toStringAsFixed(2),
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold, color: AppColor.redColor),
),
TextSpan(text: ' ${'LE'.tr}', style: AppStyle.title),
],
),
textAlign: TextAlign.center,
),
),
);
}
Widget _buildDriverInfoCard(BuildContext context,
MapPassengerController controller, Color Function(String) parseColor) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).canvasColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(box.read(BoxName.carType.toString()),
style:
AppStyle.title.copyWith(fontWeight: FontWeight.w500)),
Row(
children: [
_buildCarDetails(context, controller),
const SizedBox(width: 10),
_buildCarImage(controller, parseColor),
],
),
],
),
),
const Divider(height: 1, thickness: 1, color: Colors.grey),
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildDriverAvatarAndInfo(controller),
_buildContactButtons(context, controller),
],
),
),
Padding(
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, bottom: 12.0),
child: controller.isDriverArrivePassenger
? const DriverArrivePassengerAndWaitMinute()
: const TimeDriverToPassenger(),
),
],
),
);
}
Widget _buildCarDetails(
BuildContext context, MapPassengerController controller) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(controller.model.toString(), style: AppStyle.title),
Text(controller.licensePlate.toString(),
style: Theme.of(context).textTheme.bodyMedium),
Text(controller.carColor.toString(),
style: Theme.of(context).textTheme.bodyMedium),
],
);
}
Widget _buildCarImage(
MapPassengerController controller, Color Function(String) parseColor) {
return ColorFiltered(
colorFilter:
ColorFilter.mode(parseColor(controller.colorHex), BlendMode.srcIn),
child: Image.asset(
box.read(BoxName.carType) == 'Scooter' ||
box.read(BoxName.carType) == 'Pink Bike'
? 'assets/images/moto.png'
: 'assets/images/car3.png',
height: 60,
),
);
}
Widget _buildDriverAvatarAndInfo(MapPassengerController controller) {
return Row(
children: [
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(
'${AppLink.server}/portrate_captain_image/${controller.driverId}.jpg'),
onBackgroundImageError: (exception, stackTrace) =>
const Icon(Icons.person, size: 30, color: AppColor.blueColor),
),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(controller.driverName,
style: AppStyle.title.copyWith(fontWeight: FontWeight.w500)),
Text('${controller.driverRate}',
style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
],
);
}
Widget _buildContactButtons(
BuildContext context, MapPassengerController controller) {
return Row(
children: [
IconButton(
onPressed: () => _showContactOptionsDialog(context, controller),
icon: const Icon(Icons.message, color: AppColor.blueColor, size: 28),
),
IconButton(
onPressed: () {
HapticFeedback.heavyImpact();
makePhoneCall(controller.driverPhone);
},
icon: const Icon(Icons.call, color: AppColor.greenColor, size: 28),
),
],
);
}
void _showContactOptionsDialog(
BuildContext context, MapPassengerController controller) {
Get.defaultDialog(
title: 'Contact Options'.tr,
content: SizedBox(
width: 300,
height: Get.height * .4,
child: ListView(
// shrinkWrap: true,
children: [
..._buildPredefinedMessages(controller),
const SizedBox(height: 8),
_buildCustomMessageInput(controller, context),
],
),
),
);
}
List<Widget> _buildPredefinedMessages(MapPassengerController controller) {
const messages = [
'Hello, I\'m at the agreed-upon location',
'My location is correct. You can search for me using the navigation app',
'I\'m waiting for you',
"How much longer will you be?",
];
return messages
.map((message) => Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: ElevatedButton(
onPressed: () {
Get.find<FirebaseMessagesController>()
.sendNotificationToDriverMAP(
'message From passenger',
message.tr,
controller.driverToken.toString(),
[],
'ding.wav',
);
Get.back();
},
child: Text(message.tr),
),
))
.toList();
}
Widget _buildCustomMessageInput(
MapPassengerController controller, BuildContext context) {
return Row(
children: [
Expanded(
child: Form(
key: controller.messagesFormKey,
child: MyTextForm(
controller: controller.messageToDriver,
label: 'Send a custom message'.tr,
hint: 'Type your message'.tr,
type: TextInputType.text,
),
),
),
IconButton(
onPressed: () {
if (controller.messagesFormKey.currentState!.validate()) {
Get.find<FirebaseMessagesController>()
.sendNotificationToDriverMAP(
'message From passenger',
controller.messageToDriver.text,
controller.driverToken,
[],
'ding.wav',
);
controller.messageToDriver.clear();
Get.back();
}
},
icon: const Icon(Icons.send),
),
],
);
}
}
class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
const DriverArrivePassengerAndWaitMinute({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) {
return Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: LinearProgressIndicator(
backgroundColor: AppColor.accentColor.withOpacity(0.3),
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 20,
value:
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
),
),
const SizedBox(height: 4),
Center(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'Driver is waiting at pickup.'.tr} ',
style: AppStyle.subtitle),
TextSpan(
text: controller
.stringRemainingTimeDriverWaitPassenger5Minute,
style: AppStyle.title),
],
),
textAlign: TextAlign.center,
),
),
],
);
});
}
}
class TimeDriverToPassenger extends StatelessWidget {
const TimeDriverToPassenger({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<MapPassengerController>(builder: (controller) {
return controller.isDriverInPassengerWay == false ||
controller.timeToPassengerFromDriverAfterApplied > 0
? Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: LinearProgressIndicator(
backgroundColor: AppColor.accentColor.withOpacity(0.3),
color: controller
.remainingTimeToPassengerFromDriverAfterApplied <
60
? AppColor.redColor
: AppColor.greenColor,
minHeight: 20,
value: controller
.progressTimerToPassengerFromDriverAfterApplied
.toDouble()
.clamp(0.0, 1.0),
),
),
const SizedBox(height: 4),
Center(
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: '${'Driver is on the way'.tr} ',
style: AppStyle.subtitle,
),
TextSpan(
text: controller.stringRemainingTimeToPassenger,
style: AppStyle.title,
),
],
),
textAlign: TextAlign.center,
),
),
],
)
: const SizedBox();
});
}
}