293 lines
11 KiB
Dart
Executable File
293 lines
11 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:sefer_driver/constant/colors.dart';
|
|
import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart';
|
|
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
|
|
import '../../../../constant/box_name.dart';
|
|
import '../../../../constant/style.dart';
|
|
import '../../../../controller/firebase/notification_service.dart';
|
|
import '../../../../main.dart';
|
|
import 'package:sefer_driver/views/widgets/mydialoug.dart';
|
|
|
|
class PassengerInfoWindow extends StatelessWidget {
|
|
PassengerInfoWindow({super.key});
|
|
|
|
// Optimization: defining static styles here avoids rebuilding them every frame
|
|
final TextStyle _labelStyle =
|
|
AppStyle.title.copyWith(color: Colors.grey[600], fontSize: 13);
|
|
final TextStyle _valueStyle =
|
|
AppStyle.title.copyWith(fontWeight: FontWeight.bold, fontSize: 18);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Get safe area top padding (for Notches/Status bars)
|
|
final double topPadding = MediaQuery.of(context).padding.top;
|
|
final double topMargin = topPadding + 10; // Safe area + 10px spacing
|
|
|
|
return GetBuilder<MapDriverController>(
|
|
builder: (controller) => AnimatedPositioned(
|
|
duration: const Duration(milliseconds: 400),
|
|
curve: Curves.easeInOut,
|
|
// FIX: Use calculated top margin to avoid hiding behind status bar
|
|
top: controller.isPassengerInfoWindow ? topMargin : -250.0,
|
|
left: 15.0,
|
|
right: 15.0,
|
|
child: Card(
|
|
// Optimization: Lower elevation slightly for smoother animation on cheap phones
|
|
elevation: 4,
|
|
shadowColor: Colors.black.withOpacity(0.2),
|
|
color: Colors.white,
|
|
surfaceTintColor: Colors.white, // Fix for Material 3 tinting
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
child: Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
_buildTopInfoRow(controller),
|
|
const Divider(height: 16),
|
|
|
|
if (!controller.isRideBegin) _buildActionButtons(controller),
|
|
|
|
// Optimization: Only render linear indicator if needed
|
|
if (controller.remainingTimeInPassengerLocatioWait < 300 &&
|
|
controller.remainingTimeInPassengerLocatioWait != 0 &&
|
|
!controller.isRideBegin) ...[
|
|
const SizedBox(height: 10),
|
|
_buildWaitingIndicator(controller),
|
|
],
|
|
|
|
if (controller.isdriverWaitTimeEnd &&
|
|
!controller.isRideBegin) ...[
|
|
const SizedBox(height: 10),
|
|
_buildCancelAfterWaitButton(controller),
|
|
]
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTopInfoRow(MapDriverController controller) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start, // Align top
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Go to passenger:'.tr, style: _labelStyle),
|
|
const SizedBox(height: 2),
|
|
Text(
|
|
controller.passengerName ?? 'loading...',
|
|
style: _valueStyle,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 10), // Spacing between name and chips
|
|
Column(
|
|
// Changed to Column for better layout on small screens
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
_buildInfoChip(Icons.map_outlined, '${controller.distance} km'),
|
|
const SizedBox(height: 6), // Vertical spacing
|
|
_buildInfoChip(
|
|
Icons.timer_outlined,
|
|
controller.hours > 1
|
|
? '${controller.hours}h ${controller.minutes}m'
|
|
: '${controller.minutes}m',
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildInfoChip(IconData icon, String text) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
|
decoration: BoxDecoration(
|
|
color: AppColor.primaryColor.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(icon, color: AppColor.primaryColor, size: 14), // Smaller icon
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
text,
|
|
style: TextStyle(
|
|
color: AppColor.primaryColor,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 12 // Slightly smaller font for chips
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildActionButtons(MapDriverController controller) {
|
|
return Row(
|
|
children: [
|
|
if (controller.isArrivedSend)
|
|
Expanded(
|
|
flex: 1,
|
|
child: SizedBox(
|
|
height: 45, // Fixed height for consistency
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColor.yellowColor,
|
|
foregroundColor: Colors.black,
|
|
padding: EdgeInsets.zero, // Reduce padding to fit text
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10)),
|
|
),
|
|
onPressed: () async {
|
|
// LOGIC FIX: Check distance FIRST
|
|
double distance = await controller
|
|
.calculateDistanceBetweenDriverAndPassengerLocation();
|
|
|
|
if (distance < 140) {
|
|
// Only draw route and send notif if close enough
|
|
controller.getRoute(
|
|
origin: controller.latLngPassengerLocation,
|
|
destination: controller.latLngPassengerDestination,
|
|
routeColor: Colors.blue);
|
|
|
|
NotificationService.sendNotification(
|
|
target: controller.tokenPassenger.toString(),
|
|
title: 'Hi ,I Arrive your site'.tr,
|
|
body: 'I Arrive at your site'.tr,
|
|
isTopic: false,
|
|
tone: 'ding',
|
|
driverList: [],
|
|
category: 'Hi ,I Arrive your site',
|
|
);
|
|
controller.startTimerToShowDriverWaitPassengerDuration();
|
|
controller.isArrivedSend = false;
|
|
} else {
|
|
MyDialog().getDialog(
|
|
'You are not near'.tr, // Shortened title
|
|
'Please go to the pickup location exactly'.tr,
|
|
() => Get.back());
|
|
}
|
|
},
|
|
// Using Row instead of .icon constructor for better control
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.location_on, size: 16),
|
|
const SizedBox(width: 4),
|
|
Flexible(
|
|
child: Text('I Arrive'.tr,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: const TextStyle(fontSize: 12))),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (controller.isArrivedSend) const SizedBox(width: 8),
|
|
Expanded(
|
|
flex: 2, // Give "Start" button more space
|
|
child: SizedBox(
|
|
height: 45,
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColor.greenColor,
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10)),
|
|
),
|
|
onPressed: () {
|
|
MyDialog().getDialog(
|
|
"Is the Passenger in your Car?".tr,
|
|
"Don't start trip if passenger not in your car".tr,
|
|
() async {
|
|
await controller.startRideFromDriver();
|
|
Get.back();
|
|
},
|
|
);
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.play_arrow_rounded, size: 22),
|
|
const SizedBox(width: 6),
|
|
Flexible(
|
|
child: Text('Start the Ride'.tr,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: const TextStyle(fontWeight: FontWeight.bold))),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildWaitingIndicator(MapDriverController controller) {
|
|
return Column(
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(10),
|
|
child: LinearProgressIndicator(
|
|
backgroundColor: AppColor.greyColor.withOpacity(0.2),
|
|
// Ternary for color is fine
|
|
color: controller.remainingTimeInPassengerLocatioWait < 60
|
|
? AppColor.redColor
|
|
: AppColor.greenColor,
|
|
minHeight: 8, // Thinner looks more modern
|
|
value: controller.progressInPassengerLocationFromDriver.toDouble(),
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
"${'Waiting'.tr}: ${controller.stringRemainingTimeWaitingPassenger}",
|
|
style: AppStyle.title.copyWith(
|
|
color: Colors.grey[700],
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildCancelAfterWaitButton(MapDriverController controller) {
|
|
return MyElevatedButton(
|
|
title: 'Cancel Trip & Get Cost'.tr, // Shortened text
|
|
kolor: AppColor.gold,
|
|
onPressed: () {
|
|
MyDialog().getDialog('Are you sure to cancel?'.tr, '', () async {
|
|
NotificationService.sendNotification(
|
|
target: controller.tokenPassenger.toString(),
|
|
title: 'Driver Cancelled Your Trip'.tr,
|
|
body: 'You will need to pay the cost...',
|
|
isTopic: false,
|
|
tone: 'cancel',
|
|
driverList: [],
|
|
category: 'Driver Cancelled Your Trip',
|
|
);
|
|
box.write(BoxName.rideStatus, 'Cancel');
|
|
await controller.addWaitingTimeCostFromPassengerToDriverWallet();
|
|
controller.isdriverWaitTimeEnd = false;
|
|
Get.back();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|