import 'dart:convert'; import 'dart:io'; import 'dart:math' as math; import 'dart:ui' as ui; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:driver/constant/show_toast_dialog.dart'; import 'package:driver/models/currency_model.dart'; import 'package:driver/models/language_model.dart'; import 'package:driver/models/mail_setting.dart'; import 'package:driver/models/section_model.dart'; import 'package:driver/models/tax_model.dart'; import 'package:driver/models/user_model.dart'; import 'package:driver/themes/app_them_data.dart'; import 'package:driver/utils/preferences.dart'; import 'package:driver/widget/permission_dialog.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:intl/intl.dart'; import 'package:location/location.dart'; import 'package:mailer/mailer.dart'; import 'package:mailer/smtp_server.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:uuid/uuid.dart'; import 'package:http/http.dart' as http; class Constant { static String userRoleDriver = 'driver'; static String userRoleCustomer = 'customer'; static String userRoleVendor = 'vendor'; static ShippingAddress selectedLocation = ShippingAddress(); static LocationData? locationDataFinal; static UserModel? userModel; static SectionModel? sectionModel; static const globalUrl = "https://Replace_your_domain/"; static bool isMaintenanceModeForDriver = false; static bool singleOrderReceive = false; static bool enableOTPTripStartForRental = true; static String driverLocationUpdate = '50'; static String minimumDepositToRideAccept = '0.0'; static String ownerMinimumDepositToRideAccept = '0.0'; static String minimumAmountToWithdrawal = '0.0'; static bool isDriverVerification = false; static bool isOwnerVerification = false; static bool enableOTPTripStart = false; static String parcelRadius = '0.0'; static String rentalRadius = '0.0'; static String mapAPIKey = ""; static String placeHolderImage = ""; static String defaultCountryCode = ""; static String defaultCountry = ""; static String senderId = ''; static String jsonNotificationFileURL = ''; static String distanceType = "km"; static String? referralAmount = "0.0"; static String googlePlayLink = ""; static String appStoreLink = ""; static String appVersion = ""; static String termsAndConditions = ""; static String privacyPolicy = ""; static String supportURL = ""; static String minimumAmountToDeposit = "0.0"; static String? mapType = "inappmap"; static bool? autoApproveDriver = true; static const String orderPlaced = "Order Placed"; static const String orderAccepted = "Order Accepted"; static const String orderRejected = "Order Rejected"; static const String driverPending = "Driver Pending"; static const String driverAccepted = "Driver Accepted"; static const String driverRejected = "Driver Rejected"; static const String orderShipped = "Order Shipped"; static const String orderInTransit = "In Transit"; static const String orderCompleted = "Order Completed"; static const String orderCancelled = "Order Cancelled"; static CurrencyModel? currencyModel; static List? taxList = []; static MailSettings? mailSettings; static String walletTopup = "wallet_topup"; static String newVendorSignup = "new_vendor_signup"; static String payoutRequestStatus = "payout_request_status"; static String payoutRequest = "payout_request"; static String newOrderPlaced = "new_order_placed"; static String scheduleOrder = "schedule_order"; static String dineInPlaced = "dinein_placed"; static String dineInCanceled = "dinein_canceled"; static String dineinAccepted = "dinein_accepted"; static String restaurantRejected = "restaurant_rejected"; static String driverCompleted = "driver_completed"; static String driverAcceptedNotification = "driver_accepted"; static String restaurantAccepted = "restaurant_accepted"; static String takeawayCompleted = "takeaway_completed"; static String parcelAccepted = "parcel_accepted"; static String parcelCompleted = "parcel_completed"; static String rentalAccepted = "rental_accepted"; static String rentalCompleted = "rental_completed"; static String selectedMapType = 'google'; static String orderRingtoneUrl = ''; static bool isSelfDeliveryFeature = false; static String amountShow({required String? amount}) { if (currencyModel!.symbolAtRight == true) { return "${double.parse(amount.toString()).toStringAsFixed(currencyModel!.decimalDigits ?? 0)} ${currencyModel!.symbol.toString()}"; } else { return "${currencyModel!.symbol.toString()} ${amount == null || amount.isEmpty ? "0.0" : double.parse(amount.toString()).toStringAsFixed(currencyModel!.decimalDigits ?? 0)}"; } } Future getBytesFromUrl(String url, {int width = 100}) async { final http.Response response = await http.get(Uri.parse(url)); if (response.statusCode != 200) { throw Exception("Failed to load image from $url"); } final Uint8List bytes = response.bodyBytes; // Decode & resize final ui.Codec codec = await ui.instantiateImageCodec(bytes, targetWidth: width); final ui.FrameInfo frameInfo = await codec.getNextFrame(); final ByteData? byteData = await frameInfo.image.toByteData(format: ui.ImageByteFormat.png); return byteData!.buffer.asUint8List(); } static Color statusText({required String? status}) { if (status == orderPlaced) { return AppThemeData.grey50; } else if (status == orderAccepted || status == orderCompleted) { return AppThemeData.grey50; } else if (status == orderRejected) { return AppThemeData.grey50; } else { return AppThemeData.grey900; } } static Color statusColor({required String? status}) { if (status == orderPlaced) { return AppThemeData.primary300; } else if (status == orderAccepted || status == orderCompleted) { return AppThemeData.success400; } else if (status == orderRejected) { return AppThemeData.danger300; } else { return AppThemeData.warning300; } } static double calculateTax({String? amount, TaxModel? taxModel}) { double taxAmount = 0.0; if (taxModel != null && taxModel.enable == true) { if (taxModel.type == "fix") { taxAmount = double.parse(taxModel.tax.toString()); } else { taxAmount = (double.parse(amount.toString()) * double.parse(taxModel.tax!.toString())) / 100; } } return taxAmount; } static double calculateAdminCommission({required String amount, required String adminCommissionType, required String adminCommission}) { double taxAmount = 0.0; if (adminCommissionType == "Percentage" || adminCommissionType == "percentage") { taxAmount = (double.parse(amount.toString()) * double.parse(adminCommission.toString())) / 100; } else { taxAmount = double.parse(adminCommission.toString()); } return taxAmount; } static String calculateReview({required String? reviewCount, required String? reviewSum}) { if (0 == double.parse(reviewSum.toString()) && 0 == double.parse(reviewSum.toString())) { return "0"; } return (double.parse(reviewSum.toString()) / double.parse(reviewCount.toString())).toStringAsFixed(1); } static const userPlaceHolder = 'assets/images/user_placeholder.png'; static String getUuid() { return const Uuid().v4(); } static Widget loader() { return Center( child: CircularProgressIndicator(color: AppThemeData.primary300), ); } static Widget showEmptyView({required String message,required bool isDark}) { return Center( child: Text(message, style: TextStyle(fontFamily: AppThemeData.medium, fontSize: 18, color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900)), ); } static String getReferralCode() { var rng = math.Random(); return (rng.nextInt(900000) + 100000).toString(); } static String maskingString(String documentId, int maskingDigit) { String maskedDigits = documentId; for (int i = 0; i < documentId.length - maskingDigit; i++) { maskedDigits = maskedDigits.replaceFirst(documentId[i], "*"); } return maskedDigits; } String? validateRequired(String? value, String type) { if (value!.isEmpty) { return '$type required'; } return null; } String? validateEmail(String? value) { String pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; RegExp regExp = RegExp(pattern); if (value == null || value.isEmpty) { return "Email is Required"; } else if (!regExp.hasMatch(value)) { return "Invalid Email"; } else { return null; } } static String getDistance({required String lat1, required String lng1, required String lat2, required String lng2}) { double distance; double distanceInMeters = Geolocator.distanceBetween( double.parse(lat1), double.parse(lng1), double.parse(lat2), double.parse(lng2), ); if (distanceType == "miles") { distance = distanceInMeters / 1609; } else { distance = distanceInMeters / 1000; } return distance.toStringAsFixed(2); } bool hasValidUrl(String value) { String pattern = r'(http|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?'; RegExp regExp = RegExp(pattern); if (value.isEmpty) { return false; } else if (!regExp.hasMatch(value)) { return false; } return true; } static Future uploadUserImageToFireStorage(File image, String filePath, String fileName) async { Reference upload = FirebaseStorage.instance.ref().child('$filePath/$fileName'); UploadTask uploadTask = upload.putFile(image); var downloadUrl = await (await uploadTask.whenComplete(() {})).ref.getDownloadURL(); return downloadUrl.toString(); } static Future makePhoneCall(String phoneNumber) async { final Uri launchUri = Uri( scheme: 'tel', path: phoneNumber, ); await launchUrl(launchUri); } Future launchURL(Uri url) async { if (!await launchUrl( url, mode: LaunchMode.externalApplication, )) { throw Exception('Could not launch $url'); } } Future getBytesFromAsset(String path, int width) async { ByteData data = await rootBundle.load(path); ui.Codec codec = await ui.instantiateImageCodec( data.buffer.asUint8List(), targetWidth: width, ); ui.FrameInfo fi = await codec.getNextFrame(); final Uint8List bytes = (await fi.image.toByteData(format: ui.ImageByteFormat.png))!.buffer.asUint8List(); return bytes; } static Future selectTime(context) async { FocusScope.of(context).requestFocus(FocusNode()); //remove focus TimeOfDay? newTime = await showTimePicker( context: context, initialTime: TimeOfDay.now(), ); if (newTime != null) { return newTime; } return null; } static Future selectDate(context) async { DateTime? pickedDate = await showDatePicker( context: context, builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: ColorScheme.light( primary: AppThemeData.primary300, // header background color onPrimary: AppThemeData.grey900, // header text color onSurface: AppThemeData.grey900, // body text color ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: AppThemeData.grey900, // button text color ), ), ), child: child!, ); }, initialDate: DateTime.now(), //get today's date firstDate: DateTime(2000), //DateTime.now() - not to allow to choose before today. lastDate: DateTime(2101)); return pickedDate; } static int calculateDifference(DateTime date) { DateTime now = DateTime.now(); return DateTime(date.year, date.month, date.day).difference(DateTime(now.year, now.month, now.day)).inDays; } static String timestampToDate(Timestamp timestamp) { DateTime dateTime = timestamp.toDate(); return DateFormat('MMM dd,yyyy').format(dateTime); } static String timestampToDateTime(Timestamp timestamp) { DateTime dateTime = timestamp.toDate(); return DateFormat('MMM dd,yyyy hh:mm aa').format(dateTime); } static String timestampToTime(Timestamp timestamp) { DateTime dateTime = timestamp.toDate(); return DateFormat('hh:mm aa').format(dateTime); } static String timestampToDateChat(Timestamp timestamp) { DateTime dateTime = timestamp.toDate(); return DateFormat('dd/MM/yyyy').format(dateTime); } static DateTime stringToDate(String openDineTime) { return DateFormat('HH:mm').parse(DateFormat('HH:mm').format(DateFormat("hh:mm a").parse((Intl.getCurrentLocale() == "en_US") ? openDineTime : openDineTime.toLowerCase()))); } static LanguageModel getLanguage() { final String user = Preferences.getString(Preferences.languageCodeKey); Map userMap = jsonDecode(user); return LanguageModel.fromJson(userMap); } static String orderId({String orderId = ''}) { return "#$orderId"; // return "#${(orderId).substring(orderId.length - 10)}"; } static Future checkPermission({required BuildContext context, required Function() onTap}) async { LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); } if (permission == LocationPermission.denied) { ShowToastDialog.showToast("You have to allow location permission to use your location"); } else if (permission == LocationPermission.deniedForever) { showDialog( context: context, builder: (BuildContext context) { return const PermissionDialog(); }, ); } else { onTap(); } } static bool isPointInPolygon(LatLng point, List polygon) { int crossings = 0; for (int i = 0; i < polygon.length; i++) { int next = (i + 1) % polygon.length; if (polygon[i].latitude <= point.latitude && polygon[next].latitude > point.latitude || polygon[i].latitude > point.latitude && polygon[next].latitude <= point.latitude) { double edgeLong = polygon[next].longitude - polygon[i].longitude; double edgeLat = polygon[next].latitude - polygon[i].latitude; double interpol = (point.latitude - polygon[i].latitude) / edgeLat; if (point.longitude < polygon[i].longitude + interpol * edgeLong) { crossings++; } } } return (crossings % 2 != 0); } static final smtpServer = SmtpServer(mailSettings!.host.toString(), username: mailSettings!.userName.toString(), password: mailSettings!.password.toString(), port: 465, ignoreBadCertificate: false, ssl: true, allowInsecure: true); static Future sendMail({String? subject, String? body, bool? isAdmin = false, List? recipients}) async { // Create our message. if (isAdmin == true) { recipients!.add(mailSettings!.userName.toString()); } final message = Message() ..from = Address(mailSettings!.userName.toString(), mailSettings!.fromName.toString()) ..recipients = recipients! ..subject = subject ..text = body ..html = body; try { final sendReport = await send(message, smtpServer); print('Message sent: $sendReport'); } on MailerException catch (e) { print(e); print('Message not sent.'); for (var p in e.problems) { print('Problem: ${p.code}: ${p.msg}'); } } // var connection = PersistentConnection(smtpServer); // // // Send the first message // await connection.send(message); } static Uri createCoordinatesUrl(double latitude, double longitude, [String? label]) { Uri uri; if (kIsWeb) { uri = Uri.https('www.google.com', '/maps/search/', {'api': '1', 'query': '$latitude,$longitude'}); } else if (Platform.isAndroid) { var query = '$latitude,$longitude'; if (label != null) query += '($label)'; uri = Uri(scheme: 'geo', host: '0,0', queryParameters: {'q': query}); } else if (Platform.isIOS) { var params = {'ll': '$latitude,$longitude'}; if (label != null) params['q'] = label; uri = Uri.https('maps.apple.com', '/', params); } else { uri = Uri.https('www.google.com', '/maps/search/', {'api': '1', 'query': '$latitude,$longitude'}); } return uri; } /// Calculate tax amount for a single tax model static double getTaxValue({required String amount, required TaxModel taxModel}) { double taxVal = 0.0; if (taxModel.enable == true) { if (taxModel.type == "fix") { taxVal = double.tryParse(taxModel.tax.toString()) ?? 0.0; } else { taxVal = (double.tryParse(amount) ?? 0.0) * (double.tryParse(taxModel.tax.toString()) ?? 0.0) / 100; } } return taxVal; } } extension StringExtension on String { String capitalizeString() { return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; } }