From 027d248e563a17b0afee610216399eca976beff1 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sun, 24 Dec 2023 21:28:31 +0300 Subject: [PATCH] 12/24/1 --- .env | 5 +- android/app/build.gradle | 4 +- lib/constant/api_key.dart | 5 + lib/constant/colors.dart | 2 + lib/constant/links.dart | 17 ++ .../admin/captain_admin_controller.dart | 109 ++++++++ .../admin/passenger_admin_controller.dart | 110 ++++++++ .../admin/ride_admin_controller.dart | 50 ++++ lib/controller/auth/captin/ml_google_doc.dart | 4 +- lib/controller/auth/login_controller.dart | 17 ++ lib/controller/firebase/firbase_messge.dart | 2 +- lib/controller/functions/crud.dart | 4 +- lib/controller/functions/device_info.dart | 2 +- lib/controller/functions/gemeni.dart | 247 ++++++++++++++++++ lib/controller/functions/llama_ai.dart | 1 + .../home/map_passenger_controller.dart | 8 + lib/models/model/admin/monthly_ride.dart | 20 ++ lib/models/model/admin/passenger_model.dart | 79 ++++++ lib/views/admin/admin_home_page.dart | 111 ++++++++ lib/views/admin/captain/captain.dart | 224 ++++++++++++++++ lib/views/admin/captain/captain_details.dart | 168 ++++++++++++ lib/views/admin/captain/form_captain.dart | 86 ++++++ lib/views/admin/passenger/form_passenger.dart | 86 ++++++ lib/views/admin/passenger/passenger.dart | 206 +++++++++++++++ .../passenger/passenger_details_page.dart | 168 ++++++++++++ lib/views/admin/rides/rides.dart | 196 ++++++++++++++ lib/views/admin/static/static.dart | 12 + lib/views/admin/wallet/wallet.dart | 12 + lib/views/auth/login_page.dart | 39 +++ pubspec.lock | 16 ++ pubspec.yaml | 1 + 31 files changed, 2001 insertions(+), 10 deletions(-) create mode 100644 lib/controller/admin/captain_admin_controller.dart create mode 100644 lib/controller/admin/passenger_admin_controller.dart create mode 100644 lib/controller/admin/ride_admin_controller.dart create mode 100644 lib/controller/functions/gemeni.dart create mode 100644 lib/models/model/admin/monthly_ride.dart create mode 100644 lib/models/model/admin/passenger_model.dart create mode 100644 lib/views/admin/admin_home_page.dart create mode 100644 lib/views/admin/captain/captain.dart create mode 100644 lib/views/admin/captain/captain_details.dart create mode 100644 lib/views/admin/captain/form_captain.dart create mode 100644 lib/views/admin/passenger/form_passenger.dart create mode 100644 lib/views/admin/passenger/passenger.dart create mode 100644 lib/views/admin/passenger/passenger_details_page.dart create mode 100644 lib/views/admin/rides/rides.dart create mode 100644 lib/views/admin/static/static.dart create mode 100644 lib/views/admin/wallet/wallet.dart diff --git a/.env b/.env index 773f98f..fffa616 100644 --- a/.env +++ b/.env @@ -13,7 +13,8 @@ secretKey=zg_cjzc_57I0TCIYNJPlIFQ5ZXkqiZZ28bBULsuMd1Cr5IYztSseaRvf3LdXWT9wwfV94C stripe_publishableKe=vg_cjzc_57I0TCIYNJPlIFQ5ZB5j2x4vQpU5FVYF9f9Vou74a60BJAQvH5QunMMJB8D1TOqsuOlHCeeh7vHqpnkijRkx9UL5g33vb0iNWKIXrXlBl llamaKey=LL-JfdiCXFpcLXNe87cSGQwGE0piZ9Zw179tVjEP1KMxQgVWGxD9Ixz3m8kkKaO5Kdi serverPHP=https://ride.mobile-app.store -Cohere=Qfrhx9d5YVHiy4uEuK4wiFc9kIuFFlvc5A6WVzPK -ClaudeAiAPI=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 +cohere=Qfrhx9d5YVHiy4uEuK4wiFc9kIuFFlvc5A6WVzPK +claudeAiAPI=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 payPalClientId=AWj9MdPaA5Djpx8gOkvBn2qhP-3KvfB6W-l8USTsm19Xi2NhkNkE9QzosOvTPTsKjCMNffgpqStUA1-x payPalSecret=EKkasSl9O61lrfrbaJfXp1B-CIs2Rv71J0WPouxxugi38DsWaMhWpovJxN2ftYPQ0l6v9eoBvnyWkemp +geminiApi=AIzaSyADz49pIaeO1grPEcpV8HNCJijzekd037o \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 0b6e25e..4b95c84 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -55,8 +55,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion 23 targetSdkVersion flutter.targetSdkVersion - versionCode 14 - versionName '1.3.7' + versionCode 15 + versionName '1.3.8' } signingConfigs { diff --git a/lib/constant/api_key.dart b/lib/constant/api_key.dart index 926ee82..2054c1d 100644 --- a/lib/constant/api_key.dart +++ b/lib/constant/api_key.dart @@ -27,4 +27,9 @@ class AK { static final String chatGPTkeySeferNew = Env.chatGPTkeySeferNew; static final String serverPHP = Env.serverPHP; static final String llamaKey = Env.llamaKey; + static final String cohere = Env.cohere; + static final String claudeAiAPI = Env.claudeAiAPI; + static final String payPalClientId = Env.payPalClientId; + static final String payPalSecret = Env.payPalSecret; + static final String geminiApi = Env.geminiApi; } diff --git a/lib/constant/colors.dart b/lib/constant/colors.dart index 8080df3..428cc1c 100644 --- a/lib/constant/colors.dart +++ b/lib/constant/colors.dart @@ -8,4 +8,6 @@ class AppColor { static const Color greenColor = Color(0xFF34A853); // Google Green static const Color blueColor = Color(0xFF4285F4); // Google Blue static const Color yellowColor = Color(0xFFFBBC05); // Google Yellow + static Color deepPurpleAccent = + const Color.fromARGB(255, 123, 76, 254).withOpacity(0.3); // Google Yellow } diff --git a/lib/constant/links.dart b/lib/constant/links.dart index e16f333..09e1ee4 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -4,6 +4,8 @@ class AppLink { static final String server = Env.serverPHP; static String googleMapsLink = 'https://maps.googleapis.com/maps/api/'; static String llama = 'https://api.llama-api.com/chat/completions'; + static String gemini = + 'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText'; static String test = "$server/test.php"; //===============firebase========================== @@ -153,4 +155,19 @@ class AppLink { static String deletecaptainAccounr = "$authCaptin/deletecaptainAccounr.php"; static String updateAccountBank = "$authCaptin/updateAccountBank.php"; static String getAccount = "$authCaptin/getAccount.php"; + + //===================Admin Captin============ + + static String getPassengerDetailsByPassengerID = + "$server/Admin/getPassengerDetailsByPassengerID.php"; + static String getPassengerDetails = "$server/Admin/getPassengerDetails.php"; + static String getPassengerbyEmail = "$server/Admin/getPassengerbyEmail.php"; + static String addAdminUser = "$server/Admin/adminUser/add.php"; + static String getAdminUser = "$server/Admin/adminUser/get.php"; + static String getCaptainDetailsByEmailOrIDOrPhone = + "$server/Admin/AdminCaptain/getCaptainDetailsByEmailOrIDOrPhone.php"; + static String getCaptainDetails = "$server/Admin/AdminCaptain/get.php"; + static String getRidesPerMonth = + "$server/Admin/AdminRide/getRidesPerMonth.php"; + static String getRidesDetails = "$server/Admin/AdminRide/get.php"; } diff --git a/lib/controller/admin/captain_admin_controller.dart b/lib/controller/admin/captain_admin_controller.dart new file mode 100644 index 0000000..f73327f --- /dev/null +++ b/lib/controller/admin/captain_admin_controller.dart @@ -0,0 +1,109 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; + +import '../../constant/colors.dart'; +import '../../constant/links.dart'; +import '../functions/crud.dart'; + +class CaptainAdminController extends GetxController { + bool isLoading = false; + Map captainData = {}; + Map captain = {}; + final captainController = TextEditingController(); + final captainPrizeController = TextEditingController(); + final titleNotify = TextEditingController(); + final bodyNotify = TextEditingController(); + final formCaptainKey = GlobalKey(); + final formCaptainPrizeKey = GlobalKey(); + + Future getCaptainCount() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getCaptainDetails, payload: {}); + var d = jsonDecode(res); + if (d['status'] == 'success') { + captainData = d; + print(captainData); + } + + isLoading = false; + update(); + } + + Future addCaptainPrizeToWallet() async { + String? paymentId; + //todo link to add wallet to captain + for (var i = 0; i < captainData['message'].length; i++) { + await CRUD().post(link: AppLink.addDriverPaymentPoints, payload: { + 'driverID': captainData['message'][i]['id'], + 'amount': captainPrizeController.text, + 'paymentMethod': 'Prize', + }).then((value) { + paymentId = value['message'].toString(); + }); + await CRUD().post(link: AppLink.addPassengersWallet, payload: { + 'driverID': captainData['message'][i]['id'], + 'amount': captainPrizeController.text, + 'paymentMethod': 'Prize', + 'paymentID': paymentId.toString(), + }); + } + + Get.back(); + } + + void addCaptainsPrizeToWalletSecure() async { + try { + // Check if local authentication is available + bool isAvailable = await LocalAuthentication().isDeviceSupported(); + if (isAvailable) { + // Authenticate the user + bool didAuthenticate = await LocalAuthentication().authenticate( + localizedReason: 'Use Touch ID or Face ID to confirm payment', + ); + if (didAuthenticate) { + // User authenticated successfully, proceed with payment + await addCaptainPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } else { + // Authentication failed, handle accordingly + Get.snackbar('Authentication failed', '', + backgroundColor: AppColor.redColor); + // print( + // 'Authentication failed'); + } + } else { + // Local authentication not available, proceed with payment without authentication + await addCaptainPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } + } catch (e) { + rethrow; + } + } + + Future getCaptains() async { + var res = await CRUD() + .get(link: AppLink.getCaptainDetailsByEmailOrIDOrPhone, payload: { + 'driver_id': captainController.text, + 'driverEmail': captainController.text, + 'driverPhone': captainController.text, + }); + var d = jsonDecode(res); + // print(d['message']); + if (d['status'] == 'success') { + captain = d; + } + // print(passengers); + update(); + } + + @override + void onInit() { + getCaptainCount(); + super.onInit(); + } +} diff --git a/lib/controller/admin/passenger_admin_controller.dart b/lib/controller/admin/passenger_admin_controller.dart new file mode 100644 index 0000000..1d15d39 --- /dev/null +++ b/lib/controller/admin/passenger_admin_controller.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/links.dart'; +import 'package:ride/controller/functions/crud.dart'; + +class PassengerAdminController extends GetxController { + bool isLoading = false; + Map passengersData = {}; + Map passengers = {}; + double height = 150; + final formPassKey = GlobalKey(); + final formPrizeKey = GlobalKey(); + final titleNotify = TextEditingController(); + final bodyNotify = TextEditingController(); + final passengerController = TextEditingController(); + final passengerPrizeController = TextEditingController(); + + Future getPassengerCount() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getPassengerDetails, payload: {}); + var d = jsonDecode(res); + if (d['status'] == 'success') { + passengersData = d; + } + + isLoading = false; + update(); + } + + Future addPassengerPrizeToWallet() async { + for (var i = 0; i < passengersData['message'].length; i++) { + await CRUD().post(link: AppLink.addPassengersWallet, payload: { + 'passenger_id': passengersData['message'][i]['id'], + 'balance': passengerPrizeController.text, + }); + } + + Get.back(); + } + + void addPassengerPrizeToWalletSecure() async { + try { + // Check if local authentication is available + bool isAvailable = await LocalAuthentication().isDeviceSupported(); + if (isAvailable) { + // Authenticate the user + bool didAuthenticate = await LocalAuthentication().authenticate( + localizedReason: 'Use Touch ID or Face ID to confirm payment', + ); + if (didAuthenticate) { + // User authenticated successfully, proceed with payment + await addPassengerPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } else { + // Authentication failed, handle accordingly + Get.snackbar('Authentication failed', '', + backgroundColor: AppColor.redColor); + // print( + // 'Authentication failed'); + } + } else { + // Local authentication not available, proceed with payment without authentication + await addPassengerPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } + } catch (e) { + rethrow; + } + } + + Future getPassengers() async { + var res = await CRUD().get(link: AppLink.getPassengerbyEmail, payload: { + 'passengerEmail': passengerController.text, + 'passengerId': passengerController.text, + 'passengerphone': passengerController.text, + }); + var d = jsonDecode(res); + // print(d['message']); + if (d['status'] == 'success') { + passengers = d; + } + // print(passengers); + update(); + } + + changeHeight() { + if (passengers.isEmpty) { + height = 0; + update(); + } + height = 150; + update(); + } + + void clearPlaces() { + passengers = {}; + update(); + } + + @override + void onInit() { + getPassengerCount(); + super.onInit(); + } +} diff --git a/lib/controller/admin/ride_admin_controller.dart b/lib/controller/admin/ride_admin_controller.dart new file mode 100644 index 0000000..e710fb9 --- /dev/null +++ b/lib/controller/admin/ride_admin_controller.dart @@ -0,0 +1,50 @@ +import 'dart:convert'; + +import 'package:fl_chart/fl_chart.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/links.dart'; +import 'package:ride/controller/functions/crud.dart'; + +import '../../models/model/admin/monthly_ride.dart'; + +class RideAdminController extends GetxController { + bool isLoading = false; + late List rideData; + late Map jsonResponse; + List ridesDetails = []; + var chartData; + Future getRidesAdminDash() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getRidesPerMonth, payload: {}); + jsonResponse = jsonDecode(res); + rideData = (jsonResponse['message'] as List) + .map((item) => RideData.fromJson(item)) + .toList(); + + chartData = rideData + .map((data) => FlSpot(data.day.toDouble(), data.ridesCount.toDouble())) + .toList(); + isLoading = false; + update(); + } + + Future getRidesDetails() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getRidesDetails, payload: {}); + + var d = jsonDecode(res); + ridesDetails = d['message']; + + isLoading = false; + update(); + } + + @override + void onInit() { + getRidesAdminDash(); + getRidesDetails(); + super.onInit(); + } +} diff --git a/lib/controller/auth/captin/ml_google_doc.dart b/lib/controller/auth/captin/ml_google_doc.dart index ac93c0f..174ad99 100644 --- a/lib/controller/auth/captin/ml_google_doc.dart +++ b/lib/controller/auth/captin/ml_google_doc.dart @@ -52,13 +52,13 @@ class CarRegistrationRecognizerController extends GetxController { ], uiSettings: [ AndroidUiSettings( - toolbarTitle: 'Cropper', + toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false), IOSUiSettings( - title: 'Cropper', + title: 'Cropper'.tr, ), ], ); diff --git a/lib/controller/auth/login_controller.dart b/lib/controller/auth/login_controller.dart index 12d72e9..ddfbd1e 100644 --- a/lib/controller/auth/login_controller.dart +++ b/lib/controller/auth/login_controller.dart @@ -12,11 +12,17 @@ import 'package:ride/main.dart'; import 'package:ride/views/auth/verify_email_page.dart'; import 'package:ride/views/home/map_page_passenger.dart'; +import '../../views/admin/admin_home_page.dart'; +import '../functions/device_info.dart'; + class LoginController extends GetxController { final formKey = GlobalKey(); + final formKeyAdmin = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); + TextEditingController adminPasswordController = TextEditingController(); + TextEditingController adminNameController = TextEditingController(); bool isAgreeTerms = false; bool isloading = false; final FlutterSecureStorage _storage = const FlutterSecureStorage(); @@ -32,6 +38,17 @@ class LoginController extends GetxController { update(); } + void adminDashboardOpen() async { + if (formKeyAdmin.currentState!.validate()) { + await DeviceInfoPlus.getDeviceInfo(); + print(DeviceInfoPlus.deviceData); + if (DeviceInfoPlus.deviceData['model'] == 'Nokia 6.1 Plus') { + Get.back(); + Get.to(() => AdminHomePage()); + } + } + } + void login() async { isloading = true; update(); diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index 4f2404a..0e66407 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -96,7 +96,7 @@ class FirebaseMessagesController extends GetxController { } else { box.write(BoxName.tokenFCM, token); } - // print(token); + print(token); }); FirebaseMessaging.onMessage.listen((RemoteMessage message) { diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index 3eb9abc..0b6e3da 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -28,11 +28,11 @@ class CRUD { ); print("-----request----" + response.request.toString()); // print("-----headers-----" + response.headers.toString()); - print("-----payload-----" + payload.toString()); + // print("-----payload-----" + payload.toString()); if (response.statusCode == 200) { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { - print(jsonData); + // print(jsonData); return response.body; } diff --git a/lib/controller/functions/device_info.dart b/lib/controller/functions/device_info.dart index f0cb0a5..529f6dd 100644 --- a/lib/controller/functions/device_info.dart +++ b/lib/controller/functions/device_info.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; class DeviceInfoPlus { + static Map deviceData = {}; static Future> getDeviceInfo() async { final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); - Map deviceData = {}; try { if (Platform.isAndroid) { diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart new file mode 100644 index 0000000..dd691b0 --- /dev/null +++ b/lib/controller/functions/gemeni.dart @@ -0,0 +1,247 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:get/get.dart'; +import 'package:image_cropper/image_cropper.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:http/http.dart' as http; +import 'package:image/image.dart' as img; +import 'package:path_provider/path_provider.dart'; + +import '../../constant/api_key.dart'; +import '../../constant/colors.dart'; + +class ContentController extends GetxController { + final picker = ImagePicker(); + bool isloading = false; + var image; + CroppedFile? croppedFile; + + Future pickImage() async { + final pickedImage = await picker.pickImage(source: ImageSource.gallery); + + if (pickedImage != null) { + image = File(pickedImage.path); + // Crop the image + croppedFile = await ImageCropper().cropImage( + sourcePath: image!.path, + aspectRatioPresets: [ + CropAspectRatioPreset.square, + CropAspectRatioPreset.ratio3x2, + CropAspectRatioPreset.original, + CropAspectRatioPreset.ratio4x3, + CropAspectRatioPreset.ratio16x9 + ], + uiSettings: [ + AndroidUiSettings( + toolbarTitle: 'Cropper'.tr, + toolbarColor: AppColor.blueColor, + toolbarWidgetColor: AppColor.yellowColor, + initAspectRatio: CropAspectRatioPreset.original, + lockAspectRatio: false), + IOSUiSettings( + title: 'Cropper'.tr, + ), + ], + ); + // image = croppedFile; + + // Resize the image + final rawImage = + img.decodeImage(File(croppedFile!.path).readAsBytesSync()); + final resizedImage = + img.copyResize(rawImage!, width: 800); // Adjust the width as needed + + final appDir = await getTemporaryDirectory(); + final resizedImagePath = '${appDir.path}/resized_image.jpg'; + + final resizedImageFile = File(resizedImagePath); + resizedImageFile.writeAsBytesSync( + img.encodeJpg(resizedImage)); // Save the resized image as JPEG + + image = resizedImageFile; + update(); + } + } + + Future generateContent() async { + await pickImage(); + if (image != null) { + final imageBytes = await image.readAsBytes(); + final imageData = base64Encode(imageBytes); + + var requestBody = jsonEncode({ + 'contents': [ + { + 'parts': [ + { + 'inlineData': { + 'mimeType': 'image/jpeg', + 'data': imageData, + }, + }, + { + 'text': + 'write json for all data as first name ,last name,dob,licenseID,expiration date,issued date asdress class type ,output json type', + }, + ], + }, + ], + 'generationConfig': { + 'temperature': 0.4, + 'topK': 32, + 'topP': 1, + 'maxOutputTokens': 4096, + 'stopSequences': [], + }, + 'safetySettings': [ + { + 'category': 'HARM_CATEGORY_HARASSMENT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_HATE_SPEECH', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + ], + }); + print(requestBody); + + final response = await http.post( + Uri.parse( + 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), + headers: {'Content-Type': 'application/json'}, + body: requestBody, + ); + + if (response.statusCode == 200) { + var responseData = jsonDecode(response.body); + // Process the responseData as needed + // print(responseData); + + var result = + responseData['candidates'][0]['content']['parts'][0]['text']; + // print(jsonEncode(result)); + // print((result)); + // print(result['dob']); + RegExp regex = RegExp(r"```json([^`]*)```"); + String? jsonString = + regex.firstMatch(responseData.toString())?.group(1)?.trim(); + + if (jsonString != null) { + // Convert the JSON object to a String + jsonString = jsonEncode(json.decode(jsonString)); + print(jsonString); + } else { + print("JSON string not found"); + } + + // Rest of your code... + } else { + print('Request failed with status: ${response.statusCode}'); + print('Request failed with status: ${response.body}'); + } + } else { + print('No image selected'); + } + } + + Future getFromCarRegistration() async { + await pickImage(); + if (image != null) { + final imageBytes = await image.readAsBytes(); + final imageData = base64Encode(imageBytes); + + var requestBody = jsonEncode({ + 'contents': [ + { + 'parts': [ + { + 'inlineData': { + 'mimeType': 'image/jpeg', + 'data': imageData, + }, + }, + { + 'text': + 'write output json from image for[ vin, make, model, year, expiration_date, color, owner, registration_date ],output json type ', + }, + ], + }, + ], + 'generationConfig': { + 'temperature': 0.4, + 'topK': 32, + 'topP': 1, + 'maxOutputTokens': 4096, + 'stopSequences': [], + }, + 'safetySettings': [ + { + 'category': 'HARM_CATEGORY_HARASSMENT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_HATE_SPEECH', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + { + 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', + 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', + }, + ], + }); + print(requestBody); + + final response = await http.post( + Uri.parse( + 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), + headers: {'Content-Type': 'application/json'}, + body: requestBody, + ); + + if (response.statusCode == 200) { + var responseData = jsonDecode(response.body); + // Process the responseData as needed + var result = + responseData['candidates'][0]['content']['parts'][0]['text']; + print(result); + RegExp regex = RegExp(r"```json([^`]*)```"); + String? jsonString = + regex.firstMatch(responseData.toString())?.group(1)?.trim(); + + if (jsonString != null) { + // Convert the JSON object to a String + jsonString = jsonEncode(json.decode(jsonString)); + print(jsonString); + } else { + print("JSON string not found"); + } + + // Rest of your code... + } else { + print('Request failed with status: ${response.statusCode}'); + print('Request failed with status: ${response.body}'); + } + } else { + print('No image selected'); + } + } + + @override + void onInit() { + // generateContent(); + super.onInit(); + } +} diff --git a/lib/controller/functions/llama_ai.dart b/lib/controller/functions/llama_ai.dart index 3179026..fda1b19 100644 --- a/lib/controller/functions/llama_ai.dart +++ b/lib/controller/functions/llama_ai.dart @@ -8,6 +8,7 @@ class LlamaAi { print(true); Map exrtatDataFinal = {}; String oneLine = input.replaceAll('\n', ' '); + // var res = await CRUD().getLlama(link: AppLink.gemini, payload: oneLine); var res = await CRUD().getLlama(link: AppLink.llama, payload: oneLine); var decod = jsonDecode(res); // print(decod); diff --git a/lib/controller/home/map_passenger_controller.dart b/lib/controller/home/map_passenger_controller.dart index f3840b8..2823b49 100644 --- a/lib/controller/home/map_passenger_controller.dart +++ b/lib/controller/home/map_passenger_controller.dart @@ -1215,12 +1215,20 @@ class MapPassengerController extends GetxController { // ); } + addToken() async { + await CRUD().post(link: AppLink.addTokens, payload: { + 'token': box.read(BoxName.tokenFCM), + 'passengerID': box.read(BoxName.passengerID).toString() + }).then((value) => print('cccc')); + } + List polylineCoordinate = []; String? cardNumber; @override void onInit() async { mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY); await getLocation(); + await addToken(); await getCarsLocationByPassenger(); getNearestDriverByPassengerLocation(); addCustomPicker(); diff --git a/lib/models/model/admin/monthly_ride.dart b/lib/models/model/admin/monthly_ride.dart new file mode 100644 index 0000000..61b345c --- /dev/null +++ b/lib/models/model/admin/monthly_ride.dart @@ -0,0 +1,20 @@ +class RideData { + final int year; + final int month; + final int day; + final int ridesCount; + + RideData({ + required this.year, + required this.month, + required this.day, + required this.ridesCount, + }); + + factory RideData.fromJson(Map json) => RideData( + year: json['year'] as int, + month: json['month'] as int, + day: json['day'] as int, + ridesCount: json['rides_count'] as int, + ); +} diff --git a/lib/models/model/admin/passenger_model.dart b/lib/models/model/admin/passenger_model.dart new file mode 100644 index 0000000..ed920bb --- /dev/null +++ b/lib/models/model/admin/passenger_model.dart @@ -0,0 +1,79 @@ +class Passenger { + String id; + String phone; + String email; + String gender; + String status; + String birthdate; + String site; + String firstName; + String lastName; + String sosPhone; + String education; + String employmentType; + String maritalStatus; + String createdAt; + String updatedAt; + int countPassenger; + int countFeedback; + double ratingPassenger; + int countDriverRate; + int countPassengerCancel; + double passengerAverageRating; + int countPassengerRate; + int countPassengerRide; + + Passenger({ + required this.id, + required this.phone, + required this.email, + required this.gender, + required this.status, + required this.birthdate, + required this.site, + required this.firstName, + required this.lastName, + required this.sosPhone, + required this.education, + required this.employmentType, + required this.maritalStatus, + required this.createdAt, + required this.updatedAt, + required this.countPassenger, + required this.countFeedback, + required this.ratingPassenger, + required this.countDriverRate, + required this.countPassengerCancel, + required this.passengerAverageRating, + required this.countPassengerRate, + required this.countPassengerRide, + }); + + factory Passenger.fromJson(Map json) { + return Passenger( + id: json['id'], + phone: json['phone'], + email: json['email'], + gender: json['gender'], + status: json['status'], + birthdate: json['birthdate'], + site: json['site'], + firstName: json['first_name'], + lastName: json['last_name'], + sosPhone: json['sosPhone'], + education: json['education'], + employmentType: json['employmentType'], + maritalStatus: json['maritalStatus'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + countPassenger: json['countPassenger'], + countFeedback: json['countFeedback'], + ratingPassenger: json['ratingPassenger'].toDouble(), + countDriverRate: json['countDriverRate'], + countPassengerCancel: json['countPassengerCancel'], + passengerAverageRating: json['passengerAverageRating'].toDouble(), + countPassengerRate: json['countPassengerRate'], + countPassengerRide: json['countPassengerRide'], + ); + } +} diff --git a/lib/views/admin/admin_home_page.dart b/lib/views/admin/admin_home_page.dart new file mode 100644 index 0000000..f730b42 --- /dev/null +++ b/lib/views/admin/admin_home_page.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart'; +import 'package:ride/constant/box_name.dart'; +import 'package:ride/constant/links.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/controller/functions/crud.dart'; +import 'package:ride/main.dart'; +import 'package:ride/views/admin/rides/rides.dart'; +import 'package:ride/views/admin/static/static.dart'; +import 'package:ride/views/admin/wallet/wallet.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; + +import '../../controller/auth/captin/ml_google_doc.dart'; +import '../../controller/functions/device_info.dart'; +import '../../controller/functions/gemeni.dart'; +import 'captain/captain.dart'; +import 'passenger/passenger.dart'; + +class AdminHomePage extends StatelessWidget { + const AdminHomePage({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Admin Home Page', + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + alignment: WrapAlignment.center, + children: [ + AdminWidgetsDashBoard( + title: 'Passengers', + onPressed: () => Get.to(() => Passengrs(), + transition: Transition.topLevel)), + AdminWidgetsDashBoard( + title: 'Captains', + onPressed: () => + Get.to(() => Captain(), transition: Transition.size)), + AdminWidgetsDashBoard( + title: 'Wallet', + onPressed: () => + Get.to(() => Wallet(), transition: Transition.fade)), + AdminWidgetsDashBoard( + title: 'Rides', + onPressed: () => + Get.to(() => Rides(), transition: Transition.downToUp)), + AdminWidgetsDashBoard( + title: 'Static', + onPressed: () => Get.to(() => StaticDash())), + AdminWidgetsDashBoard( + title: 'Gemeni', + onPressed: () => ContentController().generateContent()), + AdminWidgetsDashBoard( + title: 'GemeniCarRegistration', + onPressed: () => + ContentController().getFromCarRegistration()), + AdminWidgetsDashBoard( + title: 'Llama', + onPressed: () => + CarRegistrationRecognizerController().scanText()), + AdminWidgetsDashBoard( + title: 'Add device to be Admin', + onPressed: () async { + Map device = DeviceInfoPlus.deviceData; + // print(device); + await CRUD().post(link: AppLink.addAdminUser, payload: { + 'deviceNumber': device['serialNumber'].toString(), + 'name': 'b', + }); + }), + ], + ), + ) + ], + isleading: false); + } +} + +class AdminWidgetsDashBoard extends StatelessWidget { + const AdminWidgetsDashBoard({ + super.key, + required this.title, + required this.onPressed, + }); + final String title; + final Callback onPressed; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: onPressed, + child: Container( + decoration: AppStyle.boxDecoration, + height: 100, + width: Get.width * .4, + child: Center( + child: Text( + title.tr, + style: AppStyle.title, + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/captain/captain.dart b/lib/views/admin/captain/captain.dart new file mode 100644 index 0000000..6653772 --- /dev/null +++ b/lib/views/admin/captain/captain.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/views/admin/captain/captain_details.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/captain_admin_controller.dart'; +import '../../widgets/elevated_btn.dart'; +import '../../widgets/my_textField.dart'; +import '../../widgets/mycircular.dart'; +import '../passenger/form_passenger.dart'; +import 'form_captain.dart'; + +class Captain extends StatelessWidget { + Captain({super.key}); + final CaptainAdminController captainAdminController = + Get.put(CaptainAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Captain'.tr, + body: [ + GetBuilder( + builder: (captainAdminController) => Column( + children: [ + captainAdminController.isLoading + ? const MyCircularProgressIndicator() + : Column( + children: [ + Padding( + padding: const EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + captainAdmin( + captainAdminController, + 'Captains Count', + 'countPassenger', + ), + MyElevatedButton( + title: 'Add Prize to Gold Captains', + onPressed: () { + var date = DateTime.now(); + var day = date.weekday; + + if (day == 6) { + // Saturday is 6 + // print(day); + Get.defaultDialog( + title: + 'Add Prize to Gold Captains', + titleStyle: AppStyle.title, + content: Column( + children: [ + Text( + 'Add Points to their wallet as prize' + .tr, + style: AppStyle.title, + ), + Form( + key: captainAdminController + .formCaptainPrizeKey, + child: MyTextForm( + controller: + captainAdminController + .captainPrizeController, + label: + 'Count of prize' + .tr, + hint: 'Count of prize' + .tr, + type: TextInputType + .number)) + ], + ), + confirm: MyElevatedButton( + title: 'Add', + onPressed: () async { + if (captainAdminController + .formCaptainPrizeKey + .currentState! + .validate()) { + captainAdminController + .addCaptainsPrizeToWalletSecure(); + } + }, + ), + ); + } else { + Get.defaultDialog( + title: + 'This day is not allowed', + titleStyle: AppStyle.title, + middleText: + 'Saturday only Allowed day', + middleTextStyle: AppStyle.title, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + Get.back(); + })); + } + }) + ], + ), + ), + const SizedBox( + height: 10, + ), + InkWell( + onTap: () { + //todo search + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + width: Get.width, + height: 110, + decoration: BoxDecoration( + border: Border.all( + width: 2, + color: AppColor.greenColor)), + child: formSearchCaptain() + // ], + // ), + ), + ), + ), + SizedBox( + height: Get.height * .5, + child: ListView.builder( + itemCount: captainAdminController + .captainData['message'].length, + itemBuilder: (context, index) { + final user = captainAdminController + .captainData['message'][index]; + + return InkWell( + onTap: () { + Get.to(const CaptainsDetailsPage(), + arguments: { + 'data': user, + }); + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + decoration: BoxDecoration( + border: Border.all(width: 2)), + child: ListTile( + title: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Name : ${user['first_name']} ${user['last_name']}', + style: AppStyle.title, + ), + Text( + 'Rating : ${user['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + subtitle: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Count Trip : ${user['countPassengerRide']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate : ${user['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ], + )) + ], + isleading: true, + ); + } + + Container captainAdmin(CaptainAdminController captainAdminController, + String title, String jsonField) { + return Container( + height: Get.height * .1, + decoration: BoxDecoration(border: Border.all(width: 2)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () {}, + child: Column( + children: [ + Text( + title.tr, + style: AppStyle.title, + ), + Text( + captainAdminController.captainData['message'][0][jsonField] + .toString(), + style: AppStyle.title, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/captain/captain_details.dart b/lib/views/admin/captain/captain_details.dart new file mode 100644 index 0000000..7db6441 --- /dev/null +++ b/lib/views/admin/captain/captain_details.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/controller/firebase/firbase_messge.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; +import 'package:ride/views/widgets/my_textField.dart'; + +import '../../../controller/admin/captain_admin_controller.dart'; + +class CaptainsDetailsPage extends StatelessWidget { + const CaptainsDetailsPage({super.key}); + + @override + Widget build(BuildContext context) { + final arguments = Get.arguments; + final Map data = arguments['data']; + var key = Get.find().formCaptainPrizeKey; + var titleNotify = Get.find().titleNotify; + var bodyNotify = Get.find().bodyNotify; + return MyScafolld( + title: data['first_name'] + ' ' + data['last_name'], + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Email is ${data['email']}', + style: AppStyle.title, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Phone is ${data['phone']}', + style: AppStyle.title, + ), + Text( + 'gender is ${data['gender']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'status is ${data['status']}', + style: AppStyle.title, + ), + Text( + 'birthdate is ${data['birthdate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'site is ${data['site']}', + style: AppStyle.title, + ), + // Text( + // 'sosPhone is ${data['sosPhone']}', + // style: AppStyle.title, + // ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Feedback is ${data['countFeedback']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate is ${data['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Cancel is ${data['countPassengerCancel']}', + style: AppStyle.title, + ), + Text( + 'Count Ride is ${data['countPassengerRide']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Rating Captain Avarage is ${data['passengerAverageRating']}', + style: AppStyle.title, + ), + Text( + 'Rating is ${data['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 3, color: AppColor.yellowColor)), + child: TextButton( + onPressed: () async { + Get.defaultDialog( + title: 'Send Notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: key, + child: Column( + children: [ + MyTextForm( + controller: titleNotify, + label: 'title'.tr, + hint: 'title notificaton'.tr, + type: TextInputType.name), + const SizedBox( + height: 10, + ), + MyTextForm( + controller: bodyNotify, + label: 'body'.tr, + hint: 'body notificaton'.tr, + type: TextInputType.name) + ], + ), + ), + confirm: MyElevatedButton( + title: 'Send', + onPressed: () { + print(titleNotify.text); + if (key.currentState!.validate()) { + FirebaseMessagesController() + .sendNotificationToAnyWithoutData( + titleNotify.text, + bodyNotify.text, + data['passengerToken'], + ); + Get.back(); + } + })); + }, + child: Text( + "Send Notificaion to Captains ".tr, + style: AppStyle.title, + ), + ), + ) + ], + ), + ) + ], + isleading: true, + ); + } +} diff --git a/lib/views/admin/captain/form_captain.dart b/lib/views/admin/captain/form_captain.dart new file mode 100644 index 0000000..902a9d4 --- /dev/null +++ b/lib/views/admin/captain/form_captain.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/controller/admin/captain_admin_controller.dart'; +import 'package:ride/views/admin/captain/captain_details.dart'; +import 'package:ride/views/admin/passenger/passenger_details_page.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; + +GetBuilder formSearchCaptain() { + // DbSql sql = DbSql.instance; + return GetBuilder( + builder: (controller) => Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Container( + decoration: + const BoxDecoration(color: AppColor.secondaryColor), + child: TextField( + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.only(), + gapPadding: 4, + borderSide: BorderSide( + color: AppColor.redColor, + width: 2, + )), + suffixIcon: InkWell( + onTap: () async { + if (controller.captainController.text.length > 4) { + await controller.getCaptains(); + + Get.defaultDialog( + title: controller.captain['message'][0] + ['email'], + titleStyle: AppStyle.title, + content: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Name is ${controller.captain['message'][0]['first_name']} ${controller.captain['message'][0]['last_name']}', + style: AppStyle.title, + ), + Text( + 'phone is ${controller.captain['message'][0]['phone']}', + style: AppStyle.title, + ), + ], + ), + confirm: MyElevatedButton( + title: 'Go To Details'.tr, + onPressed: () { + Get.to( + () => const CaptainsDetailsPage(), + arguments: { + 'data': controller + .captain['message'][0], + }); + })); + } + }, + child: const Icon(Icons.search)), + hintText: 'Search for Passenger'.tr, + hintStyle: AppStyle.title, + hintMaxLines: 1, + prefixIcon: IconButton( + onPressed: () async { + controller.captainController.clear(); + // controller.clearPlaces(); + }, + icon: Icon( + Icons.clear, + color: Colors.red[300], + ), + ), + ), + controller: controller.captainController, + ), + ), + ) + ], + )); +} diff --git a/lib/views/admin/passenger/form_passenger.dart b/lib/views/admin/passenger/form_passenger.dart new file mode 100644 index 0000000..0fa730b --- /dev/null +++ b/lib/views/admin/passenger/form_passenger.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/views/admin/passenger/passenger_details_page.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/passenger_admin_controller.dart'; + +GetBuilder formSearchPassengers() { + // DbSql sql = DbSql.instance; + return GetBuilder( + builder: (controller) => Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Container( + decoration: + const BoxDecoration(color: AppColor.secondaryColor), + child: TextField( + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.only(), + gapPadding: 4, + borderSide: BorderSide( + color: AppColor.redColor, + width: 2, + )), + suffixIcon: InkWell( + onTap: () async { + if (controller.passengerController.text.length > + 4) { + await controller.getPassengers(); + + Get.defaultDialog( + title: controller.passengers['message'][0] + ['email'], + titleStyle: AppStyle.title, + content: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Name is ${controller.passengers['message'][0]['first_name']} ${controller.passengers['message'][0]['last_name']}', + style: AppStyle.title, + ), + Text( + 'phone is ${controller.passengers['message'][0]['phone']}', + style: AppStyle.title, + ), + ], + ), + confirm: MyElevatedButton( + title: 'Go To Details'.tr, + onPressed: () { + Get.to( + () => const PassengerDetailsPage(), + arguments: { + 'data': controller + .passengers['message'][0], + }); + })); + } + }, + child: const Icon(Icons.search)), + hintText: 'Search for Passenger'.tr, + hintStyle: AppStyle.title, + hintMaxLines: 1, + prefixIcon: IconButton( + onPressed: () async { + controller.passengerController.clear(); + controller.clearPlaces(); + }, + icon: Icon( + Icons.clear, + color: Colors.red[300], + ), + ), + ), + controller: controller.passengerController, + ), + ), + ) + ], + )); +} diff --git a/lib/views/admin/passenger/passenger.dart b/lib/views/admin/passenger/passenger.dart new file mode 100644 index 0000000..82ab342 --- /dev/null +++ b/lib/views/admin/passenger/passenger.dart @@ -0,0 +1,206 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/controller/admin/passenger_admin_controller.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; +import 'package:ride/views/widgets/my_textField.dart'; +import 'package:ride/views/widgets/mycircular.dart'; + +import 'form_passenger.dart'; +import 'passenger_details_page.dart'; + +class Passengrs extends StatelessWidget { + Passengrs({super.key}); + final PassengerAdminController passengerAdminController = + Get.put(PassengerAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Passengrs'.tr, + isleading: true, + body: [ + GetBuilder( + builder: (passengerAdminController) => Column( + children: [ + passengerAdminController.isLoading + ? const MyCircularProgressIndicator() + : Column( + children: [ + Padding( + padding: const EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + passengerAdmin( + passengerAdminController, + 'Passengers Count', + 'countPassenger', + ), + MyElevatedButton( + title: 'Add Prize to Gold Passengers', + onPressed: () { + var date = DateTime.now(); + var day = date.weekday; + + if (day == 6) { + // Saturday is 6 + print(day); + Get.defaultDialog( + title: + 'Add Prize to Gold Passengers', + titleStyle: AppStyle.title, + content: Column( + children: [ + Text( + 'Add Points to their wallet as prize' + .tr, + style: AppStyle.title, + ), + Form( + key: + passengerAdminController + .formPrizeKey, + child: MyTextForm( + controller: + passengerAdminController + .passengerPrizeController, + label: + 'Count of prize' + .tr, + hint: 'Count of prize' + .tr, + type: TextInputType + .number)) + ], + ), + confirm: MyElevatedButton( + title: 'Add', + onPressed: () async { + if (passengerAdminController + .formPrizeKey + .currentState! + .validate()) { + passengerAdminController + .addPassengerPrizeToWalletSecure(); + } + }, + ), + ); + } else { + Get.defaultDialog( + title: + 'This day is not allowed', + titleStyle: AppStyle.title, + middleText: + 'Saturday only Allowed day', + middleTextStyle: AppStyle.title, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + Get.back(); + })); + } + }) + ], + ), + ), + const SizedBox( + height: 10, + ), + formSearchPassengers(), + SizedBox( + height: Get.height * .5, + child: ListView.builder( + itemCount: passengerAdminController + .passengersData['message'].length, + itemBuilder: (context, index) { + final user = passengerAdminController + .passengersData['message'][index]; + + return InkWell( + onTap: () { + Get.to(const PassengerDetailsPage(), + arguments: { + 'data': user, + }); + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + decoration: BoxDecoration( + border: Border.all(width: 2)), + child: ListTile( + title: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Name : ${user['first_name']} ${user['last_name']}', + style: AppStyle.title, + ), + Text( + 'Rating : ${user['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + subtitle: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Count Trip : ${user['countPassengerRide']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate : ${user['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ], + )) + ], + ); + } + + Container passengerAdmin(PassengerAdminController passengerAdminController, + String title, String jsonField) { + return Container( + height: Get.height * .1, + decoration: BoxDecoration(border: Border.all(width: 2)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () {}, + child: Column( + children: [ + Text( + title.tr, + style: AppStyle.title, + ), + Text( + passengerAdminController.passengersData['message'][0][jsonField] + .toString(), + style: AppStyle.title, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/passenger/passenger_details_page.dart b/lib/views/admin/passenger/passenger_details_page.dart new file mode 100644 index 0000000..5d7cfd7 --- /dev/null +++ b/lib/views/admin/passenger/passenger_details_page.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/controller/firebase/firbase_messge.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; +import 'package:ride/views/widgets/my_textField.dart'; + +import '../../../controller/admin/passenger_admin_controller.dart'; + +class PassengerDetailsPage extends StatelessWidget { + const PassengerDetailsPage({super.key}); + + @override + Widget build(BuildContext context) { + final arguments = Get.arguments; + final Map data = arguments['data']; + var key = Get.find().formPrizeKey; + var titleNotify = Get.find().titleNotify; + var bodyNotify = Get.find().bodyNotify; + return MyScafolld( + title: data['first_name'], + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Email is ${data['email']}', + style: AppStyle.title, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Phone is ${data['phone']}', + style: AppStyle.title, + ), + Text( + 'gender is ${data['gender']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'status is ${data['status']}', + style: AppStyle.title, + ), + Text( + 'birthdate is ${data['birthdate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'site is ${data['site']}', + style: AppStyle.title, + ), + Text( + 'sosPhone is ${data['sosPhone']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Feedback is ${data['countFeedback']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate is ${data['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Cancel is ${data['countPassengerCancel']}', + style: AppStyle.title, + ), + Text( + 'Count Ride is ${data['countPassengerRide']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Rating Captain Avarage is ${data['passengerAverageRating']}', + style: AppStyle.title, + ), + Text( + 'Rating is ${data['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 3, color: AppColor.yellowColor)), + child: TextButton( + onPressed: () async { + Get.defaultDialog( + title: 'Send Notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: key, + child: Column( + children: [ + MyTextForm( + controller: titleNotify, + label: 'title'.tr, + hint: 'title notificaton'.tr, + type: TextInputType.name), + const SizedBox( + height: 10, + ), + MyTextForm( + controller: bodyNotify, + label: 'body'.tr, + hint: 'body notificaton'.tr, + type: TextInputType.name) + ], + ), + ), + confirm: MyElevatedButton( + title: 'Send', + onPressed: () { + print(titleNotify.text); + if (key.currentState!.validate()) { + FirebaseMessagesController() + .sendNotificationToAnyWithoutData( + titleNotify.text, + bodyNotify.text, + data['passengerToken'], + ); + Get.back(); + } + })); + }, + child: Text( + "Send Notificaion to Passenger ".tr, + style: AppStyle.title, + ), + ), + ) + ], + ), + ) + ], + isleading: true, + ); + } +} diff --git a/lib/views/admin/rides/rides.dart b/lib/views/admin/rides/rides.dart new file mode 100644 index 0000000..6c1ce25 --- /dev/null +++ b/lib/views/admin/rides/rides.dart @@ -0,0 +1,196 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; +import 'package:ride/views/widgets/mycircular.dart'; + +import '../../../controller/admin/ride_admin_controller.dart'; + +class Rides extends StatelessWidget { + Rides({super.key}); + RideAdminController rideAdminController = Get.put(RideAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld(title: 'Rides'.tr, isleading: true, body: [ + GetBuilder( + builder: (rideAdminController) => rideAdminController.isLoading + ? const Center(child: MyCircularProgressIndicator()) + : Column( + children: [ + SizedBox( + height: Get.height * .4, + child: LineChart( + duration: const Duration(milliseconds: 150), + curve: Curves.ease, + LineChartData( + lineBarsData: [ + LineChartBarData( + spots: rideAdminController.chartData, + isCurved: true, + color: Colors.deepPurpleAccent, // Custom color + barWidth: 3, // Thinner line + dotData: const FlDotData( + show: true), // Show dots on each point + belowBarData: BarAreaData( + // Add gradient fill below the line + show: true, + color: AppColor.deepPurpleAccent, + ), + isStrokeJoinRound: true, + shadow: const BoxShadow( + color: AppColor.yellowColor, + blurRadius: 4, + offset: Offset(2, 2), + ), + ), + ], + showingTooltipIndicators: const [], + titlesData: FlTitlesData( + show: true, + topTitles: AxisTitles( + axisNameWidget: Text( + 'Days', + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + bottomTitles: AxisTitles( + axisNameWidget: Text( + 'Total Trips on month'.tr, + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + leftTitles: AxisTitles( + axisNameWidget: Text( + 'Counts of Trips on month'.tr, + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + ), + gridData: const FlGridData( + show: true, + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide(color: AppColor.accentColor), + left: BorderSide(color: AppColor.accentColor), + ), + ), + ), + ), + ), + // SizedBox( + // height: Get.height * .4, + // child: PieChart( + // PieChartData( + // sectionsSpace: 4, // Adjust spacing between sections + // centerSpaceRadius: + // 40, // Adjust radius of center space + // sections: [ + // for (final rideData in rideAdminController.rideData) + // PieChartSectionData( + // value: rideData.ridesCount.toDouble(), + // title: '${rideData.day}', showTitle: true, + // titleStyle: + // AppStyle.subtitle, // Display day as title + // radius: 60, // Adjust radius of each section + // color: + // AppColor.deepPurpleAccent, // Custom color + // ), + // ], + // ), + // ), + // ), + const SizedBox( + height: 20, + ), + Card( + elevation: 4, + color: AppColor.deepPurpleAccent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Total Trips on this Month is ${rideAdminController.jsonResponse['message'][0]['current_month_rides_count']}', + style: AppStyle.title, + ), + ), + ), + const SizedBox( + height: 20, + ), + Card( + elevation: 4, + color: AppColor.yellowColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Driver Average Duration: ${rideAdminController.ridesDetails[0]['driver_avg_duration']}', + style: AppStyle.subtitle, + ), + Text( + 'Number of Drivers: ${rideAdminController.ridesDetails[0]['num_Driver']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Rides: ${rideAdminController.ridesDetails[0]['total_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Ongoing Rides: ${rideAdminController.ridesDetails[0]['ongoing_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Completed Rides: ${rideAdminController.ridesDetails[0]['completed_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Cancelled Rides: ${rideAdminController.ridesDetails[0]['cancelled_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Longest Duration: ${rideAdminController.ridesDetails[0]['longest_duration']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Distance: ${rideAdminController.ridesDetails[0]['total_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Average Distance: ${rideAdminController.ridesDetails[0]['average_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Longest Distance: ${rideAdminController.ridesDetails[0]['longest_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Total Driver Earnings: \$${rideAdminController.ridesDetails[0]['total_driver_earnings']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Company Earnings: \$${rideAdminController.ridesDetails[0]['total_company_earnings']}', + style: AppStyle.subtitle, + ), + Text( + 'Company Percentage: ${rideAdminController.ridesDetails[0]['companyPercent']} %', + style: AppStyle.subtitle, + ), + ], + ), + ), + ) + ], + )) + ]); + } +} diff --git a/lib/views/admin/static/static.dart b/lib/views/admin/static/static.dart new file mode 100644 index 0000000..05fafc7 --- /dev/null +++ b/lib/views/admin/static/static.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; + +class StaticDash extends StatelessWidget { + const StaticDash({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld(title: 'Static Dash'.tr, body: [], isleading: true); + } +} diff --git a/lib/views/admin/wallet/wallet.dart b/lib/views/admin/wallet/wallet.dart new file mode 100644 index 0000000..a1f0f04 --- /dev/null +++ b/lib/views/admin/wallet/wallet.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; + +class Wallet extends StatelessWidget { + const Wallet({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld(title: 'Wallet'.tr, body: [], isleading: true); + } +} diff --git a/lib/views/auth/login_page.dart b/lib/views/auth/login_page.dart index aac6197..2201a0d 100644 --- a/lib/views/auth/login_page.dart +++ b/lib/views/auth/login_page.dart @@ -10,9 +10,11 @@ import 'package:ride/main.dart'; import 'package:ride/views/auth/captin/login_captin.dart'; import 'package:ride/views/widgets/elevated_btn.dart'; import 'package:ride/views/widgets/my_scafold.dart'; +import 'package:ride/views/widgets/my_textField.dart'; import '../../constant/info.dart'; import '../../controller/auth/login_controller.dart'; +import '../admin/admin_home_page.dart'; import '../widgets/mycircular.dart'; import 'register_page.dart'; @@ -28,6 +30,43 @@ class LoginPage extends StatelessWidget { builder: (controller) => MyScafolld( title: 'Login'.tr, isleading: false, + action: GestureDetector( + onLongPress: () { + Get.defaultDialog( + title: 'Admin DashBoard', + titleStyle: AppStyle.title, + content: Form( + key: controller.formKeyAdmin, + child: Column( + children: [ + MyTextForm( + controller: controller.adminNameController, + label: 'Your name'.tr, + hint: 'Your name', + type: TextInputType.name), + const SizedBox( + height: 10, + ), + MyTextForm( + controller: controller.adminPasswordController, + label: 'Your password'.tr, + hint: 'Your password', + type: TextInputType.emailAddress), + const SizedBox( + height: 10, + ), + ], + ), + ), + confirm: MyElevatedButton( + title: 'title', + onPressed: () { + controller.adminDashboardOpen(); + }, + ), + ); + }, + child: const Icon(Icons.dashboard)), body: [ if (box.read(BoxName.agreeTerms) != 'agreed') agreedPage() diff --git a/pubspec.lock b/pubspec.lock index a674d53..aee592d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -361,6 +361,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.2" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -473,6 +481,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "5a74434cc83bf64346efb562f1a06eefaf1bcb530dc3d96a104f631a1eff8d79" + url: "https://pub.dev" + source: hosted + version: "0.65.0" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 22b3aaa..dc49897 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,7 @@ dependencies: envied: ^0.5.2 cached_network_image: ^3.3.0 calendar_builder: ^0.0.6 + fl_chart: ^0.65.0