diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 062d3fd..51e8fc2 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,29 +1,32 @@
-
-
-
-
+
+
+
-
-
+
+
-
+
+
+
+
-
-
-
+
+
-
+
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index b269a90..ee46282 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -7,12 +7,19 @@ PODS:
- AppAuth/Core
- Firebase/CoreOnly (10.25.0):
- FirebaseCore (= 10.25.0)
+ - Firebase/Crashlytics (10.25.0):
+ - Firebase/CoreOnly
+ - FirebaseCrashlytics (~> 10.25.0)
- Firebase/Messaging (10.25.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 10.25.0)
- firebase_core (2.32.0):
- Firebase/CoreOnly (= 10.25.0)
- Flutter
+ - firebase_crashlytics (3.5.7):
+ - Firebase/Crashlytics (= 10.25.0)
+ - firebase_core
+ - Flutter
- firebase_messaging (14.9.4):
- Firebase/Messaging (= 10.25.0)
- firebase_core
@@ -21,8 +28,19 @@ PODS:
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.12)
- GoogleUtilities/Logger (~> 7.12)
+ - FirebaseCoreExtension (10.29.0):
+ - FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.27.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
+ - FirebaseCrashlytics (10.25.0):
+ - FirebaseCore (~> 10.5)
+ - FirebaseInstallations (~> 10.0)
+ - FirebaseRemoteConfigInterop (~> 10.23)
+ - FirebaseSessions (~> 10.5)
+ - GoogleDataTransport (~> 9.2)
+ - GoogleUtilities/Environment (~> 7.8)
+ - nanopb (< 2.30911.0, >= 2.30908.0)
+ - PromisesObjC (~> 2.1)
- FirebaseInstallations (10.27.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
@@ -37,7 +55,22 @@ PODS:
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30911.0, >= 2.30908.0)
+ - FirebaseRemoteConfigInterop (10.29.0)
+ - FirebaseSessions (10.29.0):
+ - FirebaseCore (~> 10.5)
+ - FirebaseCoreExtension (~> 10.0)
+ - FirebaseInstallations (~> 10.0)
+ - GoogleDataTransport (~> 9.2)
+ - GoogleUtilities/Environment (~> 7.13)
+ - GoogleUtilities/UserDefaults (~> 7.13)
+ - nanopb (< 2.30911.0, >= 2.30908.0)
+ - PromisesSwift (~> 2.1)
- Flutter (1.0.0)
+ - flutter_image_compress_common (1.0.0):
+ - Flutter
+ - Mantle
+ - SDWebImage
+ - SDWebImageWebPCoder
- flutter_secure_storage (6.0.0):
- Flutter
- google_sign_in_ios (0.0.1):
@@ -92,8 +125,23 @@ PODS:
- TOCropViewController (~> 2.7.4)
- image_picker_ios (0.0.1):
- Flutter
+ - libwebp (1.3.2):
+ - libwebp/demux (= 1.3.2)
+ - libwebp/mux (= 1.3.2)
+ - libwebp/sharpyuv (= 1.3.2)
+ - libwebp/webp (= 1.3.2)
+ - libwebp/demux (1.3.2):
+ - libwebp/webp
+ - libwebp/mux (1.3.2):
+ - libwebp/demux
+ - libwebp/sharpyuv (1.3.2)
+ - libwebp/webp (1.3.2):
+ - libwebp/sharpyuv
- local_auth_darwin (0.0.1):
- Flutter
+ - Mantle (2.2.0):
+ - Mantle/extobjc (= 2.2.0)
+ - Mantle/extobjc (2.2.0)
- nanopb (2.30910.0):
- nanopb/decode (= 2.30910.0)
- nanopb/encode (= 2.30910.0)
@@ -103,6 +151,14 @@ PODS:
- Flutter
- FlutterMacOS
- PromisesObjC (2.4.0)
+ - PromisesSwift (2.4.0):
+ - PromisesObjC (= 2.4.0)
+ - SDWebImage (5.19.7):
+ - SDWebImage/Core (= 5.19.7)
+ - SDWebImage/Core (5.19.7)
+ - SDWebImageWebPCoder (0.14.6):
+ - libwebp (~> 1.0)
+ - SDWebImage/Core (~> 5.17)
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
@@ -112,8 +168,10 @@ PODS:
DEPENDENCIES:
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
+ - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
+ - flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
@@ -128,25 +186,38 @@ SPEC REPOS:
- AppAuth
- Firebase
- FirebaseCore
+ - FirebaseCoreExtension
- FirebaseCoreInternal
+ - FirebaseCrashlytics
- FirebaseInstallations
- FirebaseMessaging
+ - FirebaseRemoteConfigInterop
+ - FirebaseSessions
- GoogleDataTransport
- GoogleSignIn
- GoogleUtilities
- GTMAppAuth
- GTMSessionFetcher
+ - libwebp
+ - Mantle
- nanopb
- PromisesObjC
+ - PromisesSwift
+ - SDWebImage
+ - SDWebImageWebPCoder
- TOCropViewController
EXTERNAL SOURCES:
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
+ firebase_crashlytics:
+ :path: ".symlinks/plugins/firebase_crashlytics/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
+ flutter_image_compress_common:
+ :path: ".symlinks/plugins/flutter_image_compress_common/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
google_sign_in_ios:
@@ -168,12 +239,18 @@ SPEC CHECKSUMS:
AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa
Firebase: 0312a2352584f782ea56f66d91606891d4607f06
firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197
+ firebase_crashlytics: 17e856fabec68d993662abaf2f6fe2413f0abece
firebase_messaging: 06391e8f35dc65a00c56580266285263d2861f10
FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483
+ FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
FirebaseCoreInternal: 4b297a2d56063dbea2c1d0d04222d44a8d058862
+ FirebaseCrashlytics: 4b96efb0ce73b38b2a85e8b8bd1bd8f63f09d015
FirebaseInstallations: 766dabca09fd94aef922538aaf144cc4a6fb6869
FirebaseMessaging: 88950ba9485052891ebe26f6c43a52bb62248952
+ FirebaseRemoteConfigInterop: 6efda51fb5e2f15b16585197e26eaa09574e8a4d
+ FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
@@ -183,10 +260,15 @@ SPEC CHECKSUMS:
GTMSessionFetcher: 8000756fc1c19d2e5697b90311f7832d2e33f6cd
image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
+ libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
local_auth_darwin: 4d56c90c2683319835a61274b57620df9c4520ab
+ Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
nanopb: 438bc412db1928dac798aa6fd75726007be04262
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
+ PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
+ SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
+ SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
diff --git a/lib/constant/links.dart b/lib/constant/links.dart
index 5f22229..bd1f829 100644
--- a/lib/constant/links.dart
+++ b/lib/constant/links.dart
@@ -104,6 +104,7 @@ class AppLink {
"$ride/notificationPassenger/get.php";
static String updateNotificationPassenger =
"$ride/notificationPassenger/update.php";
+
//-----------------Driver NotificationCaptain------------------
static String addNotificationCaptain = "$ride/notificationCaptain/add.php";
static String addWaitingRide = "$ride/notificationCaptain/addWaitingRide.php";
@@ -229,6 +230,9 @@ class AppLink {
static String getPassengerbyEmail = "$server/Admin/getPassengerbyEmail.php";
static String addAdminUser = "$server/Admin/adminUser/add.php";
static String getdashbord = "$server/Admin/dashbord.php";
+ static String getEmployee = "$server/Admin/employee/get.php";
+ static String getBestDriver = "$server/Admin/driver/getBestDriver.php";
+ static String addEmployee = "$server/Admin/employee/add.php";
static String getdashbordPayment = "$server/Admin/dashbordPayment.php";
static String getAdminUser = "$server/Admin/adminUser/get.php";
static String getCaptainDetailsByEmailOrIDOrPhone =
@@ -263,6 +267,8 @@ class AppLink {
static String addNotesDriver = "$serviceApp/addNotesDriver.php";
static String getCarPlateNotEdit = "$serviceApp/getCarPlateNotEdit.php";
static String addNotesPassenger = "$serviceApp/addNotesPassenger.php";
+ static String getPackages = "$serviceApp/getPackages.php";
+ static String updatePackages = "$serviceApp/updatePackages.php";
//////
static String sendSms = "https://sms.kazumi.me/api/sms/send-sms";
static String senddlr = "https://sms.kazumi.me/api/sms/send-dlr";
diff --git a/lib/controller/admin/static_controller.dart b/lib/controller/admin/static_controller.dart
index 8ca0e54..da49c9f 100644
--- a/lib/controller/admin/static_controller.dart
+++ b/lib/controller/admin/static_controller.dart
@@ -20,6 +20,7 @@ class StaticController extends GetxController {
var chartDataEmployeeMaryam;
var chartDataEmployeeRawda;
var chartDataEmployeeMena;
+ var chartDataEmployeeSefer4;
var chartDataDriversMatchingNotes;
bool isLoading = false;
String totalMonthlyPassengers = '';
@@ -111,6 +112,7 @@ class StaticController extends GetxController {
List chartDataMaryam = [];
List chartDataRawda = [];
List chartDataMena = [];
+ List chartDataSefer4 = [];
for (int day = 1; day <= DateTime.now().day; day++) {
chartDataMaryam.add(FlSpot(
@@ -124,10 +126,10 @@ class StaticController extends GetxController {
0));
chartDataRawda.add(FlSpot(
day.toDouble(),
- employeeDataMap['rawda']
+ employeeDataMap['yasmine']
?.firstWhere((e) => e.day == day,
orElse: () => MonthlyEmployeeData(
- day: day, totalEmployees: 0, name: 'rawda'))
+ day: day, totalEmployees: 0, name: 'yasmine'))
.totalEmployees
.toDouble() ??
0));
@@ -140,12 +142,22 @@ class StaticController extends GetxController {
.totalEmployees
.toDouble() ??
0));
+ chartDataSefer4.add(FlSpot(
+ day.toDouble(),
+ employeeDataMap['ashjan']
+ ?.firstWhere((e) => e.day == day,
+ orElse: () => MonthlyEmployeeData(
+ day: day, totalEmployees: 0, name: 'ashjan'))
+ .totalEmployees
+ .toDouble() ??
+ 0));
}
// Combine spots into a single list if needed or keep them separate
chartDataEmployeeMaryam = chartDataMaryam;
chartDataEmployeeRawda = chartDataRawda;
chartDataEmployeeMena = chartDataMena;
+ chartDataEmployeeSefer4 = chartDataSefer4;
update();
}
diff --git a/lib/controller/drivers/driverthebest.dart b/lib/controller/drivers/driverthebest.dart
new file mode 100644
index 0000000..15fa16b
--- /dev/null
+++ b/lib/controller/drivers/driverthebest.dart
@@ -0,0 +1,27 @@
+import 'dart:convert';
+
+import 'package:get/get.dart';
+
+import '../../constant/colors.dart';
+import '../../constant/links.dart';
+import '../functions/crud.dart';
+
+class Driverthebest extends GetxController {
+ bool isLoading = false;
+ List driver = [];
+ getBestDriver() async {
+ var res = await CRUD().get(link: AppLink.getBestDriver, payload: {});
+ if (res != 'failure') {
+ driver = jsonDecode(res)['message'];
+ update();
+ } else {
+ Get.snackbar('error', '', backgroundColor: AppColor.redColor);
+ }
+ }
+
+ @override
+ void onInit() {
+ getBestDriver();
+ super.onInit();
+ }
+}
diff --git a/lib/controller/employee_controller/employee_controller.dart b/lib/controller/employee_controller/employee_controller.dart
new file mode 100644
index 0000000..d9c61dc
--- /dev/null
+++ b/lib/controller/employee_controller/employee_controller.dart
@@ -0,0 +1,76 @@
+import 'dart:convert';
+import 'dart:math';
+
+import 'package:flutter/widgets.dart';
+import 'package:get/get.dart';
+import 'package:sefer_admin1/constant/colors.dart';
+import 'package:sefer_admin1/constant/links.dart';
+import 'package:sefer_admin1/controller/functions/crud.dart';
+
+class EmployeeController extends GetxController {
+ List employee = [];
+ final name = TextEditingController();
+ final education = TextEditingController();
+ final site = TextEditingController();
+ final phone = TextEditingController();
+ final status = TextEditingController();
+ final formKey = GlobalKey();
+
+ fetchEmployee() async {
+ var res = await CRUD().get(link: AppLink.getEmployee, payload: {});
+ if (res != 'failure') {
+ employee = jsonDecode(res)['message'];
+ update();
+ } else {
+ Get.snackbar('error', '', backgroundColor: AppColor.redColor);
+ }
+ }
+
+ late String id;
+ String generateRandomId(int length) {
+ const String chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+ Random random = Random();
+
+ return String.fromCharCodes(Iterable.generate(
+ length,
+ (_) => chars.codeUnitAt(random.nextInt(chars.length)),
+ ));
+ }
+
+ addEmployee() async {
+ // Create the payload with the employee data
+ var res = await CRUD().post(link: AppLink.addEmployee, payload: {
+ "id": id,
+ "name": name.text,
+ "education": education.text,
+ "site": site.text,
+ "phone": phone.text,
+ "status": status.text,
+ });
+
+ // Check the response from the API
+ if (res != 'failure') {
+ // You can handle the success case here, such as showing a success message
+
+ Get.back();
+ Get.snackbar('Success', 'Employee added successfully',
+ backgroundColor: AppColor.greenColor);
+ name.clear();
+ education.clear();
+ site.clear();
+ phone.clear();
+ status.clear();
+ fetchEmployee();
+ } else {
+ // Handle the error case by showing a snackbar with an error message
+ Get.snackbar('Error', 'Failed to add employee',
+ backgroundColor: AppColor.redColor);
+ }
+ }
+
+ @override
+ void onInit() {
+ fetchEmployee();
+ super.onInit();
+ }
+}
diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart
index 2bb3f26..a70ac87 100644
--- a/lib/controller/functions/crud.dart
+++ b/lib/controller/functions/crud.dart
@@ -296,8 +296,9 @@ class CRUD {
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
-
+ Log.print('payload: ${payload}');
var jsonData = jsonDecode(response.body);
+ Log.print('jsonData: ${jsonData}');
if (response.statusCode == 200) {
if (jsonData['status'] == 'success') {
diff --git a/lib/controller/functions/launch.dart b/lib/controller/functions/launch.dart
index 65b1232..72fc360 100644
--- a/lib/controller/functions/launch.dart
+++ b/lib/controller/functions/launch.dart
@@ -7,6 +7,14 @@ void showInBrowser(String url) async {
} else {}
}
+Future makePhoneCall(String phoneNumber) async {
+ final Uri launchUri = Uri(
+ scheme: 'tel',
+ path: phoneNumber,
+ );
+ await launchUrl(launchUri);
+}
+
void launchCommunication(
String method, String contactInfo, String message) async {
String url;
diff --git a/lib/controller/functions/upload_image copy.dart b/lib/controller/functions/upload_image copy.dart
new file mode 100644
index 0000000..02596ec
--- /dev/null
+++ b/lib/controller/functions/upload_image copy.dart
@@ -0,0 +1,446 @@
+import 'dart:convert';
+import 'dart:io';
+import 'package:flutter_image_compress/flutter_image_compress.dart';
+import 'package:get/get.dart';
+import 'package:http/http.dart' as http;
+import 'package:image_cropper/image_cropper.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:path/path.dart';
+import 'package:image/image.dart' as img;
+
+import 'package:path_provider/path_provider.dart' as path_provider;
+
+import '../../constant/api_key.dart';
+import '../../constant/box_name.dart';
+import '../../constant/colors.dart';
+import '../../main.dart';
+import '../../print.dart';
+
+class ImageController extends GetxController {
+ File? myImage;
+ bool isloading = false;
+ CroppedFile? croppedFile;
+ final picker = ImagePicker();
+ var image;
+
+ Future detectAndCropDocument(File imageFile) async {
+ img.Image? image = img.decodeImage(await imageFile.readAsBytes());
+ if (image == null) throw Exception('Unable to decode image');
+
+ int left = image.width, top = image.height, right = 0, bottom = 0;
+
+ // Threshold for considering a pixel as part of the document (adjust as needed)
+ const int threshold = 240;
+
+ for (int y = 0; y < image.height; y++) {
+ for (int x = 0; x < image.width; x++) {
+ final pixel = image.getPixel(x, y);
+ final luminance = img.getLuminance(pixel);
+
+ if (luminance < threshold) {
+ left = x < left ? x : left;
+ top = y < top ? y : top;
+ right = x > right ? x : right;
+ bottom = y > bottom ? y : bottom;
+ }
+ }
+ }
+
+ // Add a small padding
+ left = (left - 5).clamp(0, image.width);
+ top = (top - 5).clamp(0, image.height);
+ right = (right + 5).clamp(0, image.width);
+ bottom = (bottom + 5).clamp(0, image.height);
+
+ return img.copyCrop(image,
+ x: left, y: top, width: right - left, height: bottom - top);
+ }
+
+ Future rotateImageIfNeeded(File imageFile) async {
+ img.Image croppedDoc = await detectAndCropDocument(imageFile);
+
+ // Check if the document is in portrait orientation
+ bool isPortrait = croppedDoc.height > croppedDoc.width;
+
+ img.Image processedImage;
+ if (isPortrait) {
+ // Rotate the image by 90 degrees clockwise
+ processedImage = img.copyRotate(croppedDoc, angle: 90);
+ } else {
+ processedImage = croppedDoc;
+ }
+
+ // Get temporary directory
+ final tempDir = await path_provider.getTemporaryDirectory();
+ final tempPath = tempDir.path;
+
+ // Create the processed image file
+ File processedFile = File('$tempPath/processed_image.jpg');
+ await processedFile.writeAsBytes(img.encodeJpg(processedImage));
+
+ return processedFile;
+ }
+
+ Future rotateImage(File imageFile) async {
+ // Read the image file
+ img.Image? image = img.decodeImage(await imageFile.readAsBytes());
+
+ if (image == null) return imageFile;
+
+ // Rotate the image by 90 degrees clockwise
+ img.Image rotatedImage = img.copyRotate(image, angle: 90);
+
+ // Get temporary directory
+ final tempDir = await path_provider.getTemporaryDirectory();
+ final tempPath = tempDir.path;
+
+ // Create the rotated image file
+ File rotatedFile = File('$tempPath/rotated_image.jpg');
+ await rotatedFile.writeAsBytes(img.encodeJpg(rotatedImage));
+
+ return rotatedFile;
+ }
+
+ choosImage(String link, String imageType, String id) async {
+ try {
+ final pickedImage = await picker.pickImage(
+ source: ImageSource.camera,
+ preferredCameraDevice: CameraDevice.rear,
+ );
+
+ if (pickedImage == null) return;
+
+ image = File(pickedImage.path);
+
+ croppedFile = await ImageCropper().cropImage(
+ sourcePath: image!.path,
+ uiSettings: [
+ AndroidUiSettings(
+ toolbarTitle: 'Cropper'.tr,
+ toolbarColor: AppColor.blueColor,
+ toolbarWidgetColor: AppColor.yellowColor,
+ initAspectRatio: CropAspectRatioPreset.original,
+ lockAspectRatio: false,
+ ),
+ IOSUiSettings(
+ title: 'Cropper'.tr,
+ ),
+ ],
+ );
+
+ if (croppedFile == null) return;
+
+ myImage = File(croppedFile!.path);
+ isloading = true;
+ update();
+
+ // Rotate the compressed image
+ File processedImage = await rotateImageIfNeeded(File(croppedFile!.path));
+ File compressedImage = await compressImage(processedImage);
+
+ print('link =$link');
+ Log.print('link: ${link}');
+
+ await uploadImage(
+ compressedImage,
+ {
+ 'driverID': id,
+ 'imageType': imageType,
+ },
+ link,
+ );
+ } catch (e) {
+ print('Error in choosImage: $e');
+ Get.snackbar('Image Upload Failed'.tr, e.toString(),
+ backgroundColor: AppColor.primaryColor);
+ } finally {
+ isloading = false;
+ update();
+ }
+ }
+
+ // choosFaceFromDriverLicense(String link, String imageType) async {
+ // final pickedImage = await picker.pickImage(
+ // source: ImageSource.camera,
+ // preferredCameraDevice: CameraDevice.rear,
+ // );
+
+ // if (pickedImage == null) return;
+
+ // image = File(pickedImage.path);
+
+ // File? processedImage;
+
+ // // For face images, use face detection and cropping
+ // processedImage = await detectAndCropFace(image!);
+ // if (processedImage == null) {
+ // Get.snackbar('Face Detection Failed', 'No face detected in the image.');
+ // return;
+ // }
+
+ // isloading = true;
+ // update();
+
+ // File compressedImage = await compressImage(processedImage);
+
+ // try {
+ // await uploadImage(
+ // compressedImage,
+ // {
+ // 'driverID': box.read(BoxName.driverID).toString(),
+ // 'imageType': imageType
+ // },
+ // link,
+ // );
+ // } catch (e) {
+ // Get.snackbar('Image Upload Failed'.tr, e.toString(),
+ // backgroundColor: AppColor.redColor);
+ // } finally {
+ // isloading = false;
+ // update();
+ // }
+ // }
+
+ choosFace(String link, String imageType) async {
+ final pickedImage = await picker.pickImage(
+ source: ImageSource.camera,
+ preferredCameraDevice: CameraDevice.front,
+ );
+ if (pickedImage != null) {
+ image = File(pickedImage.path);
+ isloading = true;
+ update();
+// Compress the image
+ File compressedImage = await compressImage(File(pickedImage.path));
+
+ // Save the picked image directly
+ // File savedImage = File(pickedImage.path);
+ print('link =$link');
+ try {
+ await uploadImage(
+ compressedImage,
+ {
+ 'driverID':
+ box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
+ 'imageType': imageType
+ },
+ link,
+ );
+ } catch (e) {
+ Get.snackbar('Image Upload Failed'.tr, e.toString(),
+ backgroundColor: AppColor.redColor);
+ } finally {
+ isloading = false;
+ update();
+ }
+ }
+ }
+
+ uploadImage(File file, Map data, String link) async {
+ var request = http.MultipartRequest(
+ 'POST',
+ Uri.parse(link),
+ );
+
+ var length = await file.length();
+ var stream = http.ByteStream(file.openRead());
+ var multipartFile = http.MultipartFile(
+ 'image',
+ stream,
+ length,
+ filename: basename(file.path),
+ );
+ request.headers.addAll({
+ 'Authorization':
+ 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
+ });
+ // Set the file name to the driverID
+ request.files.add(
+ http.MultipartFile(
+ 'image',
+ stream,
+ length,
+ filename: '${box.read(BoxName.driverID)}.jpg',
+ ),
+ );
+ data.forEach((key, value) {
+ request.fields[key] = value;
+ });
+ var myrequest = await request.send();
+ var res = await http.Response.fromStream(myrequest);
+ if (res.statusCode == 200) {
+ Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
+
+ Get.snackbar('title', 'message', backgroundColor: AppColor.greenColor);
+ return jsonDecode(res.body);
+ } else {
+ throw Exception(
+ 'Failed to upload image: ${res.statusCode} - ${res.body}');
+ }
+ }
+
+ choosImagePicture(String link, String imageType) async {
+ final pickedImage = await picker.pickImage(
+ source: ImageSource.gallery,
+ // preferredCameraDevice: CameraDevice.rear,
+ // maxHeight: Get.height * .3,
+ // maxWidth: Get.width * .9,
+ // imageQuality: 100,
+ );
+ image = File(pickedImage!.path);
+
+ croppedFile = await ImageCropper().cropImage(
+ sourcePath: image!.path,
+ uiSettings: [
+ AndroidUiSettings(
+ toolbarTitle: 'Cropper'.tr,
+ toolbarColor: AppColor.blueColor,
+ toolbarWidgetColor: AppColor.yellowColor,
+ initAspectRatio: CropAspectRatioPreset.original,
+ lockAspectRatio: false),
+ IOSUiSettings(
+ title: 'Cropper'.tr,
+ ),
+ ],
+ );
+ myImage = File(pickedImage.path);
+ isloading = true;
+ update();
+// Save the cropped image
+ // File savedCroppedImage = File(croppedFile!.path);
+ File compressedImage = await compressImage(File(croppedFile!.path));
+ print('link =$link');
+ try {
+ await uploadImage(
+ compressedImage,
+ {
+ 'driverID':
+ box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
+ 'imageType': imageType
+ },
+ link,
+ );
+ } catch (e) {
+ Get.snackbar('Image Upload Failed'.tr, e.toString(),
+ backgroundColor: AppColor.redColor);
+ } finally {
+ isloading = false;
+ update();
+ }
+ }
+
+ uploadImagePicture(File file, Map data, String link) async {
+ var request = http.MultipartRequest(
+ 'POST',
+ Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php'
+ );
+
+ var length = await file.length();
+ var stream = http.ByteStream(file.openRead());
+ var multipartFile = http.MultipartFile(
+ 'image',
+ stream,
+ length,
+ filename: basename(file.path),
+ );
+ request.headers.addAll({
+ 'Authorization':
+ 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
+ });
+ // Set the file name to the driverID
+ request.files.add(
+ http.MultipartFile(
+ 'image',
+ stream,
+ length,
+ filename: '${box.read(BoxName.driverID)}.jpg',
+ ),
+ );
+ data.forEach((key, value) {
+ request.fields[key] = value;
+ });
+ var myrequest = await request.send();
+ var res = await http.Response.fromStream(myrequest);
+ if (res.statusCode == 200) {
+ return jsonDecode(res.body);
+ } else {
+ throw Exception(
+ 'Failed to upload image: ${res.statusCode} - ${res.body}');
+ }
+ }
+}
+
+Future compressImage(File file) async {
+ final dir = await path_provider.getTemporaryDirectory();
+ final targetPath = "${dir.absolute.path}/temp.jpg";
+
+ var result = await FlutterImageCompress.compressAndGetFile(
+ file.absolute.path,
+ targetPath,
+ quality: 70,
+ minWidth: 1024,
+ minHeight: 1024,
+ );
+
+ return File(result!.path);
+}
+
+// Future detectAndCropFace(File imageFile) async {
+// final inputImage = InputImage.fromFilePath(imageFile.path);
+// final options = FaceDetectorOptions(
+// enableClassification: false,
+// enableLandmarks: false,
+// enableTracking: false,
+// minFaceSize: 0.15,
+// performanceMode: FaceDetectorMode.accurate,
+// );
+// final faceDetector = FaceDetector(options: options);
+
+// try {
+// final List faces = await faceDetector.processImage(inputImage);
+// final image = img.decodeImage(await imageFile.readAsBytes());
+
+// if (image == null) throw Exception('Unable to decode image');
+
+// int left, top, width, height;
+
+// if (faces.isNotEmpty) {
+// // Face detected, crop around the face
+// final face = faces[0];
+// double padding = 0.2; // 20% padding
+// int paddingX = (face.boundingBox.width * padding).round();
+// int paddingY = (face.boundingBox.height * padding).round();
+
+// left = (face.boundingBox.left - paddingX).round();
+// top = (face.boundingBox.top - paddingY).round();
+// width = (face.boundingBox.width + 2 * paddingX).round();
+// height = (face.boundingBox.height + 2 * paddingY).round();
+// } else {
+// // No face detected, crop the center of the image
+// int size = min(image.width, image.height);
+// left = (image.width - size) ~/ 2;
+// top = (image.height - size) ~/ 2;
+// width = size;
+// height = size;
+// }
+
+// // Ensure dimensions are within image bounds
+// left = left.clamp(0, image.width - 1);
+// top = top.clamp(0, image.height - 1);
+// width = width.clamp(1, image.width - left);
+// height = height.clamp(1, image.height - top);
+
+// final croppedImage =
+// img.copyCrop(image, x: left, y: top, width: width, height: height);
+
+// // Save the cropped image
+// final tempDir = await path_provider.getTemporaryDirectory();
+// final tempPath = tempDir.path;
+// final croppedFile = File('$tempPath/cropped_image.jpg');
+// await croppedFile.writeAsBytes(img.encodeJpg(croppedImage, quality: 100));
+
+// return croppedFile;
+// } finally {
+// faceDetector.close();
+// }
+// }
diff --git a/lib/controller/functions/wallet.dart b/lib/controller/functions/wallet.dart
new file mode 100644
index 0000000..de99327
--- /dev/null
+++ b/lib/controller/functions/wallet.dart
@@ -0,0 +1,64 @@
+import 'dart:convert';
+
+import 'package:get/get.dart';
+import 'package:sefer_admin1/constant/colors.dart';
+
+import '../../constant/links.dart';
+import '../firebase/firbase_messge.dart';
+import 'crud.dart';
+
+class WalletController extends GetxController {
+ String paymentToken = '';
+ Future generateTokenDriver(String amount, driverID) async {
+ var res = await CRUD().post(link: AppLink.addPaymentTokenDriver, payload: {
+ 'driverID': driverID.toString(),
+ 'amount': amount.toString(),
+ });
+ var d = jsonDecode(res);
+ return d['message'];
+ }
+
+ addPaymentToDriver(String amount, driverID, token) async {
+ paymentToken = await generateTokenDriver(amount.toString(), driverID);
+ var res = await CRUD().post(link: AppLink.addDrivePayment, payload: {
+ 'rideId': 'gift$driverID',
+ 'amount': amount,
+ 'payment_method': 'visaRide',
+ 'passengerID': 'passengerId',
+ 'token': paymentToken,
+ 'driverID': driverID.toString(),
+ });
+ if (res != 'failure') {
+ FirebaseMessagesController().sendNotificationToAnyWithoutData(
+ 'you have gift from SEFER'.tr,
+ '',
+ token, // Access token correctly
+ 'ding.wav',
+ );
+ Get.snackbar('success', 'addPaymentToDriver',
+ backgroundColor: AppColor.greenColor);
+ } else {
+ Get.snackbar('error', 'addPaymentToDriver',
+ backgroundColor: AppColor.redColor);
+ }
+ }
+
+ Future addSeferWallet(String point, driverID) async {
+ var amount = (int.parse(point) * -1).toStringAsFixed(0);
+ var seferToken = await generateTokenDriver(amount, driverID);
+ var res = await CRUD().post(link: AppLink.addSeferWallet, payload: {
+ 'amount': amount.toString(),
+ 'paymentMethod': 'visaRide',
+ 'passengerId': 'gift$driverID',
+ 'token': seferToken,
+ 'driverId': driverID.toString(),
+ });
+ if (res != 'failure') {
+ Get.snackbar('success', 'addSeferWallet',
+ backgroundColor: AppColor.greenColor);
+ } else {
+ Get.snackbar('error', 'addSeferWallet',
+ backgroundColor: AppColor.redColor);
+ }
+ }
+}
diff --git a/lib/controller/notification_controller.dart b/lib/controller/notification_controller.dart
index a8a693e..aa062ac 100644
--- a/lib/controller/notification_controller.dart
+++ b/lib/controller/notification_controller.dart
@@ -74,7 +74,8 @@ class NotificationController extends GetxController {
"title": title.text,
"body": body.text,
});
- Log.print('res: ${res}');
+ Log.print(
+ 'res: ${res}for ${box.read(BoxName.tokensDrivers)['message'][i]['id']}');
// Log.print('tokensDriver[i]: ${tokensDriver[i]}');
Future.delayed(const Duration(microseconds: 50));
@@ -138,7 +139,8 @@ class NotificationController extends GetxController {
if (formKey.currentState!.validate()) {
var res = await CRUD()
.post(link: AppLink.addNotificationPassenger, payload: {
- "passenger_id": tokensPassengersData[i]['id'].toString(),
+ "passenger_id":
+ tokensPassengersData[i]['passengerID'].toString(),
"title": title.text,
"body": body.text,
});
diff --git a/lib/views/admin/admin_home_page.dart b/lib/views/admin/admin_home_page.dart
index 08d3ab3..d012b7c 100644
--- a/lib/views/admin/admin_home_page.dart
+++ b/lib/views/admin/admin_home_page.dart
@@ -8,6 +8,7 @@ import 'package:sefer_admin1/controller/admin/static_controller.dart';
import 'package:sefer_admin1/controller/notification_controller.dart';
import 'package:sefer_admin1/views/admin/captain/drivers_cant_registe.dart';
import 'package:sefer_admin1/views/admin/captain/register_captain.dart';
+import 'package:sefer_admin1/views/admin/employee/employee_page.dart';
import 'package:sefer_admin1/views/widgets/elevated_btn.dart';
import 'package:sefer_admin1/views/widgets/my_textField.dart';
import 'package:sefer_admin1/views/widgets/mycircular.dart';
@@ -19,6 +20,8 @@ import '../../controller/functions/gemeni.dart';
import '../../print.dart';
import '../widgets/my_scafold.dart';
import 'captain/captain.dart';
+import 'drivers/driver_the_best.dart';
+import 'packages.dart';
import 'passenger/passenger.dart';
import 'rides/rides.dart';
import 'static/static.dart';
@@ -410,7 +413,25 @@ class AdminHomePage extends StatelessWidget {
onPressed: () async {
await Get.put(RegisterCaptainController())
.getDriverNotCompleteRegistration();
- Get.to(() => DriversCantRegister());
+ Get.to(() => const DriversCantRegister());
+ },
+ ),
+ AdminWidgetsDashBoard(
+ title: 'update packages'.tr,
+ onPressed: () async {
+ Get.to(() => PackageUpdateScreen());
+ },
+ ),
+ AdminWidgetsDashBoard(
+ title: 'Employee'.tr,
+ onPressed: () async {
+ Get.to(() => EmployeePage());
+ },
+ ),
+ AdminWidgetsDashBoard(
+ title: 'Drivers the best'.tr,
+ onPressed: () async {
+ Get.to(() => DriverTheBest());
},
),
diff --git a/lib/views/admin/drivers/driver_the_best.dart b/lib/views/admin/drivers/driver_the_best.dart
new file mode 100644
index 0000000..e600db8
--- /dev/null
+++ b/lib/views/admin/drivers/driver_the_best.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:sefer_admin1/controller/functions/wallet.dart';
+import 'package:sefer_admin1/views/admin/wallet/wallet.dart';
+import 'package:sefer_admin1/views/widgets/my_scafold.dart';
+
+import '../../../controller/drivers/driverthebest.dart';
+
+class DriverTheBest extends StatelessWidget {
+ const DriverTheBest({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ Get.put(Driverthebest());
+ return MyScafolld(
+ title: 'Best Drivers'.tr,
+ body: [
+ GetBuilder(builder: (driverthebest) {
+ return driverthebest.driver.isNotEmpty
+ ? ListView.builder(
+ itemCount: driverthebest.driver.length,
+ itemBuilder: (context, index) {
+ final driver = driverthebest.driver[index];
+ return ListTile(
+ leading: CircleAvatar(
+ child: Text(
+ ((driver['driver_count'] * 5) / 3600)
+ .toStringAsFixed(0),
+ ),
+ ),
+ title: Text(driver['name_arabic'] ?? 'Unknown Name'),
+ subtitle: Text('Phone: ${driver['phone'] ?? 'N/A'}'),
+ trailing: IconButton(
+ onPressed: () async {
+ Get.defaultDialog(
+ title:
+ 'are you sure to pay to this driver gift'.tr,
+ middleText: '',
+ onConfirm: () async {
+ final wallet = Get.put(WalletController());
+ await wallet.addPaymentToDriver('200',
+ driver['id'].toString(), driver['token']);
+ await wallet.addSeferWallet(
+ '200', driver['id'].toString());
+ },
+ onCancel: () => Get.back());
+ },
+ icon: const Icon(Icons.wallet_giftcard_rounded),
+ ),
+ );
+ },
+ )
+ : const Center(
+ child: Text('No drivers available.'),
+ );
+ })
+ ],
+ isleading: true,
+ );
+ }
+}
diff --git a/lib/views/admin/employee/employee_page.dart b/lib/views/admin/employee/employee_page.dart
new file mode 100644
index 0000000..80971dc
--- /dev/null
+++ b/lib/views/admin/employee/employee_page.dart
@@ -0,0 +1,185 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:sefer_admin1/constant/colors.dart';
+import 'package:sefer_admin1/constant/style.dart';
+import 'package:sefer_admin1/controller/employee_controller/employee_controller.dart';
+import 'package:sefer_admin1/controller/functions/launch.dart';
+import 'package:sefer_admin1/views/widgets/elevated_btn.dart';
+import 'package:sefer_admin1/views/widgets/my_scafold.dart';
+import 'package:sefer_admin1/views/widgets/my_textField.dart';
+
+import '../../../constant/links.dart';
+import '../../../controller/functions/upload_image copy.dart';
+
+class EmployeePage extends StatelessWidget {
+ const EmployeePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ Get.put(EmployeeController());
+ return GetBuilder(builder: (employeeController) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('Employee Page'.tr),
+ ),
+ body: ListView.builder(
+ itemCount: employeeController
+ .employee.length, // Set the item count based on the employee list
+ itemBuilder: (context, index) {
+ // Get the employee data for the current index
+ var employee = employeeController.employee[index];
+
+ // Return a widget to display the employee information
+ return Padding(
+ padding: const EdgeInsets.all(3.0),
+ child: Container(
+ decoration: AppStyle.boxDecoration1,
+ child: ListTile(
+ trailing: IconButton(
+ onPressed: () {
+ Get.to(() => EmployeeDetails(
+ index: index,
+ ));
+ },
+ icon: Icon(
+ Icons.shop_two,
+ color: employee['status'].toString().contains('ممتاز')
+ ? AppColor.greenColor
+ : AppColor.accentColor,
+ ),
+ ),
+ title: Column(
+ children: [
+ Text(employee['name']),
+ Text(
+ 'Phone: ${employee['phone']}\nEducation: ${employee['education']}'),
+ Text('Status: ${employee['status']}'),
+ ],
+ ), // Display employee name
+ onTap: () {
+ // Add any action you want when the employee is tapped
+ },
+ leading: IconButton(
+ onPressed: () {
+ makePhoneCall(employee['phone'].toString());
+ // launchCommunication(
+ // 'phone', employee['phone'].toString(), '');
+ },
+ icon: const Icon(Icons.phone),
+ ),
+ ),
+ ),
+ );
+ },
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {
+ employeeController.id = employeeController.generateRandomId(8);
+ Get.to(
+ employeeFields(employeeController),
+ );
+ }, // Icon to display
+ backgroundColor: Colors.blue, // Button color (optional)
+ tooltip: 'Add Employee',
+ child: const Icon(Icons.add), // Tooltip text when long-pressed
+ ),
+ );
+ });
+ }
+
+ Scaffold employeeFields(EmployeeController employeeController) {
+ return Scaffold(
+ appBar: AppBar(),
+ body: Form(
+ key: employeeController.formKey,
+ child: SizedBox(
+ height: 500,
+ child: ListView(
+ children: [
+ MyElevatedButton(
+ title: 'front id',
+ onPressed: () async {
+ await ImageController().choosImage(AppLink.uploadEgypt,
+ 'idFrontEmployee', employeeController.id);
+ }),
+ MyElevatedButton(
+ title: 'back id',
+ onPressed: () async {
+ await ImageController().choosImage(AppLink.uploadEgypt,
+ 'idbackEmployee', employeeController.id);
+ }),
+ MyTextForm(
+ controller: employeeController.name,
+ label: 'name',
+ hint: 'name',
+ type: TextInputType.name),
+ MyTextForm(
+ controller: employeeController.education,
+ label: 'education',
+ hint: 'education',
+ type: TextInputType.name),
+ MyTextForm(
+ controller: employeeController.site,
+ label: 'site',
+ hint: 'site',
+ type: TextInputType.name),
+ MyTextForm(
+ controller: employeeController.phone,
+ label: 'phone',
+ hint: 'phone',
+ type: TextInputType.phone),
+ MyTextForm(
+ controller: employeeController.status,
+ label: 'status',
+ hint: 'status',
+ type: TextInputType.name),
+ ],
+ ),
+ ),
+ ),
+ bottomNavigationBar: MyElevatedButton(
+ title: 'upload',
+ onPressed: () async {
+ if (employeeController.formKey.currentState!.validate()) {
+ await employeeController.addEmployee();
+ }
+ },
+ ),
+ );
+ }
+}
+
+class EmployeeDetails extends StatelessWidget {
+ const EmployeeDetails({super.key, required this.index});
+ final int index;
+ @override
+ Widget build(BuildContext context) {
+ return MyScafolld(
+ title: 'Details',
+ isleading: true,
+ body: [
+ GetBuilder(builder: (employeeController) {
+ return Column(
+ children: [
+ SizedBox(
+ height: 200,
+ width: 400,
+ child: Image.network(
+ 'https://sefer.click/sefer/card_image/idFrontEmployee-${employeeController.employee[index]['id']}.jpg'),
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+ SizedBox(
+ height: 200,
+ width: 400,
+ child: Image.network(
+ 'https://sefer.click/sefer/card_image/idFrontEmployee-${employeeController.employee[index]['id']}.jpg'),
+ )
+ ],
+ );
+ })
+ ],
+ );
+ }
+}
diff --git a/lib/views/admin/packages.dart b/lib/views/admin/packages.dart
new file mode 100644
index 0000000..c695b8e
--- /dev/null
+++ b/lib/views/admin/packages.dart
@@ -0,0 +1,107 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'dart:convert';
+import 'package:http/http.dart' as http;
+import 'package:sefer_admin1/constant/links.dart';
+import 'package:sefer_admin1/controller/functions/crud.dart';
+import 'package:sefer_admin1/views/widgets/my_textField.dart';
+
+import '../../print.dart';
+
+class PackageUpdateScreen extends StatelessWidget {
+ final PackageController packageController = Get.put(PackageController());
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Package Update'),
+ ),
+ body: GetBuilder(builder: (packageController) {
+ return Center(
+ child: ListView.builder(
+ itemCount: packageController.packages.length,
+ itemBuilder: (context, index) {
+ var package = packageController.packages[index];
+ return ListTile(
+ title: Text(package['appName']),
+ subtitle: Text(
+ 'Platform: ${package['platform']} \nVersion: ${package['version']}'),
+ trailing: const Icon(Icons.update),
+ onTap: () {
+ Get.defaultDialog(
+ title: 'Update',
+ middleText: '',
+ content: Column(
+ children: [
+ Text(package['appName']),
+ Text(package['platform']),
+ Text(package['version']),
+ MyTextForm(
+ controller: packageController.versionController,
+ label: package['version'].toString(),
+ hint: package['version'].toString(),
+ type: const TextInputType.numberWithOptions(
+ decimal: true),
+ ),
+ ],
+ ),
+ onConfirm: () async {
+ await packageController.updatePackages(
+ package['id'].toString(),
+ packageController.versionController.text.toString(),
+ );
+ },
+ onCancel: () {},
+ );
+ },
+ );
+ },
+ ),
+ );
+ }),
+ );
+ }
+}
+
+class PackageController extends GetxController {
+ List packages = []; // Observable list to hold package info
+ var isLoading = false.obs;
+ final versionController = TextEditingController();
+ final formKey = GlobalKey();
+
+ @override
+ void onInit() {
+ super.onInit();
+ fetchPackages();
+ }
+
+ // Method to fetch package data from API
+ fetchPackages() async {
+ var response = await CRUD().get(link: AppLink.getPackages, payload: {});
+
+ if (response != 'failure') {
+ var jsonData = jsonDecode(response);
+ packages = jsonData['message'];
+ update();
+ Log.print('jsonData: ${jsonData}');
+ }
+ }
+
+ updatePackages(String id, version) async {
+ var response = await CRUD().post(
+ link: AppLink.updatePackages,
+ payload: {
+ "id": id,
+ "version": version,
+ },
+ );
+ Log.print('response: ${response}');
+ if (response != 'failure') {
+ Get.back();
+ fetchPackages();
+ } else {
+ Get.snackbar('error', 'message');
+ }
+ }
+}
diff --git a/lib/views/admin/static/static.dart b/lib/views/admin/static/static.dart
index 850f56b..f7212db 100644
--- a/lib/views/admin/static/static.dart
+++ b/lib/views/admin/static/static.dart
@@ -354,6 +354,18 @@ class StaticDash extends StatelessWidget {
show: true,
color: Colors.green.withOpacity(0.3)),
),
+ LineChartBarData(
+ spots: staticController
+ .chartDataEmployeeSefer4,
+ isCurved: true,
+ color:
+ Colors.yellow, // Custom color for Mena
+ barWidth: 3,
+ dotData: const FlDotData(show: true),
+ belowBarData: BarAreaData(
+ show: true,
+ color: Colors.yellow.withOpacity(0.3)),
+ ),
],
titlesData: const FlTitlesData(
bottomTitles: AxisTitles(
diff --git a/lib/views/widgets/my_textField.dart b/lib/views/widgets/my_textField.dart
index 54f2bf0..2d4168b 100644
--- a/lib/views/widgets/my_textField.dart
+++ b/lib/views/widgets/my_textField.dart
@@ -51,7 +51,7 @@ class MyTextForm extends StatelessWidget {
return 'Please enter a valid email.'.tr;
}
} else if (type == TextInputType.phone) {
- if (value.length != 10) {
+ if (value.length != 11) {
return 'Please enter a valid phone number.'.tr;
}
}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 92f8ef3..7994270 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -9,6 +9,7 @@ import file_selector_macos
import firebase_core
import firebase_crashlytics
import firebase_messaging
+import flutter_image_compress_macos
import flutter_secure_storage_macos
import google_sign_in_ios
import path_provider_foundation
@@ -20,6 +21,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
+ FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index f7b2fa2..2c7f543 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -374,6 +374,54 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_image_compress:
+ dependency: "direct main"
+ description:
+ name: flutter_image_compress
+ sha256: "45a3071868092a61b11044c70422b04d39d4d9f2ef536f3c5b11fb65a1e7dd90"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ flutter_image_compress_common:
+ dependency: transitive
+ description:
+ name: flutter_image_compress_common
+ sha256: "7f79bc6c8a363063620b4e372fa86bc691e1cb28e58048cd38e030692fbd99ee"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ flutter_image_compress_macos:
+ dependency: transitive
+ description:
+ name: flutter_image_compress_macos
+ sha256: "26df6385512e92b3789dc76b613b54b55c457a7f1532e59078b04bf189782d47"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.2"
+ flutter_image_compress_ohos:
+ dependency: transitive
+ description:
+ name: flutter_image_compress_ohos
+ sha256: e76b92bbc830ee08f5b05962fc78a532011fcd2041f620b5400a593e96da3f51
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.0.3"
+ flutter_image_compress_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_image_compress_platform_interface
+ sha256: "579cb3947fd4309103afe6442a01ca01e1e6f93dc53bb4cbd090e8ce34a41889"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ flutter_image_compress_web:
+ dependency: transitive
+ description:
+ name: flutter_image_compress_web
+ sha256: f02fe352b17f82b72f481de45add240db062a2585850bea1667e82cc4cd6c311
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.4+1"
flutter_launcher_icons:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index bbb7e24..cff4a64 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -62,6 +62,7 @@ dependencies:
# webview_flutter: ^4.7.0
googleapis_auth: ^1.6.0
firebase_crashlytics: ^3.5.7
+ flutter_image_compress: ^2.3.0
dev_dependencies:
flutter_test: