service 2-5-26-1
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
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 {
|
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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
// ── JWT Validity Check (No external libs) ──────────────────────
|
||||||
'aud': '${AK.allowed}$dev',
|
static bool _isJwtValid(String? token) {
|
||||||
};
|
if (token == null || token.isEmpty) return false;
|
||||||
var response0 = await http.post(
|
try {
|
||||||
Uri.parse(AppLink.jwtService),
|
final parts = token.split('.');
|
||||||
body: payload,
|
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) {}
|
||||||
|
}
|
||||||
|
|
||||||
if (response0.statusCode == 200) {
|
String _getFpHeader() {
|
||||||
final decodedResponse1 = jsonDecode(response0.body);
|
return box.read(BoxName.fingerPrint)?.toString() ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
final jwt = decodedResponse1['jwt'];
|
// ═══════════════════════════════════════════════════════════════
|
||||||
Log.print('jwt: ${jwt}');
|
// _makeRequest — Central Request Handler
|
||||||
box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs));
|
// ───────────────────────────────────────────────────────────────
|
||||||
|
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) {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
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: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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
|||||||
@@ -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 = {
|
||||||
"email": storedEmail,
|
"fingerprint": fingerprint,
|
||||||
"password": storedPassword,
|
"password": pass,
|
||||||
|
"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 {
|
||||||
|
await EncryptionHelper.initialize();
|
||||||
|
await DeviceHelper.getDeviceFingerprint();
|
||||||
|
|
||||||
|
// Auto login if credentials exist
|
||||||
|
String? storedPassword = await storage.read(key: 'password');
|
||||||
|
if (storedPassword != null) {
|
||||||
login();
|
login();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
super.onInit();
|
super.onInit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,51 +1,172 @@
|
|||||||
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: [
|
||||||
|
// 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,
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
),
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(16.0),
|
),
|
||||||
|
|
||||||
|
SafeArea(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30.0),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: controller.formKey,
|
key: controller.formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
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),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
MyTextForm(
|
MyTextForm(
|
||||||
controller: controller.email,
|
controller: controller.email,
|
||||||
label: 'email',
|
label: 'البريد الإلكتروني',
|
||||||
hint: 'email',
|
hint: 'أدخل البريد الإلكتروني',
|
||||||
type: TextInputType.emailAddress),
|
type: TextInputType.emailAddress,
|
||||||
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
MyTextForm(
|
MyTextForm(
|
||||||
controller: controller.password,
|
controller: controller.password,
|
||||||
label: 'Password',
|
label: 'كلمة المرور',
|
||||||
hint: 'Password',
|
hint: 'أدخل كلمة المرور',
|
||||||
type: TextInputType.name),
|
type: TextInputType.visiblePassword,
|
||||||
|
),
|
||||||
|
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
CupertinoButton.filled(
|
|
||||||
child: const Text('Login'),
|
// Login Button
|
||||||
onPressed: () {
|
Container(
|
||||||
controller.login();
|
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 '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';
|
||||||
|
|||||||
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,
|
"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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
450
pubspec.lock
450
pubspec.lock
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user