service 2-5-26-1

This commit is contained in:
Hamza-Ayed
2026-05-02 15:12:46 +03:00
parent c3f29f30c1
commit 255724418c
25 changed files with 1063 additions and 530 deletions

View File

@@ -32,7 +32,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "com.service_intaleq" applicationId = "com.service_intaleq"
minSdk = 23 minSdk = flutter.minSdkVersion
targetSdk = 36 targetSdk = 36
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"
@@ -90,4 +90,4 @@ dependencies {
implementation("com.scottyab:rootbeer-lib:0.1.0") implementation("com.scottyab:rootbeer-lib:0.1.0")
implementation("com.google.android.gms:play-services-safetynet:18.0.1") implementation("com.google.android.gms:play-services-safetynet:18.0.1")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
} }

View File

@@ -7,6 +7,8 @@ class BoxName {
static const String firstTimeLoadKey = 'firstTimeLoadKey'; static const String firstTimeLoadKey = 'firstTimeLoadKey';
static const String jwt = "jwt"; static const String jwt = "jwt";
static const String fingerPrint = "fingerPrint"; static const String fingerPrint = "fingerPrint";
static const String deviceFingerprint = "deviceFingerprint";
static const String payMobApikey = "payMobApikey"; static const String payMobApikey = "payMobApikey";
static const String employeename = "employeename"; static const String employeename = "employeename";
static const String refreshToken = "refreshToken"; static const String refreshToken = "refreshToken";

View File

@@ -10,17 +10,24 @@ class AppLink {
static final String seferCairoServer = Env.seferCairoServer; static final String seferCairoServer = Env.seferCairoServer;
static final String seferGizaServer = Env.seferGizaServer; static final String seferGizaServer = Env.seferGizaServer;
static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main'; static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main';
static String location = 'https://api.intaleq.xyz/intaleq/ride/location'; static String locationServer = 'https://location.intaleq.xyz/intaleq/ride/location';
static String locationServer = static String location = locationServer;
'https://location.intaleq.xyz/intaleq/ride/location'; static String locationServerSide = 'https://location.intaleq.xyz/intaleq/ride/location';
static String mapSaasRoute = 'https://map-saas.intaleqapp.com/api/maps/route';
static String mapSaasPlaces = 'https://map-saas.intaleqapp.com/api/geocoding/places';
static const String routeApiBaseUrl = "https://routesjo.intaleq.xyz/route/v1/driving";
static final String syria = 'https://syria.intaleq.xyz/intaleq';
static String seferPaymentServer0 = box.read('seferPaymentServer'); static String seferPaymentServer0 = box.read('seferPaymentServer');
static final String endPoint = 'https://api.intaleq.xyz/intaleq'; static final String endPoint = 'https://api.intaleq.xyz/intaleq_v3';
static final String rideServer = 'https://rides.intaleq.xyz/intaleq'; static final String rideServer = 'https://rides.intaleq.xyz/intaleq';
// static final String server = Env.serverPHP; // static final String server = Env.serverPHP;
static String getBestDriver = "$server/Admin/driver/getBestDriver.php"; static String getBestDriver = "$server/Admin/driver/getBestDriver.php";
static final String server = 'https://api.intaleq.xyz/intaleq'; static final String server = 'https://api.intaleq.xyz/intaleq_v3';
static final String jwtService = '$server/jwtService.php'; static final String jwtService = '$server/jwtService.php';
static String addError = "$server/Admin/errorApp.php";
// static final String endPoint = box.read(BoxName.serverChosen); // static final String endPoint = box.read(BoxName.serverChosen);
// static final String server = Env.seferCairoServer; // static final String server = Env.seferCairoServer;
@@ -34,6 +41,8 @@ class AppLink {
static String uploadEgypt = "$server/uploadEgypt.php"; static String uploadEgypt = "$server/uploadEgypt.php";
static String auth = '$server/auth'; static String auth = '$server/auth';
static String login = "$serviceApp/login.php"; static String login = "$serviceApp/login.php";
static String register = "$serviceApp/register.php";
static String signUp = "$auth/signup.php"; static String signUp = "$auth/signup.php";
static String sendVerifyEmail = "$auth/sendVerifyEmail.php"; static String sendVerifyEmail = "$auth/sendVerifyEmail.php";
static String passengerRemovedAccountEmail = static String passengerRemovedAccountEmail =

View File

@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/links.dart';
import 'package:service/controller/functions/crud.dart';
import 'package:service/controller/functions/device_helper.dart';
import 'package:service/print.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class RegisterController extends GetxController {
final firstName = TextEditingController();
final lastName = TextEditingController();
final email = TextEditingController();
final phone = TextEditingController();
final password = TextEditingController();
final FlutterSecureStorage storage = const FlutterSecureStorage();
final formKey = GlobalKey<FormState>();
var isLoading = false.obs;
void register() async {
if (formKey.currentState!.validate()) {
isLoading.value = true;
// الحصول على البصمة
String fingerprint = await DeviceHelper.getDeviceFingerprint();
var payload = {
"first_name": firstName.text,
"last_name": lastName.text,
"email": email.text,
"phone": phone.text,
"password": password.text,
"fingerprint": fingerprint,
};
Log.print('🚀 Register Payload: $payload');
var res = await CRUD().post(link: AppLink.register, payload: payload);
Log.print('📥 Register Response: $res');
isLoading.value = false;
if (res != 'failure' && res is Map && res['status'] == 'success') {
// حفظ كلمة المرور للدخول التلقائي لاحقاً
await storage.write(key: 'password', value: password.text);
Get.defaultDialog(
title: "نجاح",
middleText: res['message']['message'] ?? "تم تقديم طلبك بنجاح. يرجى انتظار موافقة الإدارة.",
onConfirm: () {
Get.back(); // close dialog
Get.back(); // return to login
},
textConfirm: "موافق",
);
} else {
Get.snackbar(
"خطأ",
res is Map ? res['message'].toString() : "فشل تقديم طلب التسجيل",
backgroundColor: Colors.red.withOpacity(0.7),
colorText: Colors.white,
);
}
}
}
@override
void onClose() {
firstName.dispose();
lastName.dispose();
email.dispose();
phone.dispose();
password.dispose();
super.onClose();
}
}

View File

@@ -13,7 +13,7 @@ class Driverthebest extends GetxController {
getBestDriver() async { getBestDriver() async {
var res = await CRUD().get(link: AppLink.getBestDriver, payload: {}); var res = await CRUD().get(link: AppLink.getBestDriver, payload: {});
if (res != 'failure') { if (res != 'failure') {
driver = jsonDecode(res)['message']; driver = res['message'];
// Log.print('driver: ${driver}'); // Log.print('driver: ${driver}');
update(); update();
} else { } else {
@@ -34,7 +34,7 @@ class DriverTheBestGizaController extends GetxController {
getBestDriver() async { getBestDriver() async {
var res = await CRUD().get(link: AppLink.getBestDriverGiza, payload: {}); var res = await CRUD().get(link: AppLink.getBestDriverGiza, payload: {});
if (res != 'failure') { if (res != 'failure') {
driver = jsonDecode(res)['message']; driver = res['message'];
update(); update();
} else { } else {
@@ -56,7 +56,7 @@ class DriverTheBestAlexandriaController extends GetxController {
var res = var res =
await CRUD().get(link: AppLink.getBestDriverAlexandria, payload: {}); await CRUD().get(link: AppLink.getBestDriverAlexandria, payload: {});
if (res != 'failure') { if (res != 'failure') {
driver = jsonDecode(res)['message']; driver = res['message'];
update(); update();
} else { } else {
Get.snackbar('error', '', backgroundColor: AppColor.redColor); Get.snackbar('error', '', backgroundColor: AppColor.redColor);

View File

@@ -11,6 +11,7 @@ import '../../constant/colors.dart';
import '../../constant/links.dart'; import '../../constant/links.dart';
import '../../constant/style.dart'; import '../../constant/style.dart';
import '../../main.dart'; import '../../main.dart';
import 'functions/crud.dart';
class FirebaseMessagesController extends GetxController { class FirebaseMessagesController extends GetxController {
final fcmToken = FirebaseMessaging.instance; final fcmToken = FirebaseMessaging.instance;
@@ -55,25 +56,16 @@ class FirebaseMessagesController extends GetxController {
} }
Future getTokens() async { Future getTokens() async {
String? basicAuthCredentials = var res = await CRUD().post(link: AppLink.getTokens, payload: {});
await storage.read(key: BoxName.basicAuthCredentials); if (res != 'failure' && res['status'] == 'success') {
var res = await http.post( dataTokens = res['data'];
Uri.parse(AppLink.getTokens),
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
body: {},
);
var jsonResponse = jsonDecode(res.body);
if (jsonResponse['status'] == 'success') {
dataTokens = jsonResponse['data'];
for (var i = 0; i < dataTokens.length; i++) { for (var i = 0; i < dataTokens.length; i++) {
tokens.add(jsonResponse['data'][i]['token']); tokens.add(res['data'][i]['token']);
} }
box.write(BoxName.tokens, tokens); box.write(BoxName.tokens, tokens);
} else { } else {
Get.defaultDialog(title: "Warning", middleText: "Server Error"); Get.snackbar("Warning".tr, "Server Error".tr,
backgroundColor: AppColor.redColor);
} }
} }

View File

@@ -1,82 +1,244 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:get/get.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:service/constant/box_name.dart';
import 'package:secure_string_operations/secure_string_operations.dart'; import 'package:service/constant/links.dart';
import 'package:service/constant/char_map.dart'; import 'package:service/controller/functions/encrypt_decrypt.dart';
import 'package:service/env/env.dart';
import 'package:service/main.dart';
import 'package:service/print.dart';
import '../../constant/api_key.dart'; import '../../constant/api_key.dart';
import '../../constant/box_name.dart';
import '../../constant/info.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
import 'encrypt_decrypt.dart';
import 'initilize.dart';
class CRUD { class CRUD {
var dev; static bool _isRefreshingJWT = false;
getJWT(String pass, email) async { static String _lastErrorSignature = '';
var dev = Platform.isAndroid ? 'android' : 'ios'; static DateTime _lastErrorTimestamp = DateTime(2000);
var payload = { static const Duration _errorLogDebounceDuration = Duration(minutes: 1);
'password': box.read(BoxName.password) ?? pass,
'email': box.read(BoxName.email) ?? email,
'aud': '${AK.allowed}$dev',
};
var response0 = await http.post(
Uri.parse(AppLink.jwtService),
body: payload,
);
if (response0.statusCode == 200) { // ── JWT Validity Check (No external libs) ──────────────────────
final decodedResponse1 = jsonDecode(response0.body); static bool _isJwtValid(String? token) {
if (token == null || token.isEmpty) return false;
final jwt = decodedResponse1['jwt']; try {
Log.print('jwt: ${jwt}'); final parts = token.split('.');
box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); if (parts.length != 3) return false;
String payload = parts[1];
switch (payload.length % 4) {
case 2:
payload += '==';
break;
case 3:
payload += '=';
break;
}
final decoded = jsonDecode(utf8.decode(base64Url.decode(payload)));
final exp = decoded['exp'];
if (exp == null) return false;
// 30 seconds buffer
return DateTime.now().millisecondsSinceEpoch < (exp * 1000 - 30000);
} catch (_) {
return false;
} }
} }
static Future<void> addError(
String error, String details, String where) async {
try {
final currentErrorSignature = '$where-$error';
final now = DateTime.now();
if (currentErrorSignature == _lastErrorSignature &&
now.difference(_lastErrorTimestamp) < _errorLogDebounceDuration) {
return;
}
_lastErrorSignature = currentErrorSignature;
_lastErrorTimestamp = now;
final userId =
box.read(BoxName.driverID) ?? box.read(BoxName.passengerID);
final userType = 'Service';
final phone = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver);
CRUD().post(
link: AppLink.addError,
payload: {
'error': error.toString(),
'userId': userId.toString(),
'userType': userType,
'phone': phone.toString(),
'device': where,
'details': details,
},
);
} catch (e) {}
}
String _getFpHeader() {
return box.read(BoxName.fingerPrint)?.toString() ?? '';
}
// ═══════════════════════════════════════════════════════════════
// _makeRequest — Central Request Handler
// ───────────────────────────────────────────────────────────────
Future<dynamic> _makeRequest({
required String link,
Map<String, dynamic>? payload,
required Map<String, String> headers,
}) async {
const totalTimeout = Duration(seconds: 60);
Future<http.Response> doPost() {
final url = Uri.parse(link);
return http
.post(url, body: payload, headers: headers)
.timeout(totalTimeout);
}
http.Response? response;
int attempts = 0;
final requestId =
DateTime.now().millisecondsSinceEpoch.toString().substring(7);
Log.print('🚀 [REQ-$requestId] $link');
Log.print('🔑 [FP-$requestId] ${headers['X-Device-FP']}');
if (payload != null) Log.print('📦 [PAYLOAD-$requestId] $payload');
while (attempts < 3) {
try {
attempts++;
response = await doPost();
break;
} on SocketException catch (_) {
Log.print('⚠️ SocketException attempt $attempts$link');
if (attempts >= 3) return 'no_internet';
await Future.delayed(const Duration(seconds: 1));
} on TimeoutException catch (_) {
Log.print('⚠️ TimeoutException attempt $attempts$link');
if (attempts >= 3) return 'failure';
} catch (e) {
if (e.toString().contains('errno = 9') && attempts < 3) {
await Future.delayed(const Duration(milliseconds: 500));
continue;
}
addError(
'HTTP Exception: $e', 'Try: $attempts', 'CRUD._makeRequest $link');
return 'failure';
}
}
if (response == null) return 'failure';
final sc = response.statusCode;
final body = response.body;
Log.print('📥 [RES-$requestId] [$sc] $link');
Log.print('📄 [BODY-$requestId] $body');
if (sc >= 200 && sc < 300) {
try {
return jsonDecode(body);
} catch (e, st) {
addError(
'JSON Decode Error', 'Body: $body\n$st', 'CRUD._makeRequest $link');
return 'failure';
}
}
if (sc == 401) {
if (!_isRefreshingJWT && !link.contains('errorApp.php')) {
_isRefreshingJWT = true;
try {
await getJWT();
} finally {
_isRefreshingJWT = false;
}
}
return 'token_expired';
}
if (sc >= 500) {
addError('Server 5xx', 'SC: $sc\nBody: $body', 'CRUD._makeRequest $link');
return 'failure';
}
return 'failure';
}
// ═══════════════════════════════════════════════════════════════
// post — standard POST
// ═══════════════════════════════════════════════════════════════
Future<dynamic> post({
required String link,
Map<String, dynamic>? payload,
}) async {
String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
if (!_isJwtValid(token) &&
!_isRefreshingJWT &&
!link.contains('login.php')) {
_isRefreshingJWT = true;
try {
await getJWT();
token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
} finally {
_isRefreshingJWT = false;
}
}
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer $token',
'X-Device-FP': _getFpHeader(),
};
return await _makeRequest(link: link, payload: payload, headers: headers);
}
// ═══════════════════════════════════════════════════════════════
// get — standard GET (uses POST method in this architecture)
// ═══════════════════════════════════════════════════════════════
Future<dynamic> get({ Future<dynamic> get({
required String link, required String link,
Map<String, dynamic>? payload, Map<String, dynamic>? payload,
}) async { }) async {
var url = Uri.parse( return await post(link: link, payload: payload);
link,
);
bool isTokenExpired = JwtDecoder.isExpired(X
.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs)
.toString()
.split(AppInformation.addd)[0]);
if (isTokenExpired) {
await getJWT(box.read(BoxName.password), box.read(BoxName.email));
}
var response = await http.post(
url,
body: payload,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}'
},
);
Log.print('esponse.body: ${response.body}');
Log.print('esponse.req: ${response.request}');
Log.print('payload: ${payload}');
var jsonData = jsonDecode(response.body);
Log.print('jsonData: ${jsonData}');
if (jsonData['status'] == 'success') {
return response.body;
}
return jsonData['status'];
} }
// } // ═══════════════════════════════════════════════════════════════
// getJWT — V1 Login Flow
// ═══════════════════════════════════════════════════════════════
Future<void> getJWT() async {
var payload = {
'fingerprint': _getFpHeader(),
'password': box.read(BoxName.password) ?? '',
'aud': 'service',
};
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
};
final response = await _makeRequest(
link: AppLink.login, payload: payload, headers: headers);
if (response != 'failure' &&
response is Map &&
response['status'] == 'success') {
final jwt = response['message']['jwt'];
Log.print('jwt: $jwt');
box.write(BoxName.jwt, c(jwt));
}
}
// ─────────────────────────────────────────────────────────────
// Service Specific Methods (Preserved)
// ─────────────────────────────────────────────────────────────
Future<dynamic> arabicTextExtractByVisionAndAI({ Future<dynamic> arabicTextExtractByVisionAndAI({
required String imagePath, required String imagePath,
required String driverID, required String driverID,
@@ -99,24 +261,24 @@ class CRUD {
if (response.statusCode == 200) { if (response.statusCode == 200) {
return await response.stream.bytesToString(); return await response.stream.bytesToString();
} else {} }
return 'failure';
} }
Future<dynamic> getAgoraToken({ Future<dynamic> getAgoraToken({
required String channelName, required String channelName,
required String uid, required String uid,
}) async { }) async {
var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); var res = await http.get(
var res = await http.get(Uri.parse( Uri.parse(
// 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'),
'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'), 'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'),
// headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'});
headers: {'Authorization': 'Bearer '}); headers: {'Authorization': 'Bearer '});
if (res.statusCode == 200) { if (res.statusCode == 200) {
var response = jsonDecode(res.body); var response = jsonDecode(res.body);
return response['token']; return response['token'];
} else {} }
return 'failure';
} }
Future<dynamic> getLlama({ Future<dynamic> getLlama({
@@ -124,18 +286,14 @@ class CRUD {
required String payload, required String payload,
required String prompt, required String prompt,
}) async { }) async {
var url = Uri.parse( var url = Uri.parse(link);
link,
);
var headers = { var headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Authorization':
'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy' 'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy'
// 'Authorization': 'Bearer ${Env.llamaKey}'
}; };
var data = json.encode({ var data = json.encode({
"model": "Llama-3-70b-Inst-FW", "model": "Llama-3-70b-Inst-FW",
// "model": "llama-13b-chat",
"messages": [ "messages": [
{ {
"role": "user", "role": "user",
@@ -145,11 +303,7 @@ class CRUD {
], ],
"temperature": 0.9 "temperature": 0.9
}); });
var response = await http.post( var response = await http.post(url, body: data, headers: headers);
url,
body: data,
headers: headers,
);
if (response.statusCode == 200) { if (response.statusCode == 200) {
return response.body; return response.body;
@@ -157,54 +311,7 @@ class CRUD {
return response.statusCode; return response.statusCode;
} }
Future<dynamic> post({ sendEmail(String link, Map<String, String>? payload) async {
required String link,
Map<String, dynamic>? payload,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse(
link,
);
bool isTokenExpired = JwtDecoder.isExpired(X
.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs)
.toString()
.split(AppInformation.addd)[0]);
if (isTokenExpired) {
await getJWT(box.read(BoxName.password), box.read(BoxName.email));
}
var response = await http.post(
url,
body: payload,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Bearer ${X.r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs).toString().split(AppInformation.addd)[0]}'
},
);
Log.print('req: ${response.request}');
Log.print('res: ${response.body}');
var jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
if (jsonData['status'] == 'success') {
return response.body;
} else {
String errorMessage = jsonData['message'];
// Get.snackbar('Error'.tr, errorMessage.tr,
// backgroundColor: AppColor.redColor);
return (jsonData['status']);
}
} else {
return response.statusCode;
}
}
sendEmail(
String link,
Map<String, String>? payload,
) async {
var headers = { var headers = {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
'Authorization': 'Authorization':
@@ -215,45 +322,6 @@ class CRUD {
request.headers.addAll(headers); request.headers.addAll(headers);
http.StreamedResponse response = await request.send(); http.StreamedResponse response = await request.send();
if (response.statusCode == 200) { if (response.statusCode == 200) {}
} else {}
} }
Future<dynamic> update({
required String endpoint,
required Map<String, dynamic> data,
required String id,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse('$endpoint/$id');
var response = await http.put(
url,
body: json.encode(data),
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
return json.decode(response.body);
}
Future<dynamic> delete({
required String endpoint,
required String id,
}) async {
// String? basicAuthCredentials =
// await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse('$endpoint/$id');
var response = await http.delete(
url,
headers: {
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
);
return json.decode(response.body);
}
extractTextFromLines(json) {}
} }

View File

@@ -0,0 +1,49 @@
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:service/constant/box_name.dart';
import 'package:service/controller/functions/encrypt_decrypt.dart';
import '../../main.dart';
import '../../print.dart';
class DeviceHelper {
static Future<String> getDeviceFingerprint() async {
await EncryptionHelper.initialize();
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
var deviceData;
try {
if (Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
deviceData = androidInfo.toMap();
} else if (Platform.isIOS) {
IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo;
deviceData = iosInfo.toMap();
} else {
throw UnsupportedError('Unsupported platform');
}
final String deviceId = Platform.isAndroid
? deviceData['id'] ??
deviceData['androidId'] ??
deviceData['fingerprint'] ??
'unknown'
: deviceData['identifierForVendor'] ?? 'unknown';
final String deviceModel = deviceData['model'] ?? 'unknown';
Log.print('DeviceId: $deviceId');
Log.print('DeviceModel: $deviceModel');
final String fingerprint =
EncryptionHelper.instance.encryptData('${deviceId}_$deviceModel');
Log.print('Generated Fingerprint: $fingerprint');
box.write(BoxName.fingerPrint, fingerprint);
return (fingerprint);
} catch (e) {
Log.print('Error generating device fingerprint: $e');
return '';
}
}
}

View File

@@ -2,8 +2,10 @@ import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:service/env/env.dart'; import 'package:service/env/env.dart';
import '../../constant/box_name.dart'; import 'package:secure_string_operations/secure_string_operations.dart';
import '../../main.dart'; import 'package:service/constant/char_map.dart';
import 'package:service/print.dart';
class EncryptionHelper { class EncryptionHelper {
static EncryptionHelper? _instance; static EncryptionHelper? _instance;
@@ -28,29 +30,35 @@ class EncryptionHelper {
} }
debugPrint("Initializing EncryptionHelper..."); debugPrint("Initializing EncryptionHelper...");
// Read stored keys // Read stored keys
String? keyOfApp = Env.keyOfApp; String keyOfApp = r(Env.keyOfApp).toString().split(Env.addd)[0];
// Log.print('keyOfApp: ${keyOfApp}'); String initializationVector = r(Env.initializationVector).toString().split(Env.addd)[0];
String? initializationVector = Env.initializationVector;
// Log.print('initializationVector: ${initializationVector}'); Log.print('Key Length: ${keyOfApp.length}');
Log.print('IV Length: ${initializationVector.length}');
// Set the global instance // Set the global instance
_instance = EncryptionHelper._( _instance = EncryptionHelper._(
encrypt.Key.fromUtf8(keyOfApp!), encrypt.Key.fromUtf8(keyOfApp),
encrypt.IV.fromUtf8(initializationVector!), encrypt.IV.fromUtf8(initializationVector),
); );
debugPrint("EncryptionHelper initialized successfully."); debugPrint("EncryptionHelper initialized successfully.");
} }
/// Encrypts a string /// Encrypts a string
String encryptData(String plainText) { String encryptData(String plainText) {
Log.print('Encrypting: $plainText');
try { try {
final encrypter = final encrypter =
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc)); encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
final encrypted = encrypter.encrypt(plainText, iv: iv); final encrypted = encrypter.encrypt(plainText, iv: iv);
return encrypted.base64; return encrypted.base64;
} catch (e) { } catch (e) {
debugPrint('Encryption Error: $e'); Log.print('Encryption Error: $e');
return ''; return '';
} }
} }
/// Decrypts a string /// Decrypts a string
@@ -66,3 +74,14 @@ class EncryptionHelper {
} }
} }
} }
r(String string) {
var res = X.r(X.r(X.r(string, cn), cC), cs).toString();
// Log.print('r($string) => $res');
return res;
}
c(String string) {
return X.c(X.c(X.c(string, cn), cC), cs).toString();
}

View File

@@ -14,6 +14,9 @@ import '../../constant/api_key.dart';
import '../../constant/box_name.dart'; import '../../constant/box_name.dart';
import '../../constant/colors.dart'; import '../../constant/colors.dart';
import '../../main.dart'; import '../../main.dart';
import 'package:service/controller/functions/encrypt_decrypt.dart';
import 'package:service/env/env.dart';
class ImageController extends GetxController { class ImageController extends GetxController {
File? myImage; File? myImage;
@@ -199,12 +202,13 @@ class ImageController extends GetxController {
length, length,
filename: basename(file.path), filename: basename(file.path),
); );
String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
request.headers.addAll({ request.headers.addAll({
'Cache-Control': 'no-cache, no-store, must-revalidate', 'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache', 'Pragma': 'no-cache',
'Expires': '0', 'Expires': '0',
'Authorization': 'Authorization': 'Bearer $token',
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', 'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '',
}); });
// Set the file name to the driverID // Set the file name to the driverID
request.files.add( request.files.add(
@@ -292,9 +296,10 @@ class ImageController extends GetxController {
length, length,
filename: basename(file.path), filename: basename(file.path),
); );
String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
request.headers.addAll({ request.headers.addAll({
'Authorization': 'Authorization': 'Bearer $token',
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', 'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '',
}); });
// Set the file name to the driverID // Set the file name to the driverID
request.files.add( request.files.add(

View File

@@ -34,7 +34,7 @@ class AppInitializer {
var res = var res =
await CRUD().get(link: Env.getapiKey, payload: {"keyName": key1}); await CRUD().get(link: Env.getapiKey, payload: {"keyName": key1});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
await storage.write(key: key1, value: d[key1].toString()); await storage.write(key: key1, value: d[key1].toString());
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
} else {} } else {}

View File

@@ -1,9 +1,10 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:service/constant/links.dart'; import 'package:service/constant/links.dart';
import 'package:service/controller/functions/crud.dart'; import 'package:service/controller/functions/crud.dart';
import 'package:service/controller/functions/device_helper.dart';
import 'package:service/controller/functions/encrypt_decrypt.dart';
import '../constant/box_name.dart'; import '../constant/box_name.dart';
import '../main.dart'; import '../main.dart';
@@ -12,73 +13,73 @@ import '../views/home/main.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'functions/initilize.dart';
class LoginController extends GetxController { class LoginController extends GetxController {
var email = TextEditingController(); var email = TextEditingController(); // Kept for UI compatibility
var password = TextEditingController(); var password = TextEditingController();
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
// Use FlutterSecureStorage instead of GetStorage
final FlutterSecureStorage storage = const FlutterSecureStorage(); final FlutterSecureStorage storage = const FlutterSecureStorage();
void login() async { void login() async {
String? storedEmail = await storage.read(key: 'email'); // Ensure fingerprint is ready
String fingerprint = box.read(BoxName.fingerPrint) ?? '';
if (fingerprint.isEmpty) {
fingerprint = await DeviceHelper.getDeviceFingerprint();
}
String? storedPassword = await storage.read(key: 'password'); String? storedPassword = await storage.read(key: 'password');
String pass = storedPassword ?? password.text;
await CRUD() if (pass.isEmpty && !formKey.currentState!.validate()) return;
.getJWT(storedPassword ?? password.text, storedEmail ?? email.text);
if (storedEmail != null) { var payload = {
var payload = { "fingerprint": fingerprint,
"email": storedEmail, "password": pass,
"password": storedPassword, "aud": "service",
}; };
Log.print('payload: ${payload}');
var res = await CRUD().get(link: AppLink.login, payload: payload);
Log.print('res: ${res}');
// if (res != 'failure') { Log.print('🚀 Login Payload: $payload');
var d = jsonDecode(res); var res = await CRUD().post(link: AppLink.login, payload: payload);
Log.print('d: ${d}'); Log.print('📥 Login Response: $res');
if (d['message'] == "Login successful") {
// Save data securely in FlutterSecureStorage
await box.write(BoxName.employeename, d['data']['first_name']); if (res != 'failure' && res is Map && res['status'] == 'success') {
Get.off(() => Main()); var d = res['message']; // V1 returns {status, message: {jwt, data: {user...}}}
// }
} // Store JWT
final jwt = d['jwt'];
box.write(BoxName.jwt, c(jwt));
// Store User Data
var userData = d['data'];
await storage.write(key: 'name', value: userData['first_name']);
await storage.write(key: 'driverID', value: userData['id'].toString());
await storage.write(key: 'password', value: pass);
await box.write(BoxName.employeename, userData['first_name']);
await box.write(BoxName.password, pass);
Get.offAll(() => Main());
} else { } else {
if (formKey.currentState!.validate()) { Get.snackbar(
var payload = { 'خطأ'.tr,
"email": storedEmail ?? email.text, res is Map ? res['message'].toString().tr : 'فشل تسجيل الدخول'.tr,
"password": storedPassword ?? password.text, backgroundColor: Colors.red.withOpacity(0.7),
}; colorText: Colors.white,
Log.print('payload: ${payload}'); );
var res = await CRUD().get(link: AppLink.login, payload: payload);
Log.print('res: ${res}');
// if (res != 'failure') {
var d = jsonDecode(res);
Log.print('d: ${d}');
if (d['message'] == "Login successful") {
// Save data securely in FlutterSecureStorage
await storage.write(key: 'email', value: d['data']['email']);
await storage.write(key: 'name', value: d['data']['first_name']);
await storage.write(key: 'driverID', value: d['data']['id']);
await storage.write(key: 'password', value: password.text);
await box.write(BoxName.employeename, d['data']['first_name']);
Get.off(() => Main());
// }
}
}
} }
} }
@override @override
void onInit() { void onInit() async {
login(); await EncryptionHelper.initialize();
await DeviceHelper.getDeviceFingerprint();
// Auto login if credentials exist
String? storedPassword = await storage.read(key: 'password');
if (storedPassword != null) {
login();
}
super.onInit(); super.onInit();
} }
} }

View File

@@ -180,7 +180,7 @@ class MainController extends GetxController {
var res = await CRUD() var res = await CRUD()
.get(link: AppLink.getDriverNotCompleteRegistration, payload: {}); .get(link: AppLink.getDriverNotCompleteRegistration, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
driverNotCompleteRegistration = d; driverNotCompleteRegistration = d;
filteredDrivers = driverNotCompleteRegistration; filteredDrivers = driverNotCompleteRegistration;
update(); update();
@@ -208,7 +208,7 @@ class MainController extends GetxController {
var res = var res =
await CRUD().get(link: AppLink.getDriversWaitingActive, payload: {}); await CRUD().get(link: AppLink.getDriversWaitingActive, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
driverWantCompleteRegistration = d; driverWantCompleteRegistration = d;
filteredDrivers = driverWantCompleteRegistration; filteredDrivers = driverWantCompleteRegistration;
update(); update();
@@ -222,7 +222,7 @@ class MainController extends GetxController {
var res = var res =
await CRUD().get(link: AppLink.getDriversPhoneNotComplete, payload: {}); await CRUD().get(link: AppLink.getDriversPhoneNotComplete, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
driverWantCompleteRegistration = d; driverWantCompleteRegistration = d;
filteredDrivers = driverWantCompleteRegistration; filteredDrivers = driverWantCompleteRegistration;
update(); update();
@@ -235,7 +235,7 @@ class MainController extends GetxController {
getNewDriverRegister() async { getNewDriverRegister() async {
var res = await CRUD().get(link: AppLink.getNewDriverRegister, payload: {}); var res = await CRUD().get(link: AppLink.getNewDriverRegister, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
newDriverRegister = d; newDriverRegister = d;
update(); update();
} else { } else {
@@ -248,7 +248,7 @@ class MainController extends GetxController {
"driverId": driveId, "driverId": driveId,
"notes": notesController.text, "notes": notesController.text,
}); });
if (res != 'failue') { if (res != 'failure') {
Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor); Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor);
} }
} }
@@ -259,7 +259,7 @@ class MainController extends GetxController {
var res = await CRUD() var res = await CRUD()
.get(link: AppLink.getPassengersNotCompleteRegistration, payload: {}); .get(link: AppLink.getPassengersNotCompleteRegistration, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
passengerNotCompleteRegistration = d; passengerNotCompleteRegistration = d;
update(); update();
} else { } else {
@@ -285,7 +285,7 @@ class MainController extends GetxController {
getCarPlateNotEdit() async { getCarPlateNotEdit() async {
var res = await CRUD().get(link: AppLink.getCarPlateNotEdit, payload: {}); var res = await CRUD().get(link: AppLink.getCarPlateNotEdit, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
carPlateNotEdit = d; carPlateNotEdit = d;
update(); update();
} else { } else {
@@ -300,7 +300,7 @@ class MainController extends GetxController {
getdriverWithoutCar() async { getdriverWithoutCar() async {
var res = await CRUD().get(link: AppLink.getdriverWithoutCar, payload: {}); var res = await CRUD().get(link: AppLink.getdriverWithoutCar, payload: {});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res)['message']; var d = res['message'];
driverWithoutCar = d; driverWithoutCar = d;
update(); update();
} else { } else {
@@ -351,11 +351,11 @@ class MainController extends GetxController {
isLoading = false; isLoading = false;
update(); update();
var status = jsonDecode(res); var status = res;
Log.print('res: $res'); Log.print('res: $res');
Log.print('status: $status'); Log.print('status: $status');
if (status['status'] == 'success') { if (status != 'failure' && status['status'] == 'success') {
await Future.wait([ await Future.wait([
CRUD().post( CRUD().post(
link: link:
@@ -492,7 +492,7 @@ class MainController extends GetxController {
payload: {"phone": passengerPhoneController.text}); payload: {"phone": passengerPhoneController.text});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res); var d = res;
passengerData = d; passengerData = d;
update(); update();
} }
@@ -504,7 +504,7 @@ class MainController extends GetxController {
payload: {"phone": driverPhoneController.text}); payload: {"phone": driverPhoneController.text});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res); var d = res;
driverData = d; driverData = d;
update(); update();
} else { } else {
@@ -518,7 +518,7 @@ class MainController extends GetxController {
payload: {"national_number": driverPhoneController.text}); payload: {"national_number": driverPhoneController.text});
if (res != 'failure') { if (res != 'failure') {
var d = jsonDecode(res); var d = res;
driverData = d; driverData = d;
update(); update();
} else { } else {

View File

@@ -96,7 +96,7 @@ class Driverthebest extends GetxController {
getBestDriver() async { getBestDriver() async {
var res = await CRUD().get(link: AppLink.getBestDriver, payload: {}); var res = await CRUD().get(link: AppLink.getBestDriver, payload: {});
if (res != 'failure') { if (res != 'failure') {
driver = jsonDecode(res)['message']; driver = res['message'];
update(); update();
} else { } else {
Get.snackbar('error', '', backgroundColor: AppColor.redColor); Get.snackbar('error', '', backgroundColor: AppColor.redColor);

View File

@@ -108,7 +108,7 @@ class RegisterCaptainServiceController extends GetxController {
payload: {'driverId': driverId.value}); payload: {'driverId': driverId.value});
if (responseString != 'failure') { if (responseString != 'failure') {
var decodedResponse = jsonDecode(responseString); var decodedResponse = responseString;
if (decodedResponse['status'] == 'success' && if (decodedResponse['status'] == 'success' &&
(decodedResponse['message'] as List).isNotEmpty) { (decodedResponse['message'] as List).isNotEmpty) {
var rawData = decodedResponse['message'][0] as Map<String, dynamic>; var rawData = decodedResponse['message'][0] as Map<String, dynamic>;
@@ -261,7 +261,7 @@ class RegisterCaptainServiceController extends GetxController {
isLoading.value = false; isLoading.value = false;
var decodedResponse = (response); var decodedResponse = (response);
Log.print('decodedResponse: ${decodedResponse}'); Log.print('decodedResponse: ${decodedResponse}');
if (decodedResponse != 'failure') { if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') {
MyDialog().getDialog('Success'.tr, '', MyDialog().getDialog('Success'.tr, '',
Text('Driver has been activated successfully!'.tr), () { Text('Driver has been activated successfully!'.tr), () {
Get.back(); Get.back();
@@ -273,7 +273,7 @@ class RegisterCaptainServiceController extends GetxController {
} else { } else {
Get.snackbar( Get.snackbar(
'Error'.tr, 'Error'.tr,
'Failed to update driver: ${decodedResponse['message']}'.tr, 'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr,
backgroundColor: Colors.red, backgroundColor: Colors.red,
colorText: Colors.white, colorText: Colors.white,
); );

View File

@@ -107,7 +107,7 @@ class RegisterCaptainController extends GetxController {
payload: {'driverId': driverId.value}); payload: {'driverId': driverId.value});
if (responseString != 'failure') { if (responseString != 'failure') {
var decodedResponse = jsonDecode(responseString); var decodedResponse = responseString;
if (decodedResponse['status'] == 'success' && if (decodedResponse['status'] == 'success' &&
(decodedResponse['message'] as List).isNotEmpty) { (decodedResponse['message'] as List).isNotEmpty) {
var rawData = decodedResponse['message'][0] as Map<String, dynamic>; var rawData = decodedResponse['message'][0] as Map<String, dynamic>;
@@ -247,7 +247,7 @@ class RegisterCaptainController extends GetxController {
isLoading.value = false; isLoading.value = false;
var decodedResponse = (response); var decodedResponse = (response);
Log.print('decodedResponse: ${decodedResponse}'); Log.print('decodedResponse: ${decodedResponse}');
if (decodedResponse != 'failure') { if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') {
MyDialog().getDialog('Success'.tr, '', MyDialog().getDialog('Success'.tr, '',
Text('Driver has been activated successfully!'.tr), () { Text('Driver has been activated successfully!'.tr), () {
Get.back(); Get.back();
@@ -259,7 +259,7 @@ class RegisterCaptainController extends GetxController {
} else { } else {
Get.snackbar( Get.snackbar(
'Error'.tr, 'Error'.tr,
'Failed to update driver: ${decodedResponse['message']}'.tr, 'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr,
backgroundColor: Colors.red, backgroundColor: Colors.red,
colorText: Colors.white, colorText: Colors.white,
); );

View File

@@ -1,50 +1,171 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:service/main.dart'; import 'package:service/constant/colors.dart';
import 'package:service/views/auth/register_page.dart';
import 'package:service/views/widgets/my_textField.dart'; import 'package:service/views/widgets/my_textField.dart';
import 'controller/login_controller.dart'; import 'controller/login_controller.dart';
class LoginPage extends StatelessWidget { class LoginPage extends StatelessWidget {
final LoginController controller = Get.put(LoginController()); const LoginPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final LoginController controller = Get.put(LoginController());
return Scaffold( return Scaffold(
appBar: const CupertinoNavigationBar( backgroundColor: Colors.white,
middle: Text('Login'), body: Stack(
), children: [
body: SafeArea( // Background Gradient Element
child: Padding( Positioned(
padding: const EdgeInsets.all(16.0), top: -100,
child: Form( right: -100,
key: controller.formKey, child: Container(
child: Column( width: 300,
crossAxisAlignment: CrossAxisAlignment.stretch, height: 300,
children: [ decoration: BoxDecoration(
const SizedBox(height: 20), shape: BoxShape.circle,
MyTextForm( gradient: LinearGradient(
controller: controller.email, colors: [AppColor.blueColor.withOpacity(0.2), Colors.transparent],
label: 'email', begin: Alignment.topRight,
hint: 'email', end: Alignment.bottomLeft,
type: TextInputType.emailAddress),
const SizedBox(height: 20),
MyTextForm(
controller: controller.password,
label: 'Password',
hint: 'Password',
type: TextInputType.name),
const SizedBox(height: 40),
CupertinoButton.filled(
child: const Text('Login'),
onPressed: () {
controller.login();
},
), ),
], ),
), ),
), ),
),
SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 80),
// App Logo or Icon
const Center(
child: Icon(
Icons.support_agent_rounded,
size: 100,
color: AppColor.blueColor,
),
),
const SizedBox(height: 24),
const Center(
child: Text(
'انطلق سيرفس',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.black87,
letterSpacing: 1.2,
),
),
),
const Center(
child: Text(
'نظام خدمة العملاء المتكامل',
style: TextStyle(
fontSize: 16,
color: Colors.grey,
),
),
),
const SizedBox(height: 60),
// Fields with modern styling
const Text(
'تسجيل الدخول',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
const SizedBox(height: 20),
MyTextForm(
controller: controller.email,
label: 'البريد الإلكتروني',
hint: 'أدخل البريد الإلكتروني',
type: TextInputType.emailAddress,
),
const SizedBox(height: 20),
MyTextForm(
controller: controller.password,
label: 'كلمة المرور',
hint: 'أدخل كلمة المرور',
type: TextInputType.visiblePassword,
),
const SizedBox(height: 40),
// Login Button
Container(
height: 55,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: const LinearGradient(
colors: [AppColor.blueColor, Color(0xFF1A237E)],
),
boxShadow: [
BoxShadow(
color: AppColor.blueColor.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 6),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () => controller.login(),
child: const Center(
child: Text(
'دخول',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
const SizedBox(height: 30),
// Register Link
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'ليس لديك حساب موظف؟ ',
style: TextStyle(color: Colors.grey),
),
TextButton(
onPressed: () => Get.to(() => const RegisterPage()),
child: const Text(
'إنشاء حساب جديد',
style: TextStyle(
color: AppColor.blueColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
),
),
],
), ),
); );
} }

View File

@@ -7,7 +7,6 @@ import 'package:service/controller/firbase_messge.dart';
import 'package:service/firebase_options.dart'; import 'package:service/firebase_options.dart';
import 'controller/functions/encrypt_decrypt.dart'; import 'controller/functions/encrypt_decrypt.dart';
import 'controller/functions/initilize.dart';
import 'controller/local/local_controller.dart'; import 'controller/local/local_controller.dart';
import 'controller/local/translations.dart'; import 'controller/local/translations.dart';
import 'login_page.dart'; import 'login_page.dart';

View File

@@ -0,0 +1,172 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:service/constant/colors.dart';
import 'package:service/controller/auth/register_controller.dart';
import 'package:service/views/widgets/my_textField.dart';
class RegisterPage extends StatelessWidget {
const RegisterPage({super.key});
@override
Widget build(BuildContext context) {
final RegisterController controller = Get.put(RegisterController());
return Scaffold(
backgroundColor: const Color(0xFFF8F9FD),
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black87),
onPressed: () => Get.back(),
),
title: Text(
'إنشاء حساب موظف'.tr,
style: const TextStyle(color: Colors.black87, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Center(
child: Icon(
Icons.person_add_rounded,
size: 80,
color: AppColor.blueColor,
),
),
const SizedBox(height: 32),
_buildFieldTitle('الاسم الأول'),
MyTextForm(
controller: controller.firstName,
label: 'الاسم الأول',
hint: 'أدخل الاسم الأول',
type: TextInputType.name,
),
const SizedBox(height: 16),
_buildFieldTitle('الاسم الأخير'),
MyTextForm(
controller: controller.lastName,
label: 'الاسم الأخير',
hint: 'أدخل الاسم الأخير',
type: TextInputType.name,
),
const SizedBox(height: 16),
_buildFieldTitle('البريد الإلكتروني'),
MyTextForm(
controller: controller.email,
label: 'البريد الإلكتروني',
hint: 'example@mail.com',
type: TextInputType.emailAddress,
),
const SizedBox(height: 16),
_buildFieldTitle('رقم الهاتف'),
MyTextForm(
controller: controller.phone,
label: 'رقم الهاتف',
hint: '09xxxxxxxx',
type: TextInputType.phone,
),
const SizedBox(height: 16),
_buildFieldTitle('كلمة المرور'),
MyTextForm(
controller: controller.password,
label: 'كلمة المرور',
hint: '********',
type: TextInputType.visiblePassword,
),
const SizedBox(height: 40),
Obx(() => controller.isLoading.value
? const Center(child: CircularProgressIndicator())
: Container(
height: 55,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: const LinearGradient(
colors: [AppColor.blueColor, Color(0xFF1A237E)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
boxShadow: [
BoxShadow(
color: AppColor.blueColor.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 6),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () => controller.register(),
child: const Center(
child: Text(
'تقديم طلب تسجيل',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
)),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'لديك حساب بالفعل؟ '.tr,
style: const TextStyle(color: Colors.grey),
),
TextButton(
onPressed: () => Get.back(),
child: const Text(
'تسجيل الدخول',
style: TextStyle(
color: AppColor.blueColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 20),
],
),
),
),
),
);
}
Widget _buildFieldTitle(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0, right: 4.0),
child: Text(
title,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.black54,
),
),
);
}
}

View File

@@ -262,7 +262,7 @@ class Main extends StatelessWidget {
"license_type": mainController.licenseTypeController.text, "license_type": mainController.licenseTypeController.text,
"phone": mainController.phoneController.text, "phone": mainController.phoneController.text,
}); });
if (res != 'failure') { if (res != 'failure' && res['status'] == 'success') {
Get.back(); Get.back();
mainController.driverNameController.clear(); mainController.driverNameController.clear();
mainController.nationalIdController.clear(); mainController.nationalIdController.clear();
@@ -361,7 +361,7 @@ class Main extends StatelessWidget {
"phone": mainController.phoneCarController.text, "phone": mainController.phoneCarController.text,
}); });
Log.print('res: ${res}'); Log.print('res: ${res}');
if (res != 'failure') { if (res != 'failure' && res['status'] == 'success') {
Get.back(); Get.back();
mainController.ownerController.clear(); mainController.ownerController.clear();
mainController.carNumberController.clear(); mainController.carNumberController.clear();

View File

@@ -9,6 +9,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)

View File

@@ -14,7 +14,6 @@ import flutter_image_compress_macos
import flutter_local_notifications import flutter_local_notifications
import flutter_secure_storage_macos import flutter_secure_storage_macos
import google_sign_in_ios import google_sign_in_ios
import path_provider_foundation
import share_plus import share_plus
import sqflite_darwin import sqflite_darwin
import url_launcher_macos import url_launcher_macos
@@ -29,7 +28,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,8 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.6 cupertino_icons: ^1.0.6
device_info_plus: ^11.3.3
secure_string_operations: secure_string_operations:
path: ./secure_string_operations path: ./secure_string_operations
firebase_messaging: ^16.0.0 firebase_messaging: ^16.0.0

View File

@@ -14,6 +14,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
flutter_local_notifications_windows flutter_local_notifications_windows
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)