service 2-5-26-1
This commit is contained in:
@@ -7,6 +7,8 @@ class BoxName {
|
||||
static const String firstTimeLoadKey = 'firstTimeLoadKey';
|
||||
static const String jwt = "jwt";
|
||||
static const String fingerPrint = "fingerPrint";
|
||||
static const String deviceFingerprint = "deviceFingerprint";
|
||||
|
||||
static const String payMobApikey = "payMobApikey";
|
||||
static const String employeename = "employeename";
|
||||
static const String refreshToken = "refreshToken";
|
||||
|
||||
@@ -10,17 +10,24 @@ class AppLink {
|
||||
static final String seferCairoServer = Env.seferCairoServer;
|
||||
static final String seferGizaServer = Env.seferGizaServer;
|
||||
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 = 'https://location.intaleq.xyz/intaleq/ride/location';
|
||||
static String location = locationServer;
|
||||
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 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 server = Env.serverPHP;
|
||||
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 String addError = "$server/Admin/errorApp.php";
|
||||
|
||||
|
||||
// static final String endPoint = box.read(BoxName.serverChosen);
|
||||
// static final String server = Env.seferCairoServer;
|
||||
@@ -34,6 +41,8 @@ class AppLink {
|
||||
static String uploadEgypt = "$server/uploadEgypt.php";
|
||||
static String auth = '$server/auth';
|
||||
static String login = "$serviceApp/login.php";
|
||||
static String register = "$serviceApp/register.php";
|
||||
|
||||
static String signUp = "$auth/signup.php";
|
||||
static String sendVerifyEmail = "$auth/sendVerifyEmail.php";
|
||||
static String passengerRemovedAccountEmail =
|
||||
|
||||
78
lib/controller/auth/register_controller.dart
Normal file
78
lib/controller/auth/register_controller.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class Driverthebest extends GetxController {
|
||||
getBestDriver() async {
|
||||
var res = await CRUD().get(link: AppLink.getBestDriver, payload: {});
|
||||
if (res != 'failure') {
|
||||
driver = jsonDecode(res)['message'];
|
||||
driver = res['message'];
|
||||
// Log.print('driver: ${driver}');
|
||||
update();
|
||||
} else {
|
||||
@@ -34,7 +34,7 @@ class DriverTheBestGizaController extends GetxController {
|
||||
getBestDriver() async {
|
||||
var res = await CRUD().get(link: AppLink.getBestDriverGiza, payload: {});
|
||||
if (res != 'failure') {
|
||||
driver = jsonDecode(res)['message'];
|
||||
driver = res['message'];
|
||||
|
||||
update();
|
||||
} else {
|
||||
@@ -56,7 +56,7 @@ class DriverTheBestAlexandriaController extends GetxController {
|
||||
var res =
|
||||
await CRUD().get(link: AppLink.getBestDriverAlexandria, payload: {});
|
||||
if (res != 'failure') {
|
||||
driver = jsonDecode(res)['message'];
|
||||
driver = res['message'];
|
||||
update();
|
||||
} else {
|
||||
Get.snackbar('error', '', backgroundColor: AppColor.redColor);
|
||||
|
||||
@@ -11,6 +11,7 @@ import '../../constant/colors.dart';
|
||||
import '../../constant/links.dart';
|
||||
import '../../constant/style.dart';
|
||||
import '../../main.dart';
|
||||
import 'functions/crud.dart';
|
||||
|
||||
class FirebaseMessagesController extends GetxController {
|
||||
final fcmToken = FirebaseMessaging.instance;
|
||||
@@ -55,25 +56,16 @@ class FirebaseMessagesController extends GetxController {
|
||||
}
|
||||
|
||||
Future getTokens() async {
|
||||
String? basicAuthCredentials =
|
||||
await storage.read(key: BoxName.basicAuthCredentials);
|
||||
var res = await http.post(
|
||||
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'];
|
||||
var res = await CRUD().post(link: AppLink.getTokens, payload: {});
|
||||
if (res != 'failure' && res['status'] == 'success') {
|
||||
dataTokens = res['data'];
|
||||
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);
|
||||
} else {
|
||||
Get.defaultDialog(title: "Warning", middleText: "Server Error");
|
||||
Get.snackbar("Warning".tr, "Server Error".tr,
|
||||
backgroundColor: AppColor.redColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,82 +1,244 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:jwt_decoder/jwt_decoder.dart';
|
||||
import 'package:secure_string_operations/secure_string_operations.dart';
|
||||
import 'package:service/constant/char_map.dart';
|
||||
import 'package:service/constant/box_name.dart';
|
||||
import 'package:service/constant/links.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/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 {
|
||||
var dev;
|
||||
getJWT(String pass, email) async {
|
||||
var dev = Platform.isAndroid ? 'android' : 'ios';
|
||||
var payload = {
|
||||
'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,
|
||||
);
|
||||
static bool _isRefreshingJWT = false;
|
||||
static String _lastErrorSignature = '';
|
||||
static DateTime _lastErrorTimestamp = DateTime(2000);
|
||||
static const Duration _errorLogDebounceDuration = Duration(minutes: 1);
|
||||
|
||||
if (response0.statusCode == 200) {
|
||||
final decodedResponse1 = jsonDecode(response0.body);
|
||||
|
||||
final jwt = decodedResponse1['jwt'];
|
||||
Log.print('jwt: ${jwt}');
|
||||
box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs));
|
||||
// ── JWT Validity Check (No external libs) ──────────────────────
|
||||
static bool _isJwtValid(String? token) {
|
||||
if (token == null || token.isEmpty) return false;
|
||||
try {
|
||||
final parts = token.split('.');
|
||||
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({
|
||||
required String link,
|
||||
Map<String, dynamic>? payload,
|
||||
}) async {
|
||||
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('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'];
|
||||
return await post(link: link, payload: payload);
|
||||
}
|
||||
|
||||
// }
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// 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({
|
||||
required String imagePath,
|
||||
required String driverID,
|
||||
@@ -99,24 +261,24 @@ class CRUD {
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return await response.stream.bytesToString();
|
||||
} else {}
|
||||
}
|
||||
return 'failure';
|
||||
}
|
||||
|
||||
Future<dynamic> getAgoraToken({
|
||||
required String channelName,
|
||||
required String uid,
|
||||
}) async {
|
||||
var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver);
|
||||
var res = await http.get(Uri.parse(
|
||||
// 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'),
|
||||
var res = await http.get(
|
||||
Uri.parse(
|
||||
'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'),
|
||||
// headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'});
|
||||
headers: {'Authorization': 'Bearer '});
|
||||
|
||||
if (res.statusCode == 200) {
|
||||
var response = jsonDecode(res.body);
|
||||
return response['token'];
|
||||
} else {}
|
||||
}
|
||||
return 'failure';
|
||||
}
|
||||
|
||||
Future<dynamic> getLlama({
|
||||
@@ -124,18 +286,14 @@ class CRUD {
|
||||
required String payload,
|
||||
required String prompt,
|
||||
}) async {
|
||||
var url = Uri.parse(
|
||||
link,
|
||||
);
|
||||
var url = Uri.parse(link);
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization':
|
||||
'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy'
|
||||
// 'Authorization': 'Bearer ${Env.llamaKey}'
|
||||
};
|
||||
var data = json.encode({
|
||||
"model": "Llama-3-70b-Inst-FW",
|
||||
// "model": "llama-13b-chat",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
@@ -145,11 +303,7 @@ class CRUD {
|
||||
],
|
||||
"temperature": 0.9
|
||||
});
|
||||
var response = await http.post(
|
||||
url,
|
||||
body: data,
|
||||
headers: headers,
|
||||
);
|
||||
var response = await http.post(url, body: data, headers: headers);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response.body;
|
||||
@@ -157,54 +311,7 @@ class CRUD {
|
||||
return response.statusCode;
|
||||
}
|
||||
|
||||
Future<dynamic> post({
|
||||
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 {
|
||||
sendEmail(String link, Map<String, String>? payload) async {
|
||||
var headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
'Authorization':
|
||||
@@ -215,45 +322,6 @@ class CRUD {
|
||||
request.headers.addAll(headers);
|
||||
|
||||
http.StreamedResponse response = await request.send();
|
||||
if (response.statusCode == 200) {
|
||||
} else {}
|
||||
if (response.statusCode == 200) {}
|
||||
}
|
||||
|
||||
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) {}
|
||||
}
|
||||
|
||||
49
lib/controller/functions/device_helper.dart
Normal file
49
lib/controller/functions/device_helper.dart
Normal 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 '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ import 'package:encrypt/encrypt.dart' as encrypt;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:service/env/env.dart';
|
||||
|
||||
import '../../constant/box_name.dart';
|
||||
import '../../main.dart';
|
||||
import 'package:secure_string_operations/secure_string_operations.dart';
|
||||
import 'package:service/constant/char_map.dart';
|
||||
import 'package:service/print.dart';
|
||||
|
||||
|
||||
class EncryptionHelper {
|
||||
static EncryptionHelper? _instance;
|
||||
@@ -28,29 +30,35 @@ class EncryptionHelper {
|
||||
}
|
||||
debugPrint("Initializing EncryptionHelper...");
|
||||
// Read stored keys
|
||||
String? keyOfApp = Env.keyOfApp;
|
||||
// Log.print('keyOfApp: ${keyOfApp}');
|
||||
String? initializationVector = Env.initializationVector;
|
||||
// Log.print('initializationVector: ${initializationVector}');
|
||||
String keyOfApp = r(Env.keyOfApp).toString().split(Env.addd)[0];
|
||||
String initializationVector = r(Env.initializationVector).toString().split(Env.addd)[0];
|
||||
|
||||
Log.print('Key Length: ${keyOfApp.length}');
|
||||
Log.print('IV Length: ${initializationVector.length}');
|
||||
|
||||
// Set the global instance
|
||||
_instance = EncryptionHelper._(
|
||||
encrypt.Key.fromUtf8(keyOfApp!),
|
||||
encrypt.IV.fromUtf8(initializationVector!),
|
||||
encrypt.Key.fromUtf8(keyOfApp),
|
||||
encrypt.IV.fromUtf8(initializationVector),
|
||||
);
|
||||
debugPrint("EncryptionHelper initialized successfully.");
|
||||
}
|
||||
|
||||
|
||||
/// Encrypts a string
|
||||
String encryptData(String plainText) {
|
||||
Log.print('Encrypting: $plainText');
|
||||
try {
|
||||
|
||||
final encrypter =
|
||||
encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
|
||||
final encrypted = encrypter.encrypt(plainText, iv: iv);
|
||||
return encrypted.base64;
|
||||
} catch (e) {
|
||||
debugPrint('Encryption Error: $e');
|
||||
Log.print('Encryption Error: $e');
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// 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();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ import '../../constant/api_key.dart';
|
||||
import '../../constant/box_name.dart';
|
||||
import '../../constant/colors.dart';
|
||||
import '../../main.dart';
|
||||
import 'package:service/controller/functions/encrypt_decrypt.dart';
|
||||
import 'package:service/env/env.dart';
|
||||
|
||||
|
||||
class ImageController extends GetxController {
|
||||
File? myImage;
|
||||
@@ -199,12 +202,13 @@ class ImageController extends GetxController {
|
||||
length,
|
||||
filename: basename(file.path),
|
||||
);
|
||||
String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
|
||||
request.headers.addAll({
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
||||
'Pragma': 'no-cache',
|
||||
'Expires': '0',
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||
'Authorization': 'Bearer $token',
|
||||
'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '',
|
||||
});
|
||||
// Set the file name to the driverID
|
||||
request.files.add(
|
||||
@@ -292,9 +296,10 @@ class ImageController extends GetxController {
|
||||
length,
|
||||
filename: basename(file.path),
|
||||
);
|
||||
String token = r(box.read(BoxName.jwt) ?? '').toString().split(Env.addd)[0];
|
||||
request.headers.addAll({
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||
'Authorization': 'Bearer $token',
|
||||
'X-Device-FP': box.read(BoxName.fingerPrint)?.toString() ?? '',
|
||||
});
|
||||
// Set the file name to the driverID
|
||||
request.files.add(
|
||||
|
||||
@@ -34,7 +34,7 @@ class AppInitializer {
|
||||
var res =
|
||||
await CRUD().get(link: Env.getapiKey, payload: {"keyName": key1});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
await storage.write(key: key1, value: d[key1].toString());
|
||||
await Future.delayed(Duration.zero);
|
||||
} else {}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import 'dart:convert';
|
||||
|
||||
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/controller/functions/encrypt_decrypt.dart';
|
||||
|
||||
import '../constant/box_name.dart';
|
||||
import '../main.dart';
|
||||
@@ -12,73 +13,73 @@ import '../views/home/main.dart';
|
||||
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
import 'functions/initilize.dart';
|
||||
|
||||
class LoginController extends GetxController {
|
||||
var email = TextEditingController();
|
||||
var email = TextEditingController(); // Kept for UI compatibility
|
||||
var password = TextEditingController();
|
||||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
// Use FlutterSecureStorage instead of GetStorage
|
||||
final FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||
|
||||
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 pass = storedPassword ?? password.text;
|
||||
|
||||
await CRUD()
|
||||
.getJWT(storedPassword ?? password.text, storedEmail ?? email.text);
|
||||
if (pass.isEmpty && !formKey.currentState!.validate()) return;
|
||||
|
||||
if (storedEmail != null) {
|
||||
var payload = {
|
||||
"email": storedEmail,
|
||||
"password": storedPassword,
|
||||
};
|
||||
Log.print('payload: ${payload}');
|
||||
var res = await CRUD().get(link: AppLink.login, payload: payload);
|
||||
Log.print('res: ${res}');
|
||||
var payload = {
|
||||
"fingerprint": fingerprint,
|
||||
"password": pass,
|
||||
"aud": "service",
|
||||
};
|
||||
|
||||
// if (res != 'failure') {
|
||||
var d = jsonDecode(res);
|
||||
Log.print('d: ${d}');
|
||||
if (d['message'] == "Login successful") {
|
||||
// Save data securely in FlutterSecureStorage
|
||||
Log.print('🚀 Login Payload: $payload');
|
||||
var res = await CRUD().post(link: AppLink.login, payload: payload);
|
||||
Log.print('📥 Login Response: $res');
|
||||
|
||||
await box.write(BoxName.employeename, d['data']['first_name']);
|
||||
Get.off(() => Main());
|
||||
// }
|
||||
}
|
||||
if (res != 'failure' && res is Map && res['status'] == 'success') {
|
||||
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 {
|
||||
if (formKey.currentState!.validate()) {
|
||||
var payload = {
|
||||
"email": storedEmail ?? email.text,
|
||||
"password": storedPassword ?? password.text,
|
||||
};
|
||||
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());
|
||||
// }
|
||||
}
|
||||
}
|
||||
Get.snackbar(
|
||||
'خطأ'.tr,
|
||||
res is Map ? res['message'].toString().tr : 'فشل تسجيل الدخول'.tr,
|
||||
backgroundColor: Colors.red.withOpacity(0.7),
|
||||
colorText: Colors.white,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
login();
|
||||
void onInit() async {
|
||||
await EncryptionHelper.initialize();
|
||||
await DeviceHelper.getDeviceFingerprint();
|
||||
|
||||
// Auto login if credentials exist
|
||||
String? storedPassword = await storage.read(key: 'password');
|
||||
if (storedPassword != null) {
|
||||
login();
|
||||
}
|
||||
|
||||
|
||||
super.onInit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ class MainController extends GetxController {
|
||||
var res = await CRUD()
|
||||
.get(link: AppLink.getDriverNotCompleteRegistration, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
driverNotCompleteRegistration = d;
|
||||
filteredDrivers = driverNotCompleteRegistration;
|
||||
update();
|
||||
@@ -208,7 +208,7 @@ class MainController extends GetxController {
|
||||
var res =
|
||||
await CRUD().get(link: AppLink.getDriversWaitingActive, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
driverWantCompleteRegistration = d;
|
||||
filteredDrivers = driverWantCompleteRegistration;
|
||||
update();
|
||||
@@ -222,7 +222,7 @@ class MainController extends GetxController {
|
||||
var res =
|
||||
await CRUD().get(link: AppLink.getDriversPhoneNotComplete, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
driverWantCompleteRegistration = d;
|
||||
filteredDrivers = driverWantCompleteRegistration;
|
||||
update();
|
||||
@@ -235,7 +235,7 @@ class MainController extends GetxController {
|
||||
getNewDriverRegister() async {
|
||||
var res = await CRUD().get(link: AppLink.getNewDriverRegister, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
newDriverRegister = d;
|
||||
update();
|
||||
} else {
|
||||
@@ -248,7 +248,7 @@ class MainController extends GetxController {
|
||||
"driverId": driveId,
|
||||
"notes": notesController.text,
|
||||
});
|
||||
if (res != 'failue') {
|
||||
if (res != 'failure') {
|
||||
Get.snackbar('Success'.tr, '', backgroundColor: AppColor.greenColor);
|
||||
}
|
||||
}
|
||||
@@ -259,7 +259,7 @@ class MainController extends GetxController {
|
||||
var res = await CRUD()
|
||||
.get(link: AppLink.getPassengersNotCompleteRegistration, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
passengerNotCompleteRegistration = d;
|
||||
update();
|
||||
} else {
|
||||
@@ -285,7 +285,7 @@ class MainController extends GetxController {
|
||||
getCarPlateNotEdit() async {
|
||||
var res = await CRUD().get(link: AppLink.getCarPlateNotEdit, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
carPlateNotEdit = d;
|
||||
update();
|
||||
} else {
|
||||
@@ -300,7 +300,7 @@ class MainController extends GetxController {
|
||||
getdriverWithoutCar() async {
|
||||
var res = await CRUD().get(link: AppLink.getdriverWithoutCar, payload: {});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
var d = res['message'];
|
||||
driverWithoutCar = d;
|
||||
update();
|
||||
} else {
|
||||
@@ -351,11 +351,11 @@ class MainController extends GetxController {
|
||||
isLoading = false;
|
||||
update();
|
||||
|
||||
var status = jsonDecode(res);
|
||||
var status = res;
|
||||
Log.print('res: $res');
|
||||
Log.print('status: $status');
|
||||
|
||||
if (status['status'] == 'success') {
|
||||
if (status != 'failure' && status['status'] == 'success') {
|
||||
await Future.wait([
|
||||
CRUD().post(
|
||||
link:
|
||||
@@ -492,7 +492,7 @@ class MainController extends GetxController {
|
||||
payload: {"phone": passengerPhoneController.text});
|
||||
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res);
|
||||
var d = res;
|
||||
passengerData = d;
|
||||
update();
|
||||
}
|
||||
@@ -504,7 +504,7 @@ class MainController extends GetxController {
|
||||
payload: {"phone": driverPhoneController.text});
|
||||
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res);
|
||||
var d = res;
|
||||
driverData = d;
|
||||
update();
|
||||
} else {
|
||||
@@ -518,7 +518,7 @@ class MainController extends GetxController {
|
||||
payload: {"national_number": driverPhoneController.text});
|
||||
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res);
|
||||
var d = res;
|
||||
driverData = d;
|
||||
update();
|
||||
} else {
|
||||
|
||||
@@ -96,7 +96,7 @@ class Driverthebest extends GetxController {
|
||||
getBestDriver() async {
|
||||
var res = await CRUD().get(link: AppLink.getBestDriver, payload: {});
|
||||
if (res != 'failure') {
|
||||
driver = jsonDecode(res)['message'];
|
||||
driver = res['message'];
|
||||
update();
|
||||
} else {
|
||||
Get.snackbar('error', '', backgroundColor: AppColor.redColor);
|
||||
|
||||
@@ -108,7 +108,7 @@ class RegisterCaptainServiceController extends GetxController {
|
||||
payload: {'driverId': driverId.value});
|
||||
|
||||
if (responseString != 'failure') {
|
||||
var decodedResponse = jsonDecode(responseString);
|
||||
var decodedResponse = responseString;
|
||||
if (decodedResponse['status'] == 'success' &&
|
||||
(decodedResponse['message'] as List).isNotEmpty) {
|
||||
var rawData = decodedResponse['message'][0] as Map<String, dynamic>;
|
||||
@@ -261,7 +261,7 @@ class RegisterCaptainServiceController extends GetxController {
|
||||
isLoading.value = false;
|
||||
var decodedResponse = (response);
|
||||
Log.print('decodedResponse: ${decodedResponse}');
|
||||
if (decodedResponse != 'failure') {
|
||||
if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') {
|
||||
MyDialog().getDialog('Success'.tr, '',
|
||||
Text('Driver has been activated successfully!'.tr), () {
|
||||
Get.back();
|
||||
@@ -273,7 +273,7 @@ class RegisterCaptainServiceController extends GetxController {
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Error'.tr,
|
||||
'Failed to update driver: ${decodedResponse['message']}'.tr,
|
||||
'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
||||
@@ -107,7 +107,7 @@ class RegisterCaptainController extends GetxController {
|
||||
payload: {'driverId': driverId.value});
|
||||
|
||||
if (responseString != 'failure') {
|
||||
var decodedResponse = jsonDecode(responseString);
|
||||
var decodedResponse = responseString;
|
||||
if (decodedResponse['status'] == 'success' &&
|
||||
(decodedResponse['message'] as List).isNotEmpty) {
|
||||
var rawData = decodedResponse['message'][0] as Map<String, dynamic>;
|
||||
@@ -247,7 +247,7 @@ class RegisterCaptainController extends GetxController {
|
||||
isLoading.value = false;
|
||||
var decodedResponse = (response);
|
||||
Log.print('decodedResponse: ${decodedResponse}');
|
||||
if (decodedResponse != 'failure') {
|
||||
if (decodedResponse != 'failure' && decodedResponse['status'] == 'success') {
|
||||
MyDialog().getDialog('Success'.tr, '',
|
||||
Text('Driver has been activated successfully!'.tr), () {
|
||||
Get.back();
|
||||
@@ -259,7 +259,7 @@ class RegisterCaptainController extends GetxController {
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Error'.tr,
|
||||
'Failed to update driver: ${decodedResponse['message']}'.tr,
|
||||
'Failed to update driver: ${decodedResponse is Map ? decodedResponse['message'] : 'failure'}'.tr,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
||||
@@ -1,50 +1,171 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.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 'controller/login_controller.dart';
|
||||
|
||||
class LoginPage extends StatelessWidget {
|
||||
final LoginController controller = Get.put(LoginController());
|
||||
const LoginPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final LoginController controller = Get.put(LoginController());
|
||||
|
||||
return Scaffold(
|
||||
appBar: const CupertinoNavigationBar(
|
||||
middle: Text('Login'),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
MyTextForm(
|
||||
controller: controller.email,
|
||||
label: 'email',
|
||||
hint: 'email',
|
||||
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();
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
body: Stack(
|
||||
children: [
|
||||
// Background Gradient Element
|
||||
Positioned(
|
||||
top: -100,
|
||||
right: -100,
|
||||
child: Container(
|
||||
width: 300,
|
||||
height: 300,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [AppColor.blueColor.withOpacity(0.2), Colors.transparent],
|
||||
begin: Alignment.topRight,
|
||||
end: Alignment.bottomLeft,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:service/controller/firbase_messge.dart';
|
||||
import 'package:service/firebase_options.dart';
|
||||
|
||||
import 'controller/functions/encrypt_decrypt.dart';
|
||||
import 'controller/functions/initilize.dart';
|
||||
import 'controller/local/local_controller.dart';
|
||||
import 'controller/local/translations.dart';
|
||||
import 'login_page.dart';
|
||||
|
||||
172
lib/views/auth/register_page.dart
Normal file
172
lib/views/auth/register_page.dart
Normal 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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -262,7 +262,7 @@ class Main extends StatelessWidget {
|
||||
"license_type": mainController.licenseTypeController.text,
|
||||
"phone": mainController.phoneController.text,
|
||||
});
|
||||
if (res != 'failure') {
|
||||
if (res != 'failure' && res['status'] == 'success') {
|
||||
Get.back();
|
||||
mainController.driverNameController.clear();
|
||||
mainController.nationalIdController.clear();
|
||||
@@ -361,7 +361,7 @@ class Main extends StatelessWidget {
|
||||
"phone": mainController.phoneCarController.text,
|
||||
});
|
||||
Log.print('res: ${res}');
|
||||
if (res != 'failure') {
|
||||
if (res != 'failure' && res['status'] == 'success') {
|
||||
Get.back();
|
||||
mainController.ownerController.clear();
|
||||
mainController.carNumberController.clear();
|
||||
|
||||
Reference in New Issue
Block a user