194 lines
7.4 KiB
Dart
194 lines
7.4 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:driver/constant/constant.dart';
|
|
import 'package:driver/constant/send_notification.dart';
|
|
import 'package:driver/models/parcel_category.dart';
|
|
import 'package:driver/models/parcel_order_model.dart';
|
|
import 'package:driver/models/user_model.dart';
|
|
import 'package:driver/utils/fire_store_utils.dart';
|
|
import 'package:driver/widget/geoflutterfire/src/geoflutterfire.dart';
|
|
import 'package:driver/widget/geoflutterfire/src/models/point.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|
import 'package:google_maps_flutter/google_maps_flutter.dart' as latlong;
|
|
import 'package:intl/intl.dart';
|
|
|
|
class ParcelSearchController extends GetxController {
|
|
// Implement parcel search logic here
|
|
|
|
RxBool isLoading = true.obs;
|
|
final Rx<TextEditingController> sourceTextEditController = TextEditingController().obs;
|
|
final Rx<TextEditingController> destinationTextEditController = TextEditingController().obs;
|
|
final Rx<TextEditingController> dateTimeTextEditController = TextEditingController().obs;
|
|
|
|
// Journey
|
|
final Rx<LatLng?> departureLatLong = Rx<LatLng?>(null);
|
|
final Rx<LatLng?> destinationLatLong = Rx<LatLng?>(null);
|
|
final Rx<latlong.LatLng?> departureLatLongOsm = Rx<latlong.LatLng?>(null);
|
|
final Rx<latlong.LatLng?> destinationLatLongOsm = Rx<latlong.LatLng?>(null);
|
|
|
|
Rx<DateTime> pickUpDateTime = DateTime.now().obs;
|
|
RxList<ParcelOrderModel> parcelList = <ParcelOrderModel>[].obs;
|
|
|
|
Rx<UserModel> driverModel = UserModel().obs;
|
|
Rx<UserModel> ownerModel = UserModel().obs;
|
|
|
|
@override
|
|
void onInit() {
|
|
isLoading.value = false;
|
|
driverModel.value = Constant.userModel!;
|
|
// TODO: implement onInit
|
|
if (driverModel.value.ownerId != null && driverModel.value.ownerId!.isNotEmpty) {
|
|
getOwnerDetails(driverModel.value.ownerId!);
|
|
}
|
|
loadParcelCategories();
|
|
super.onInit();
|
|
}
|
|
|
|
String formatDate(Timestamp timestamp) {
|
|
final dateTime = timestamp.toDate();
|
|
return DateFormat("dd MMM yyyy, hh:mm a").format(dateTime);
|
|
}
|
|
|
|
Future<void> getOwnerDetails(String ownerId) async {
|
|
ownerModel.value = await FireStoreUtils.getUserProfile(ownerId) ?? UserModel();
|
|
update();
|
|
}
|
|
|
|
void searchParcel() {
|
|
searchParcelsOnce(
|
|
srcLat: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value!.latitude : departureLatLong.value!.latitude,
|
|
srcLng: Constant.selectedMapType == 'osm' ? departureLatLongOsm.value!.longitude : departureLatLong.value!.longitude,
|
|
destLat: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value?.latitude : destinationLatLong.value?.latitude,
|
|
destLng: Constant.selectedMapType == 'osm' ? destinationLatLongOsm.value?.longitude : destinationLatLong.value?.longitude,
|
|
date: pickUpDateTime.value, // required
|
|
).then(
|
|
(event) {
|
|
parcelList.value = event;
|
|
update();
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<void> acceptParcelBooking(ParcelOrderModel parcelBookingData) async {
|
|
parcelBookingData.status = Constant.driverAccepted;
|
|
parcelBookingData.driver = Constant.userModel;
|
|
parcelBookingData.driverId = Constant.userModel!.id;
|
|
parcelBookingData.receiverPickupDateTime = Timestamp.fromDate(DateTime.now());
|
|
|
|
await FireStoreUtils.setParcelOrder(parcelBookingData);
|
|
Map<String, dynamic> payLoad = <String, dynamic>{"type": "parcel_order", "orderId": parcelBookingData.id};
|
|
await SendNotification.sendFcmMessage(Constant.parcelAccepted, parcelBookingData.author!.fcmToken.toString(), payLoad);
|
|
Get.back(result: true);
|
|
}
|
|
|
|
String calculateParcelTotalAmountBooking(ParcelOrderModel parcelBookingData) {
|
|
String subTotal = parcelBookingData.subTotal.toString();
|
|
String discount = parcelBookingData.discount ?? "0.0";
|
|
String taxAmount = "0.0";
|
|
for (var element in parcelBookingData.taxSetting!) {
|
|
taxAmount = (double.parse(taxAmount) + Constant.calculateTax(amount: (double.parse(subTotal) - double.parse(discount)).toString(), taxModel: element))
|
|
.toStringAsFixed(int.tryParse(Constant.currencyModel!.decimalDigits.toString()) ?? 2);
|
|
}
|
|
|
|
return ((double.parse(subTotal) - (double.parse(discount))) + double.parse(taxAmount)).toStringAsFixed(int.tryParse(Constant.currencyModel!.decimalDigits.toString()) ?? 2);
|
|
}
|
|
|
|
Future<List<ParcelOrderModel>> searchParcelsOnce({
|
|
required double srcLat,
|
|
required double srcLng,
|
|
double? destLat,
|
|
double? destLng,
|
|
required DateTime date,
|
|
}) async {
|
|
final ref = FireStoreUtils.fireStore.collection("parcel_orders").where("sectionId",isEqualTo: driverModel.value.sectionId).where('status', isEqualTo: "Order Placed");
|
|
|
|
GeoFirePoint center = Geoflutterfire().point(latitude: srcLat, longitude: srcLng);
|
|
|
|
// Take first snapshot from the stream
|
|
final docs = await Geoflutterfire()
|
|
.collection(collectionRef: ref)
|
|
.within(
|
|
center: center,
|
|
radius: double.parse(Constant.parcelRadius),
|
|
field: "sourcePoint",
|
|
strictMode: true,
|
|
)
|
|
.first;
|
|
|
|
final filtered = docs.where((doc) {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
if (data['senderPickupDateTime'] == null) return false;
|
|
|
|
final driverZoneId = driverModel.value.zoneId;
|
|
|
|
// ✅ Check both sender and receiver zone
|
|
final senderZoneId = data['senderZoneId'];
|
|
final receiverZoneId = data['receiverZoneId'];
|
|
|
|
if (senderZoneId == null && receiverZoneId == null) return false;
|
|
|
|
// Match if driver zone equals either sender or receiver zone
|
|
final zoneMatch = (senderZoneId == driverZoneId) || (receiverZoneId == driverZoneId);
|
|
if (!zoneMatch) return false;
|
|
|
|
// ✅ Date check
|
|
final Timestamp ts = data['senderPickupDateTime'];
|
|
final orderDate = ts.toDate().toLocal();
|
|
final inputDate = date.toLocal();
|
|
|
|
bool sameDay = orderDate.year == inputDate.year && orderDate.month == inputDate.month && orderDate.day == inputDate.day;
|
|
|
|
if (!sameDay) return false;
|
|
|
|
// ✅ Destination check
|
|
if (destLat != null && destLng != null && data['receiverLatLong'] != null) {
|
|
final rec = data['receiverLatLong'];
|
|
double recLat = rec['latitude'];
|
|
double recLng = rec['longitude'];
|
|
|
|
double distance = Geoflutterfire().point(latitude: destLat, longitude: destLng).kmDistance(lat: recLat, lng: recLng);
|
|
|
|
if (distance > double.parse(Constant.parcelRadius)) return false;
|
|
}
|
|
|
|
return true;
|
|
}).toList();
|
|
|
|
return filtered.map((e) => ParcelOrderModel.fromJson(e.data()!)).toList();
|
|
}
|
|
|
|
Future<void> pickDateTime() async {
|
|
DateTime? date = await showDatePicker(
|
|
context: Get.context!,
|
|
initialDate: pickUpDateTime.value,
|
|
firstDate: DateTime.now(),
|
|
lastDate: DateTime(2100),
|
|
);
|
|
|
|
if (date == null) return;
|
|
pickUpDateTime.value = date;
|
|
dateTimeTextEditController.value.text = DateFormat('dd-MMM-yyyy').format(date);
|
|
update();
|
|
}
|
|
|
|
RxList<ParcelCategory> parcelCategory = <ParcelCategory>[].obs;
|
|
|
|
|
|
void loadParcelCategories() async {
|
|
final categories = await FireStoreUtils.getParcelServiceCategory();
|
|
parcelCategory.value = categories;
|
|
}
|
|
|
|
ParcelCategory? getSelectedCategory(ParcelOrderModel parcelOrder) {
|
|
try {
|
|
return parcelCategory.firstWhere(
|
|
(cat) => cat.title?.toLowerCase().trim() == parcelOrder.parcelType?.toLowerCase().trim(),
|
|
orElse: () => ParcelCategory(),
|
|
);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|