diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000..776785b Binary files /dev/null and b/assets/images/logo.png differ diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart index 95465d6..0da7d8e 100644 --- a/lib/constant/box_name.dart +++ b/lib/constant/box_name.dart @@ -3,4 +3,9 @@ class BoxName { static const String lang = "lang"; static const String agreeTerms = "agreeTerms"; + static const String pasengerID = "pasengerID"; + static const String phone = "phone"; + static const String email = "email"; + static const String tokens = "tokens"; + static const String tokenFCM = "tokenFCM"; } diff --git a/lib/constant/credential.dart b/lib/constant/credential.dart index 1c80ea9..f2aa832 100644 --- a/lib/constant/credential.dart +++ b/lib/constant/credential.dart @@ -2,15 +2,11 @@ import 'dart:convert'; class AppCredintials { static const String basicAuthCredentials = 'hamzaayedphp:malDEV@2101'; - static const String serverAPI = 'fgdgf'; + static const String serverAPI = + 'AAAAinYllCo:APA91bF1shTpzSsSxqbfY6c60D8zs1ZsdIsl9ix6nl7GDdjCqWPRK0G0ub5SqFdb1jDpQDvQPxGg-697MWLo0sy3oYImBwBLObyhk0GjtNzyr0PbE3hI-pOvhf8Vp1xgUgBmofbZYXkH'; // AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0 static const String mapAPIKEY = 'AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0'; - //AIzaSyDf_9y315-15v416-_5a536-b24164b31456 - //AIzaSyC4y2434-h13-c4y2434-h13-c4y2434-h13 - // AIzaSyD10234567890AB123CDEF - // AIzaSyDf416u6_y2-2g_2-Q4d-a74r3-4v83-4h8 - // AIzaSyD_d6x8a1r2-527-37-43-43-56-37 -// + String getBasicAuthCredentials() { return base64Encode(utf8.encode(basicAuthCredentials)); } diff --git a/lib/constant/links.dart b/lib/constant/links.dart index 0fac7c5..e582bbf 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -3,6 +3,9 @@ class AppLink { static const String googleMapsLink = 'https://maps.googleapis.com/maps/api/'; static const String test = "$server/test.php"; + //===============firebase========================== + static const String getTokens = "$server/ride/firebase/get.php"; + static const String addTokens = "$server/ride/firebase/add.php"; static const String pathImage = "$server/upload/types/"; static const String uploadImage = "$server/uploadImage.php"; @@ -24,6 +27,9 @@ class AppLink { static const String updateBlog = "$blog/update.php"; //===================Auth============ - static const String auth = 'https://ride.mobile-app.store/auth/'; + static const String auth = 'https://ride.mobile-app.store/auth'; static const String login = "$auth/login.php"; + static const String signUp = "$auth/signup.php"; + static const String sendVerifyEmail = "$auth/sendVerifyEmail.php"; + static const String verifyEmail = "$auth/verifyEmail.php"; } diff --git a/lib/controller/auth/login_controller.dart b/lib/controller/auth/login_controller.dart index 2009419..74f63dc 100644 --- a/lib/controller/auth/login_controller.dart +++ b/lib/controller/auth/login_controller.dart @@ -1,11 +1,13 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; import 'package:ride/constant/box_name.dart'; import 'package:ride/constant/links.dart'; import 'package:ride/controller/functions/crud.dart'; import 'package:ride/main.dart'; +import 'package:ride/views/home/map_page.dart'; class LoginController extends GetxController { final formKey = GlobalKey(); @@ -13,6 +15,8 @@ class LoginController extends GetxController { TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); bool isAgreeTerms = false; + bool isloading = false; + final FlutterSecureStorage _storage = FlutterSecureStorage(); void changeAgreeTerm() { isAgreeTerms = !isAgreeTerms; @@ -25,26 +29,60 @@ class LoginController extends GetxController { update(); } + void saveData(String key, value) async { + await _storage.write(key: key, value: value); + } + + Future readData(String boxName) async { + final String? value = await _storage.read(key: boxName); + return value; + } + void login() async { - Map res = await CRUD().post(link: AppLink.login, payload: { + isloading = true; + update(); + var res = await CRUD().get(link: AppLink.login, payload: { 'email': emailController.text, 'phone': phoneController.text, 'password': passwordController.text }); - if (res.isNotEmpty) { - if (res['status'] == 'success1') { - print(res); - } else { - print('noooooooooooooooo'); + var jsonDecoeded = jsonDecode(res); + // print(jsonDecoeded); + if (jsonDecoeded.isNotEmpty) { + if (jsonDecoeded['status'] == 'success') { + box.write(BoxName.pasengerID, jsonDecoeded['data'][0]['id']); + box.write(BoxName.email, jsonDecoeded['data'][0]['email']); + box.write(BoxName.phone, jsonDecoeded['data'][0]['phone']); + Get.offAll(() => MapPage()); + + isloading = false; + update(); + print(box.read(BoxName.pasengerID).toString()); + await CRUD().post(link: AppLink.addTokens, payload: { + 'token': box.read(BoxName.tokenFCM.toString()), + 'passengerID': box.read(BoxName.pasengerID).toString() + }).then((value) => print('cccc')); + } else if (jsonDecoeded['status'] == 'Failure') { + Get.snackbar(jsonDecoeded['status'], jsonDecoeded['data'], + backgroundColor: Colors.redAccent); + isloading = false; + update(); } } else { print('res is null'); } } + goToMapPage() { + if (box.read(BoxName.email) != null) { + Get.offAll(() => const MapPage()); + } + } + @override void onInit() { super.onInit(); + goToMapPage(); } } diff --git a/lib/controller/auth/register_controller.dart b/lib/controller/auth/register_controller.dart index dc16390..cfb7b29 100644 --- a/lib/controller/auth/register_controller.dart +++ b/lib/controller/auth/register_controller.dart @@ -1,5 +1,13 @@ +import 'dart:convert'; +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:ride/constant/links.dart'; +import 'package:ride/controller/functions/crud.dart'; +import 'package:ride/views/home/map_page.dart'; + +import '../../views/auth/verify_email_page.dart'; class RegisterController extends GetxController { final formKey = GlobalKey(); @@ -9,8 +17,11 @@ class RegisterController extends GetxController { TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); + TextEditingController siteController = TextEditingController(); + TextEditingController verfyCode = TextEditingController(); String birthDate = 'Birth Date'.tr; + String gender = 'Male'.tr; @override void onInit() { super.onInit(); @@ -40,9 +51,41 @@ class RegisterController extends GetxController { ); } - void register() { - if (formKey.currentState!.validate()) { - // Do something with the data + void changeGender(String value) { + gender = value; + update(); + } + + sendverfications() async { + var res = await CRUD().post(link: AppLink.verifyEmail, payload: { + 'email': emailController.text, + 'token': verfyCode.text, + }); + var jsondecod = jsonDecode(res); + + if (jsondecod['status'] == 'success') { + Get.offAll(() => const MapPage()); } } + + void register() async { + if (formKey.currentState!.validate()) { + await CRUD().post(link: AppLink.signUp, payload: { + 'first_name': firstNameController.text, + 'last_name': lastNameController.text, + 'email': emailController.text, + 'phone': phoneController.text, + 'password': passwordController.text, + 'gender': gender, + 'site': siteController.text, + 'birthdate': birthDate, + }).then((value) => print(value)); + } + int randomNumber = Random().nextInt(100000) + 1; + await CRUD().post(link: AppLink.sendVerifyEmail, payload: { + 'email': emailController.text, + 'token': randomNumber.toString(), + }).then((value) => print(value)); + Get.to(() => const VerifyEmailPage()); + } } diff --git a/lib/controller/auth/tokens_controller.dart b/lib/controller/auth/tokens_controller.dart new file mode 100644 index 0000000..34382bc --- /dev/null +++ b/lib/controller/auth/tokens_controller.dart @@ -0,0 +1,39 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; + +import '../../constant/box_name.dart'; +import '../../constant/credential.dart'; +import '../../constant/links.dart'; +import '../../main.dart'; + +class TokenController extends GetxController { + bool isloading = false; + + Future addToken() async { + isloading = true; + update(); + var res = await http.post( + Uri.parse(AppLink.addTokens), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AppCredintials.basicAuthCredentials))}', + }, + body: { + 'token': box.read(BoxName.tokenFCM.toString()), + 'passengerID': box.read(BoxName.pasengerID).toString() + }, + ); + + isloading = false; + update(); + print(res.request); + print(res.body); + var jsonToken = jsonDecode(res.body); + // print(jsonToken); + if (jsonToken['status'] == 'The token has been updated successfully.') { + Get.snackbar('token updated', 'message'); + } + } +} diff --git a/lib/controller/auth/verify_email_controller.dart b/lib/controller/auth/verify_email_controller.dart new file mode 100644 index 0000000..99863cc --- /dev/null +++ b/lib/controller/auth/verify_email_controller.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/links.dart'; +import 'package:ride/controller/functions/crud.dart'; + +class VerifyEmailController extends GetxController { + TextEditingController verfyCode = TextEditingController(); + @override + void onInit() async { + super.onInit(); + } + + sendverfications() async { + await CRUD().post(link: AppLink.sendVerifyEmail); + } +} diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart new file mode 100644 index 0000000..b68d88a --- /dev/null +++ b/lib/controller/firebase/firbase_messge.dart @@ -0,0 +1,249 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; + +import '../../constant/box_name.dart'; +import '../../constant/credential.dart'; +import '../../constant/links.dart'; +import '../../main.dart'; + +class FirebasMessagesController extends GetxController { + final fcmToken = FirebaseMessaging.instance; + + List tokens = []; + List dataTokens = []; + NotificationSettings? notificationSettings; + @override + void onInit() async { + super.onInit(); + // getNotificationSettings(); + getToken(); + getTokens(); + } + + Future getNotificationSettings() async { + // Get the current notification settings. + notificationSettings = + await FirebaseMessaging.instance.getNotificationSettings(); + print('------noti======'); + print(notificationSettings!.authorizationStatus.toString()); + update(); + } + + void requestPermission() async { + // Check if the platform is Android + if (Platform.isAndroid) { + // Request permission for Android + fcmToken.requestPermission().then((value) { + if (value!.authorizationStatus == AuthorizationStatus.denied) { + print('dddddddddddddddddddddd'); + } + }); + } else { + // Request permission for iOS + NotificationSettings settings = await fcmToken.requestPermission( + alert: true, + announcement: true, + badge: true, + carPlay: true, + criticalAlert: true, + provisional: false, + sound: true, + ); + print('User granted permission: ${settings.authorizationStatus}'); + fcmToken.setForegroundNotificationPresentationOptions( + alert: true, badge: true, sound: true); + } + } + + Future getTokens() async { + var res = await http.post( + Uri.parse(AppLink.getTokens), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AppCredintials.basicAuthCredentials))}', + }, + body: {}, + ); + // print(res.body); + var jsonResponse = jsonDecode(res.body); + // print(jsonResponse); + if (jsonResponse['status'] == 'success') { + dataTokens = jsonResponse['data']; + for (var i = 0; i < dataTokens.length; i++) { + tokens.add(jsonResponse['data'][i]['token']); + } + box.write(BoxName.tokens, tokens); + print(box.read(BoxName.tokens)); + } else { + Get.defaultDialog(title: "Warning", middleText: "Server Error"); + } + } + + void getToken() async { + // final SharedPreferences prefs = await SharedPreferences.getInstance(); + await fcmToken.getToken().then( + (token) { + // print(token);/ + box.write(BoxName.tokenFCM, token); + }, + ); + FirebaseMessaging.onMessage.listen((event) { + print( + 'onMessage: ${event.notification!.title} ${event.notification!.body}'); + if (Get.currentRoute == '/') { + // If the app is in the foreground, show a dialog to the user + if (event.notification!.title.toString().contains('reef')) { + // Get.snackbar('reeffff', 'message'); + } else if (event.notification!.title.toString().contains('انذار')) { + // Get.to(() => const ProfilePage()); + } else if (event.notification!.title + .toString() + .contains('تعديل طلبيات')) {} + } else if (event.notification!.title.toString().contains('Deleted')) { + // LogOutController().removeKeys(prefs); + } else { + // If the app is in the background or terminated, show a system tray message + RemoteNotification? notification = event.notification; + AndroidNotification? android = event.notification?.android; + // if (notification != null && android != null) { + if (notification != null && android != null) { + print( + 'onMessageOpenedApp: ${notification.title} ${notification.body}'); + if (event.notification!.title.toString().contains('reef')) { + // Get.snackbar('reef', ''); + // SendGpsNow().getSiteNotification(); + } else if (event.notification!.title.toString().contains('انذار')) { + // Get.to(() => const ProfilePage()); + } else if (event.notification!.title + .toString() + .contains('تعديل طلبيات')) { + // Get.to(() => const OrdersDriverPage()); + } else if (event.notification!.title.toString().contains('Deleted')) { + // LogOutController().removeKeys(prefs); + } + } + } + }); + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage event) { + print( + 'onMessageOpenedApp: ${event.notification!.title} ${event.notification!.body}'); + RemoteNotification? notification = event.notification; + if (notification != null) { + print('onMessageOpenedApp: ${notification.title} ${notification.body}'); + + if (event.notification!.title.toString().contains('reef')) { + // Get.snackbar('reef', ''); + // SendGpsNow().getSiteNotification(); + } else if (event.notification!.title.toString().contains('انذار')) { + // Get.to(() => const ProfilePage()); + } else if (event.notification!.title + .toString() + .contains('تعديل طلبيات')) { + // Get.to(() => const OrdersDriverPage()); + } else if (event.notification!.title.toString().contains('Deleted')) { + // LogOutController().removeKeys(prefs); + } + } + }); + } + + void sendNotificationAll(String title, body) async { + // Get the token you want to subtract. + String token = box.read(BoxName.tokenFCM); + tokens = box.read(BoxName.tokens); + // Subtract the token from the list of tokens. + tokens.remove(token); + + // Save the list of tokens back to the box. + // box.write(BoxName.tokens, tokens); + tokens = box.read(BoxName.tokens); + // print(tokens); + for (var i = 0; i < tokens.length; i++) { + http + .post(Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AppCredintials.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'true' + }, + 'priority': 'high', + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'to': tokens[i], + })) + .whenComplete(() {}) + .catchError((e) { + print('sendNotification() error: $e'); + }); + } + } + + void sendNotificationToManager(String title, body) async { + // tokens = box.read(BoxName.tokenManager); + + for (var i = 0; i < tokens.length; i++) { + http + .post(Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AppCredintials.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'true' + }, + 'priority': 'high', + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'to': tokens[i], + })) + .whenComplete(() {}) + .catchError((e) { + print('sendNotification() error: $e'); + }); + } + } + + void sendNotificationDriverId(String title, body, token) async { + http + .post(Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AppCredintials.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'true' + }, + 'priority': 'high', + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'to': token, + })) + .whenComplete(() {}) + .catchError((e) { + print('sendNotification() error: $e'); + }); + } +} diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index c216515..a3442ef 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -25,9 +25,10 @@ class CRUD { if (response.statusCode == 200) { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { - print(jsonData['message']); - return jsonData['message']; + print(jsonData['data']); + return response.body; } + return response.body; } } @@ -47,7 +48,7 @@ class CRUD { 'Basic ${base64Encode(utf8.encode(AppCredintials.basicAuthCredentials))}', }, ); - + print(response.request); if (response.statusCode == 200) { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { @@ -57,12 +58,9 @@ class CRUD { ); return response.body; - } else if (jsonData['status'] == 'success1') { - print(jsonData['data']); - return jsonData; } } - return (response.body); + // return (response.body); } Future getGoogleApi({ diff --git a/lib/controller/functions/location_permission.dart b/lib/controller/functions/location_permission.dart new file mode 100644 index 0000000..9bbf33c --- /dev/null +++ b/lib/controller/functions/location_permission.dart @@ -0,0 +1,16 @@ +import 'package:location/location.dart'; +import 'package:get/get.dart'; + +class LocationPermissions { + late Location location; + + Future locationPermissions() async { + location = Location(); + var permissionStatus = await location.requestPermission(); + if (permissionStatus == PermissionStatus.denied) { + // The user denied the location permission. + Get.defaultDialog(title: 'GPS Required Allow !.'.tr, middleText: ''); + return null; + } + } +} diff --git a/lib/controller/home/map_page_controller.dart b/lib/controller/home/map_page_controller.dart index 6af1609..9ade3c1 100644 --- a/lib/controller/home/map_page_controller.dart +++ b/lib/controller/home/map_page_controller.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -167,8 +169,10 @@ class MapController extends GetxController { } Future getCarsLocationByPassenger() async { - List data = + var res = await CRUD().get(link: AppLink.getCarsLocationByPassenger, payload: {}); + List data = jsonDecode(res); + print(data); for (var i = 0; i < data.length; i++) { carsLocationByPassenger.add(LatLng(double.parse(data[i]['latitude']), double.parse(data[i]['longitude']))); diff --git a/lib/main.dart b/lib/main.dart index 753a995..2fdc601 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; @@ -8,12 +9,24 @@ import 'package:ride/views/auth/login_page.dart'; import 'package:ride/views/lang/languages.dart'; import 'constant/box_name.dart'; +import 'controller/firebase/firbase_messge.dart'; +import 'controller/functions/location_permission.dart'; import 'controller/local/local_controller.dart'; import 'controller/local/translations.dart'; import 'firebase_options.dart'; import 'views/home/map_page.dart'; final box = GetStorage(); +@pragma('vm:entry-point') +Future backgroundMessageHandler(RemoteMessage message) async { + await Firebase.initializeApp(); + print('===========back===${message.notification?.title}'); + + if (message.notification!.title == 'reef') { + // SendGpsNow().getSiteNotification(); + } +} + void main() async { WidgetsFlutterBinding.ensureInitialized(); await GetStorage.init(); @@ -22,6 +35,10 @@ void main() async { options: DefaultFirebaseOptions.currentPlatform, ); } + LocationPermissions().locationPermissions(); + FirebasMessagesController().getToken(); + await FirebasMessagesController().getTokens(); + FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); runApp(const MyApp()); } @@ -46,6 +63,8 @@ class MyApp extends StatelessWidget { home: box.read(BoxName.lang).toString() != 'ar' && box.read(BoxName.lang).toString() != 'en' ? const Language() - : LoginPage()); + : box.read(BoxName.email).toString() != null + ? const MapPage() + : LoginPage()); } } diff --git a/lib/views/auth/login_page.dart b/lib/views/auth/login_page.dart index 68a65bf..076e08c 100644 --- a/lib/views/auth/login_page.dart +++ b/lib/views/auth/login_page.dart @@ -9,6 +9,7 @@ import 'package:ride/views/widgets/elevated_btn.dart'; import 'package:ride/views/widgets/my_scafold.dart'; import '../../controller/auth/login_controller.dart'; +import '../widgets/mycircular.dart'; import 'register_page.dart'; class LoginPage extends StatelessWidget { @@ -114,15 +115,19 @@ class LoginPage extends StatelessWidget { return null; }, ), - MyElevatedButton( - onPressed: () { - if (controller.formKey.currentState! - .validate()) { - controller.login(); - } - }, - title: 'Submit', - ), + GetBuilder( + builder: (controller) => controller.isloading + ? const MyCircularProgressIndicator() + : MyElevatedButton( + onPressed: () { + if (controller.formKey.currentState! + .validate()) { + controller.login(); + } + }, + title: 'Submit', + ), + ) ], ), ), @@ -134,7 +139,7 @@ class LoginPage extends StatelessWidget { style: AppStyle.subtitle, ), AnimatedTextKit( - onTap: () => Get.to(() => RegisterPage()), + onTap: () => Get.to(() => const RegisterPage()), animatedTexts: [ TypewriterAnimatedText( 'Register', diff --git a/lib/views/auth/register_page.dart b/lib/views/auth/register_page.dart index b87459f..4c0cb75 100644 --- a/lib/views/auth/register_page.dart +++ b/lib/views/auth/register_page.dart @@ -137,46 +137,97 @@ class RegisterPage extends StatelessWidget { const SizedBox( height: 15, ), - TextFormField( - keyboardType: TextInputType.phone, - cursorColor: AppColor.accentColor, - controller: controller.phoneController, - decoration: InputDecoration( - focusColor: AppColor.accentColor, - fillColor: AppColor.accentColor, - border: const OutlineInputBorder( - borderRadius: - BorderRadius.all(Radius.circular(12))), - labelText: 'Phone'.tr, - hintText: 'Enter your phone number'.tr, - ), - validator: (value) { - if (value!.isEmpty || value.length != 10) { - return 'Please enter your phone number.'.tr; - } - return null; - }, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: Get.width * .4, + child: TextFormField( + keyboardType: TextInputType.phone, + cursorColor: AppColor.accentColor, + controller: controller.phoneController, + decoration: InputDecoration( + focusColor: AppColor.accentColor, + fillColor: AppColor.accentColor, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12))), + labelText: 'Phone'.tr, + hintText: 'Enter your phone number'.tr, + ), + validator: (value) { + if (value!.isEmpty || value.length != 10) { + return 'Please enter your phone number.'.tr; + } + return null; + }, + ), + ), + SizedBox( + width: Get.width * .4, + child: TextFormField( + keyboardType: TextInputType.text, + controller: controller.siteController, + decoration: InputDecoration( + focusColor: AppColor.accentColor, + fillColor: AppColor.accentColor, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12))), + labelText: 'City'.tr, + hintText: 'Enter your City'.tr, + ), + validator: (value) { + if (value!.isEmpty) { + return 'Please enter your City.'.tr; + } + return null; + }, + ), + ), + ], ), const SizedBox( height: 15, ), - InkWell( - onTap: () => controller.getBirthDate(), - child: Container( - height: 50, - width: Get.width, - decoration: BoxDecoration( - border: Border.all(), - borderRadius: BorderRadius.circular(13)), - child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 20), - child: Text( - controller.birthDate, - style: AppStyle.title, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + onTap: () => controller.getBirthDate(), + child: Container( + height: 50, + width: Get.width * .4, + decoration: BoxDecoration( + border: Border.all(), + borderRadius: BorderRadius.circular(13)), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20), + child: Text( + controller.birthDate, + style: AppStyle.title, + ), + ), ), ), - ), + DropdownButton( + value: controller.gender, + items: [ + DropdownMenuItem( + value: 'Male'.tr, + child: Text('Male'.tr), + ), + DropdownMenuItem( + value: 'Female'.tr, + child: Text('Female'.tr), + ), + ], + onChanged: (value) { + controller.changeGender(value!); + }, + ) + ], ), MyElevatedButton( title: 'Register'.tr, diff --git a/lib/views/auth/verify_email_page.dart b/lib/views/auth/verify_email_page.dart new file mode 100644 index 0000000..d421f6d --- /dev/null +++ b/lib/views/auth/verify_email_page.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:ride/constant/colors.dart'; +import 'package:ride/constant/style.dart'; +import 'package:ride/controller/auth/register_controller.dart'; +import 'package:ride/controller/auth/verify_email_controller.dart'; +import 'package:ride/views/widgets/elevated_btn.dart'; +import 'package:ride/views/widgets/my_scafold.dart'; + +class VerifyEmailPage extends StatelessWidget { + const VerifyEmailPage({super.key}); + + @override + Widget build(BuildContext context) { + Get.put(RegisterController()); + return MyScafolld( + title: 'Verify Email'.tr, + body: [ + Positioned( + top: 10, + left: 20, + child: Text( + 'We sent 5 digit to your Email provided'.tr, + style: AppStyle.title.copyWith(fontSize: 20), + )), + GetBuilder( + builder: (controller) => Positioned( + top: 100, + left: 80, + right: 80, + child: Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + width: 100, + child: TextField( + controller: controller.verfyCode, + decoration: InputDecoration( + labelStyle: AppStyle.title, + border: const OutlineInputBorder(), + hintText: '5 digit', + counterStyle: AppStyle.number, + hintStyle: AppStyle.subtitle + .copyWith(color: AppColor.accentColor), + ), + maxLength: 5, + keyboardType: TextInputType.number, + ), + ), + const SizedBox( + height: 30, + ), + MyElevatedButton( + title: 'Send Verfication Code'.tr, + onPressed: () => controller.sendverfications()) + ], + ), + ), + )), + ], + isleading: true, + ); + } + + Padding verifyEmail() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: AppColor.accentColor, + width: 2, + ), + borderRadius: BorderRadius.circular(8), + ), + child: const Padding( + padding: EdgeInsets.all(10), + child: SizedBox( + width: 20, + child: TextField( + maxLength: 1, + keyboardType: TextInputType.number, + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/widgets/mycircular.dart b/lib/views/widgets/mycircular.dart new file mode 100644 index 0000000..366d81a --- /dev/null +++ b/lib/views/widgets/mycircular.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class MyCircularProgressIndicator extends StatelessWidget { + final Color backgroundColor; + + const MyCircularProgressIndicator({ + super.key, + this.backgroundColor = Colors.transparent, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 110, + height: 110, + decoration: BoxDecoration( + color: backgroundColor, + shape: BoxShape.circle, + ), + child: Stack( + children: [ + const Center(child: CircularProgressIndicator()), + Column( + children: [ + Align( + alignment: Alignment.center, + child: Image.asset('assets/images/logo.png'), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index f6f23bf..38dd0bc 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,9 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f16b4c3..65240e9 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_linux url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index ef77a02..881df5d 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import firebase_core import firebase_messaging import flutter_local_notifications +import flutter_secure_storage_macos import location import path_provider_foundation import sqflite @@ -17,6 +18,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 4fe3c8b..e6d9323 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -230,6 +230,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.15" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "98352186ee7ad3639ccc77ad7924b773ff6883076ab952437d20f18a61f0a7c5" + url: "https://pub.dev" + source: hosted + version: "8.0.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "083add01847fc1c80a07a08e1ed6927e9acd9618a35e330239d4422cd2a58c50" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b + url: "https://pub.dev" + source: hosted + version: "1.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: fc2910ec9b28d60598216c29ea763b3a96c401f0ce1d13cdf69ccb0e5c93c3ee + url: "https://pub.dev" + source: hosted + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index de61050..d07b1de 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,6 +53,7 @@ dependencies: google_polyline_algorithm: ^3.1.0 custom_searchable_dropdown: ^2.1.1 animated_text_kit: ^4.2.2 + flutter_secure_storage: ^8.0.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index ec8e8d4..0e0afee 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,11 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 02d26c3..9efea82 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST firebase_core + flutter_secure_storage_windows url_launcher_windows )