11/3/1
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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<FlSpot> chartDataMaryam = [];
|
||||
List<FlSpot> chartDataRawda = [];
|
||||
List<FlSpot> chartDataMena = [];
|
||||
List<FlSpot> 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();
|
||||
}
|
||||
|
||||
27
lib/controller/drivers/driverthebest.dart
Normal file
27
lib/controller/drivers/driverthebest.dart
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
76
lib/controller/employee_controller/employee_controller.dart
Normal file
76
lib/controller/employee_controller/employee_controller.dart
Normal file
@@ -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<FormState>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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') {
|
||||
|
||||
@@ -7,6 +7,14 @@ void showInBrowser(String url) async {
|
||||
} else {}
|
||||
}
|
||||
|
||||
Future<void> 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;
|
||||
|
||||
446
lib/controller/functions/upload_image copy.dart
Normal file
446
lib/controller/functions/upload_image copy.dart
Normal file
@@ -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<img.Image> 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<File> 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<File> 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<File> 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<File> 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<Face> 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();
|
||||
// }
|
||||
// }
|
||||
64
lib/controller/functions/wallet.dart
Normal file
64
lib/controller/functions/wallet.dart
Normal file
@@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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());
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
61
lib/views/admin/drivers/driver_the_best.dart
Normal file
61
lib/views/admin/drivers/driver_the_best.dart
Normal file
@@ -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<Driverthebest>(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,
|
||||
);
|
||||
}
|
||||
}
|
||||
185
lib/views/admin/employee/employee_page.dart
Normal file
185
lib/views/admin/employee/employee_page.dart
Normal file
@@ -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<EmployeeController>(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<EmployeeController>(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'),
|
||||
)
|
||||
],
|
||||
);
|
||||
})
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
107
lib/views/admin/packages.dart
Normal file
107
lib/views/admin/packages.dart
Normal file
@@ -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<PackageController>(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<FormState>();
|
||||
|
||||
@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');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user