Compare commits
12 Commits
1e47dd914a
...
948777ee21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
948777ee21 | ||
|
|
58703af212 | ||
|
|
195a9aab7a | ||
|
|
d91f14c5ca | ||
|
|
2def888574 | ||
|
|
c3cfd64328 | ||
|
|
74f9b14645 | ||
|
|
7ea696d96c | ||
|
|
bef5db2c79 | ||
|
|
83f0f9c990 | ||
|
|
fab01aa29a | ||
|
|
7fa9f4d6f8 |
@@ -11,7 +11,7 @@
|
|||||||
"signUpText": "اشتراك",
|
"signUpText": "اشتراك",
|
||||||
"welcomeText": "مرحبا بعودتك!",
|
"welcomeText": "مرحبا بعودتك!",
|
||||||
"pleaseEnterLoginDetails": "يرجى إدخال تفاصيل تسجيل الدخول الخاصة بك للبدء",
|
"pleaseEnterLoginDetails": "يرجى إدخال تفاصيل تسجيل الدخول الخاصة بك للبدء",
|
||||||
"toGetYourAccountPleaseSetYourInfo": "للحصول على حسابك، يرجى تحديد معلوماتك",
|
"toGetYourAccountPleaseSetYourInfo": "للحصول على حسابك، يرجى تحديد معلوماتك",
|
||||||
"countryOfResidence": "بلد الإقامة",
|
"countryOfResidence": "بلد الإقامة",
|
||||||
"chooseCountry": "اختر الدولة",
|
"chooseCountry": "اختر الدولة",
|
||||||
"phoneNumber": "رقم الهاتف",
|
"phoneNumber": "رقم الهاتف",
|
||||||
@@ -245,6 +245,14 @@
|
|||||||
"tryAgainText": "حاول مرة اخرى",
|
"tryAgainText": "حاول مرة اخرى",
|
||||||
"investmentConfirmationText": "تأكيد الاستثمار",
|
"investmentConfirmationText": "تأكيد الاستثمار",
|
||||||
"enterAmountText": "أدخل المبلغ",
|
"enterAmountText": "أدخل المبلغ",
|
||||||
"pleaseEnterAmountText": "الرجاء إدخال المبلغ"
|
"pleaseEnterAmountText": "الرجاء إدخال المبلغ",
|
||||||
|
"authenticationFailedText" : "المصادقة فشلت",
|
||||||
|
"pleaseAuthenticateToAccessTheApp" : "يرجى المصادقة للوصول إلى التطبيق",
|
||||||
|
"masterPinAddedSucessfullyText" : "تمت إضافة الدبوس الرئيسي بنجاح",
|
||||||
|
"passwordChangedSucessfully" : "تم تغيير الرقم السري بنجاح!",
|
||||||
|
"passwordResetSucessful" : "تمت إعادة تعيين كلمة المرور بنجاح!",
|
||||||
|
"otpSendSuccessfulText" : "تم إرسال OTP بنجاح!",
|
||||||
|
"successfulText" : "ناجح !",
|
||||||
|
"portfolioBottomText" : "مَلَفّ"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"resendSms": "Resend SMS",
|
"resendSms": "Resend SMS",
|
||||||
"otpVerifiedSucessfully": "OTP Verified Successfully!",
|
"otpVerifiedSucessfully": "OTP Verified Successfully!",
|
||||||
"otpVerifiedFailed": "OTP Verification Failed:",
|
"otpVerifiedFailed": "OTP Verification Failed:",
|
||||||
"pinCode": "Pin Code",
|
"pinCode": "Pin Code",
|
||||||
"createPinCode": "Create Pin Code",
|
"createPinCode": "Create Pin Code",
|
||||||
"changePinCode": "Change Pin Code",
|
"changePinCode": "Change Pin Code",
|
||||||
"confirmPinCode": "Confirm Pin Code",
|
"confirmPinCode": "Confirm Pin Code",
|
||||||
@@ -245,6 +245,14 @@
|
|||||||
"tryAgainText": "Try again",
|
"tryAgainText": "Try again",
|
||||||
"investmentConfirmationText": "Investment confirmation",
|
"investmentConfirmationText": "Investment confirmation",
|
||||||
"enterAmountText": "Enter Amount",
|
"enterAmountText": "Enter Amount",
|
||||||
"pleaseEnterAmountText": "Please Enter Amount"
|
"pleaseEnterAmountText": "Please Enter Amount",
|
||||||
|
"authenticationFailedText" : "Authentication failed",
|
||||||
|
"pleaseAuthenticateToAccessTheApp" : "Please authenticate to access the app",
|
||||||
|
"masterPinAddedSucessfullyText" : "Master pin added sucessfully",
|
||||||
|
"passwordChangedSucessfully" : "Password changed successfully!",
|
||||||
|
"passwordResetSucessful" : "Password reset successful!",
|
||||||
|
"otpSendSuccessfulText" : "OTP send successful !",
|
||||||
|
"successfulText" : "successful !",
|
||||||
|
"portfolioBottomText" : "Portfolio"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,5 +3,6 @@ class Globalconst {
|
|||||||
static String name = "";
|
static String name = "";
|
||||||
static String phonenumber = "";
|
static String phonenumber = "";
|
||||||
static String isdcode = "";
|
static String isdcode = "";
|
||||||
static String createdpin="";
|
static String createdpin = "";
|
||||||
|
static String firstName = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// router.dart
|
// router.dart
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:tanami_app/core/routes/route_name.dart';
|
import 'package:tanami_app/core/routes/route_name.dart';
|
||||||
import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart';
|
import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart';
|
||||||
@@ -33,8 +32,6 @@ import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.da
|
|||||||
import 'package:tanami_app/shared/components/no_internet.dart';
|
import 'package:tanami_app/shared/components/no_internet.dart';
|
||||||
|
|
||||||
import '../../features/MainScreens/main_screen.dart';
|
import '../../features/MainScreens/main_screen.dart';
|
||||||
import '../../features/countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
|
||||||
import '../../features/countrySelection/bloc/GetCountry/get_country_event.dart';
|
|
||||||
import '../../features/forgotPassword/presentation/pages/restore_password_phone_verification_screen.dart';
|
import '../../features/forgotPassword/presentation/pages/restore_password_phone_verification_screen.dart';
|
||||||
import '../../features/login/presentation/pages/login_screen.dart';
|
import '../../features/login/presentation/pages/login_screen.dart';
|
||||||
import '../../features/register/presentation/pages/register_user_details_screen.dart';
|
import '../../features/register/presentation/pages/register_user_details_screen.dart';
|
||||||
@@ -54,7 +51,7 @@ final goRouter = GoRouter(
|
|||||||
name: "splash",
|
name: "splash",
|
||||||
path: RouteName.splashScreen,
|
path: RouteName.splashScreen,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
context.read<GetCountryBlock>().add(GetCountry());
|
// context.read<GetCountryBlock>().add(GetCountry());
|
||||||
return const SplashScreen();
|
return const SplashScreen();
|
||||||
},
|
},
|
||||||
routes: [
|
routes: [
|
||||||
|
|||||||
@@ -27,6 +27,19 @@ class AppText {
|
|||||||
static const String enterPhoneNo = "enterPhoneNo";
|
static const String enterPhoneNo = "enterPhoneNo";
|
||||||
static const String invalidPassword = "invalidPassword";
|
static const String invalidPassword = "invalidPassword";
|
||||||
static const String forgotPassword = "forgotPassword";
|
static const String forgotPassword = "forgotPassword";
|
||||||
|
static const String passwordLength =
|
||||||
|
"Password must be between 8 and 20 characters long.";
|
||||||
|
static const String passwordLowerCase =
|
||||||
|
"Password must contain at least one lower-case letter.";
|
||||||
|
static const String passwordUpperCase =
|
||||||
|
"Password must contain at least one upper-case letter.";
|
||||||
|
static const String passwordDigit =
|
||||||
|
"Password must contain at least one digit.";
|
||||||
|
static const String passwordSpecialCharacter =
|
||||||
|
"Password must contain at least one special character (!@#\$%&*()-+=^).";
|
||||||
|
static const String authenticationFailedText = "authenticationFailedText";
|
||||||
|
static const String pleaseAuthenticateToAccessTheApp =
|
||||||
|
"pleaseAuthenticateToAccessTheApp";
|
||||||
|
|
||||||
//Register
|
//Register
|
||||||
static const String getStartedToday = "getStartedToday";
|
static const String getStartedToday = "getStartedToday";
|
||||||
@@ -63,6 +76,7 @@ class AppText {
|
|||||||
static const String termsAndCondition = "termsAndCondition";
|
static const String termsAndCondition = "termsAndCondition";
|
||||||
static const String andThe = "andThe";
|
static const String andThe = "andThe";
|
||||||
static const String privacyPolicy = "privacyPolicy";
|
static const String privacyPolicy = "privacyPolicy";
|
||||||
|
static const String successfulText = "successfulText";
|
||||||
|
|
||||||
//Country Name
|
//Country Name
|
||||||
static const String bahrainCountryText = "Bahrain";
|
static const String bahrainCountryText = "Bahrain";
|
||||||
@@ -81,6 +95,7 @@ class AppText {
|
|||||||
static const String totalreturn = "totalreturn";
|
static const String totalreturn = "totalreturn";
|
||||||
static const String disttodate = "disttodate";
|
static const String disttodate = "disttodate";
|
||||||
static const String includeddocs = "includeddocs";
|
static const String includeddocs = "includeddocs";
|
||||||
|
static const String portfolioBottomText = "portfolioBottomText";
|
||||||
|
|
||||||
//Academy
|
//Academy
|
||||||
static const String videosTitle = "videosTitle";
|
static const String videosTitle = "videosTitle";
|
||||||
@@ -108,6 +123,7 @@ class AppText {
|
|||||||
static const String resendSms = "resendSms";
|
static const String resendSms = "resendSms";
|
||||||
static const String otpVerifiedSucessfully = "otpVerifiedSucessfully";
|
static const String otpVerifiedSucessfully = "otpVerifiedSucessfully";
|
||||||
static const String otpVerifiedFailed = "otpVerifiedFailed";
|
static const String otpVerifiedFailed = "otpVerifiedFailed";
|
||||||
|
static const String otpSendSuccessfulText = "otpSendSuccessfulText";
|
||||||
|
|
||||||
//Pin Code
|
//Pin Code
|
||||||
static const String pinCode = "pinCode";
|
static const String pinCode = "pinCode";
|
||||||
@@ -125,17 +141,19 @@ class AppText {
|
|||||||
"toRestorePinYouWillBeLoggedOut";
|
"toRestorePinYouWillBeLoggedOut";
|
||||||
static const String allowText = "allowText";
|
static const String allowText = "allowText";
|
||||||
static const String declineText = "declineText";
|
static const String declineText = "declineText";
|
||||||
|
static const String masterPinAddedSucessfullyText =
|
||||||
|
"masterPinAddedSucessfullyText";
|
||||||
|
|
||||||
//Forgot Password
|
//Forgot Password
|
||||||
static const String almostHere = "almostHere";
|
static const String almostHere = "almostHere";
|
||||||
static const String completeAcc = "completeAcc";
|
static const String completeAcc = "completeAcc";
|
||||||
|
|
||||||
//Forgot Password
|
|
||||||
static const String restorePasswordText = "restorePasswordText";
|
static const String restorePasswordText = "restorePasswordText";
|
||||||
static const String toRestorePasswordPleaseEnterPhoneNumber =
|
static const String toRestorePasswordPleaseEnterPhoneNumber =
|
||||||
"toRestorePasswordPleaseEnterPhoneNumber";
|
"toRestorePasswordPleaseEnterPhoneNumber";
|
||||||
static const String createNewPasswordText = "createNewPasswordText";
|
static const String createNewPasswordText = "createNewPasswordText";
|
||||||
static const String submitText = "submitText";
|
static const String submitText = "submitText";
|
||||||
|
static const String passwordChangedSucessfully = "passwordChangedSucessfully";
|
||||||
|
static const String passwordResetSucessful = "passwordResetSucessful";
|
||||||
|
|
||||||
//Wallet
|
//Wallet
|
||||||
static const String walletTitle = "walletTitle";
|
static const String walletTitle = "walletTitle";
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
import 'package:tanami_app/core/styles/app_images.dart';
|
import 'package:tanami_app/core/styles/app_images.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
|
||||||
|
|
||||||
List<String> title = [
|
|
||||||
AppText.step1,
|
|
||||||
AppText.step2,
|
|
||||||
AppText.step3,
|
|
||||||
];
|
|
||||||
|
|
||||||
List<String> description = [
|
|
||||||
AppText.enterYourCountryOfResidence,
|
|
||||||
AppText.enterNameEmailPassword,
|
|
||||||
AppText.enableBiometricAuthentication,
|
|
||||||
];
|
|
||||||
|
|
||||||
List<String> stepImage = [
|
List<String> stepImage = [
|
||||||
AppImages.step1Image,
|
AppImages.step1Image,
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
class PhoneNumberHintGenerator {
|
||||||
|
String formatPhoneNumber(String code, int length) {
|
||||||
|
switch (code) {
|
||||||
|
case "+973":
|
||||||
|
return "000 000 00";
|
||||||
|
case "+965":
|
||||||
|
return "0000 0000";
|
||||||
|
case "+968":
|
||||||
|
return "000 00 000";
|
||||||
|
case "+974":
|
||||||
|
return "000 000 00";
|
||||||
|
case "+966":
|
||||||
|
return "000 000 000";
|
||||||
|
case "+971":
|
||||||
|
return "00 000 0000";
|
||||||
|
default:
|
||||||
|
return List.generate(length, (index) => '0').join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of country codes to phone number lengths
|
||||||
|
final Map<String, int> countryPhoneLengths = {
|
||||||
|
"+973": 8, // Bahrain
|
||||||
|
"+965": 8, // Kuwait
|
||||||
|
"+968": 8, // Oman
|
||||||
|
"+974": 8, // Qatar
|
||||||
|
"+966": 9, // Saudi Arabia
|
||||||
|
"+971": 9, // United Arab Emirates
|
||||||
|
"+91": 10,
|
||||||
|
};
|
||||||
|
}
|
||||||
12
lib/features/biometric/domain/repository/biometric_api.dart
Normal file
12
lib/features/biometric/domain/repository/biometric_api.dart
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
|
import '../../../../shared/api/api_endpoints.dart';
|
||||||
|
import '../../../../shared/api/network_api_services.dart';
|
||||||
|
|
||||||
|
class BiometricAPIServices {
|
||||||
|
BiometricAPIServices();
|
||||||
|
Future<ResponseData> biometricLoginApi(Map<String, dynamic> data) async {
|
||||||
|
String url = ApiEndpoints.biometricLoginapi;
|
||||||
|
final response = await NetworkApiService().post(url, data);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,14 +2,19 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
import 'package:local_auth/local_auth.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
|
import 'package:tanami_app/features/biometric/domain/repository/biometric_api.dart';
|
||||||
|
|
||||||
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
import 'biometric_event.dart';
|
import 'biometric_event.dart';
|
||||||
import 'biometric_state.dart';
|
import 'biometric_state.dart';
|
||||||
|
|
||||||
class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
|
class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
|
||||||
final LocalAuthentication localAuthentication;
|
final LocalAuthentication localAuthentication;
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
|
|
||||||
BiometricBloc(this.localAuthentication) : super(BiometricInitial()) {
|
BiometricBloc(this.localAuthentication, this.secureStorageService)
|
||||||
|
: super(BiometricInitial()) {
|
||||||
on<CheckBiometricEvent>(_onCheckBiometric);
|
on<CheckBiometricEvent>(_onCheckBiometric);
|
||||||
on<AuthenticateBiometricEvent>(_onAuthenticateBiometric);
|
on<AuthenticateBiometricEvent>(_onAuthenticateBiometric);
|
||||||
}
|
}
|
||||||
@@ -46,7 +51,21 @@ class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
emit(BiometricAuthenticated());
|
Map<String, dynamic> biometricLoginData = {
|
||||||
|
"token": await secureStorageService.read("temp_token"),
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseData response =
|
||||||
|
await BiometricAPIServices().biometricLoginApi(biometricLoginData);
|
||||||
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
|
await secureStorageService.write(
|
||||||
|
'accesstoken', response.data["data"]["accessToken"]);
|
||||||
|
await secureStorageService.write(
|
||||||
|
'refreshtoken', response.data["data"]["refreshToken"]);
|
||||||
|
emit(BiometricAuthenticated());
|
||||||
|
} else {
|
||||||
|
emit(BiometricFailed('Authentication failed'));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emit(BiometricFailed('Authentication failed'));
|
emit(BiometricFailed('Authentication failed'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
|
|
||||||
import '../../../../core/routes/route_name.dart';
|
import '../../../../core/routes/route_name.dart';
|
||||||
import '../../../../core/routes/routes.dart';
|
import '../../../../core/routes/routes.dart';
|
||||||
@@ -18,6 +19,7 @@ class BiometricLayout extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
String biometricImage = "";
|
String biometricImage = "";
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
biometricImage = AppImages.biometricFace;
|
biometricImage = AppImages.biometricFace;
|
||||||
@@ -27,15 +29,14 @@ class BiometricLayout extends StatelessWidget {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
body: BlocConsumer<BiometricBloc, BiometricState>(
|
body: BlocConsumer<BiometricBloc, BiometricState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) async {
|
||||||
if (state is BiometricChecked && state.canAuthenticate) {
|
if (state is BiometricChecked && state.canAuthenticate) {
|
||||||
context.read<BiometricBloc>().add(AuthenticateBiometricEvent());
|
context.read<BiometricBloc>().add(AuthenticateBiometricEvent());
|
||||||
} else if (state is BiometricFailed) {
|
} else if (state is BiometricFailed) {
|
||||||
deviceLockedDialog(context);
|
deviceLockedDialog(context);
|
||||||
} else if (state is BiometricAuthenticated) {
|
} else if (state is BiometricAuthenticated) {
|
||||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
await secureStorageService.write('isLoginedIn', "true");
|
||||||
"fromScreen": "LoginedInUser",
|
goRouter.goNamed(RouteName.mainScreen);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ class RestorePasswordBottomSection extends StatelessWidget {
|
|||||||
if (state is ChangePasswordLoading) {
|
if (state is ChangePasswordLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is ChangePasswordSuccess) {
|
} else if (state is ChangePasswordSuccess) {
|
||||||
successToastMessage(context, "Password changed successful !");
|
successToastMessage(context,
|
||||||
|
localizations.translate(AppText.passwordChangedSucessfully));
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
} else if (state is ChangePasswordFailure) {
|
} else if (state is ChangePasswordFailure) {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class GetCountryBlock extends Bloc<GetCountryEvent, GetCountryState> {
|
|||||||
GetCountryModel countryModel = GetCountryModel.fromJson(response.data);
|
GetCountryModel countryModel = GetCountryModel.fromJson(response.data);
|
||||||
emit(CountryLoaded(countryModel));
|
emit(CountryLoaded(countryModel));
|
||||||
}
|
}
|
||||||
print("//");
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(CountryError("Oops Something went wrong"));
|
emit(CountryError("Oops Something went wrong"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ class ChooseCountryLayout extends StatelessWidget {
|
|||||||
child: ButtonWidget().elevatedBtn(
|
child: ButtonWidget().elevatedBtn(
|
||||||
txtClr: AppColor.plainWhite,
|
txtClr: AppColor.plainWhite,
|
||||||
function: () {
|
function: () {
|
||||||
print("//");
|
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
},
|
},
|
||||||
text: localizations.translate(AppText.confirmSelectionText),
|
text: localizations.translate(AppText.confirmSelectionText),
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../../../core/styles/app_color.dart';
|
import '../../../../core/styles/app_color.dart';
|
||||||
|
import '../../bloc/GetCountry/get_country_bloc.dart';
|
||||||
|
import '../../bloc/GetCountry/get_country_event.dart';
|
||||||
import 'choose_country_layout.dart';
|
import 'choose_country_layout.dart';
|
||||||
|
|
||||||
class ChooseCountryScreen extends StatelessWidget {
|
class ChooseCountryScreen extends StatelessWidget {
|
||||||
@@ -8,6 +11,7 @@ class ChooseCountryScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
context.read<GetCountryBlock>().add(GetCountry());
|
||||||
return const Scaffold(
|
return const Scaffold(
|
||||||
backgroundColor: AppColor.plainWhite,
|
backgroundColor: AppColor.plainWhite,
|
||||||
resizeToAvoidBottomInset: true,
|
resizeToAvoidBottomInset: true,
|
||||||
|
|||||||
@@ -38,18 +38,20 @@ class CountrySelectionList extends StatelessWidget {
|
|||||||
context.read<GetCountryBlock>().add(GetCountry());
|
context.read<GetCountryBlock>().add(GetCountry());
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const SnackBar(content: Text(" not fetch"));
|
const SnackBar(content: Text("not fetch"));
|
||||||
}
|
}
|
||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
print(state);
|
|
||||||
if (state is CountryLoading) {
|
if (state is CountryLoading) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: AppColor.primaryColor,
|
||||||
|
));
|
||||||
} else if (state is CountryLoaded) {
|
} else if (state is CountryLoaded) {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: state.countryModel.data?.length ?? 0,
|
itemCount: state.countryModel.data?.length ?? 0,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
var country = state.countryModel.data![index];
|
var country = state.countryModel.data![index];
|
||||||
print("${ApiEndpoints.base}${country.flagIcon}");
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Row(
|
title: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
|
import '../../../../shared/api/api_endpoints.dart';
|
||||||
|
import '../../../../shared/api/network_api_services.dart';
|
||||||
|
|
||||||
|
class ForgotPasswordApi {
|
||||||
|
ForgotPasswordApi();
|
||||||
|
Future<ResponseData> forgotPasswordApi(Map<String, dynamic> data) async {
|
||||||
|
String url = ApiEndpoints.forgotPasswordApi;
|
||||||
|
final response = await NetworkApiService().post(url, data);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseData> resetPasswordApi(Map<String, dynamic> data) async {
|
||||||
|
String url = ApiEndpoints.resetPasswordApi;
|
||||||
|
final response = await NetworkApiService().post(url, data);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tanami_app/Globalconst.dart';
|
||||||
|
|
||||||
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
|
import '../../domain/repository/forgot_password_api.dart';
|
||||||
import 'restore_password_event.dart';
|
import 'restore_password_event.dart';
|
||||||
import 'restore_password_state.dart';
|
import 'restore_password_state.dart';
|
||||||
|
|
||||||
@@ -24,15 +29,18 @@ class RestorePasswordBloc
|
|||||||
}
|
}
|
||||||
emit(RestorePasswordLoading());
|
emit(RestorePasswordLoading());
|
||||||
try {
|
try {
|
||||||
// Simulate API call
|
log(Globalconst.token);
|
||||||
await Future.delayed(const Duration(seconds: 2));
|
Map<String, dynamic> dataForm = {
|
||||||
// Replace the next line with actual API call
|
"token": Globalconst.token,
|
||||||
final isSuccess = await _mockLoginApi(event.password);
|
"passwordHash": event.password
|
||||||
if (isSuccess) {
|
};
|
||||||
|
ResponseData response =
|
||||||
|
await ForgotPasswordApi().resetPasswordApi(dataForm);
|
||||||
|
|
||||||
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
emit(RestorePasswordSuccess());
|
emit(RestorePasswordSuccess());
|
||||||
} else {
|
} else {
|
||||||
emit(const RestorePasswordFailure(
|
emit(RestorePasswordFailure(response.message));
|
||||||
"Failed. Please check your credentials."));
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(RestorePasswordFailure(e.toString()));
|
emit(RestorePasswordFailure(e.toString()));
|
||||||
@@ -59,13 +67,6 @@ class RestorePasswordBloc
|
|||||||
repeatPasswordTextField.clear();
|
repeatPasswordTextField.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock API function, replace with actual API call
|
|
||||||
Future<bool> _mockLoginApi(
|
|
||||||
String phoneNumber,
|
|
||||||
) async {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
passwordTextField.dispose();
|
passwordTextField.dispose();
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tanami_app/Globalconst.dart';
|
||||||
|
|
||||||
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
|
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||||
|
import '../../domain/repository/forgot_password_api.dart';
|
||||||
import 'restore_password_phone_verification_event.dart';
|
import 'restore_password_phone_verification_event.dart';
|
||||||
import 'restore_password_phone_verification_state.dart';
|
import 'restore_password_phone_verification_state.dart';
|
||||||
|
|
||||||
class RestorePasswordPhoneVerificationBloc extends Bloc<
|
class RestorePasswordPhoneVerificationBloc extends Bloc<
|
||||||
RestorePasswordPhoneVerificationEvent,
|
RestorePasswordPhoneVerificationEvent,
|
||||||
RestorePasswordPhoneVerificationState> {
|
RestorePasswordPhoneVerificationState> {
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
|
String isdcode = "";
|
||||||
|
|
||||||
|
String countryId = "";
|
||||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController phoneNumberTextField = TextEditingController();
|
final TextEditingController phoneNumberTextField = TextEditingController();
|
||||||
final TextEditingController countrySelectionTextField =
|
final TextEditingController countrySelectionTextField =
|
||||||
@@ -16,26 +24,28 @@ class RestorePasswordPhoneVerificationBloc extends Bloc<
|
|||||||
return formKey;
|
return formKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
RestorePasswordPhoneVerificationBloc()
|
RestorePasswordPhoneVerificationBloc({required this.secureStorageService})
|
||||||
: super(RestorePasswordPhoneVerificationInitial()) {
|
: super(RestorePasswordPhoneVerificationInitial()) {
|
||||||
phoneNumberTextField.addListener(_onFormFieldChanged);
|
phoneNumberTextField.addListener(_onFormFieldChanged);
|
||||||
countrySelectionTextField.addListener(_onFormFieldChanged);
|
countrySelectionTextField.addListener(_onFormFieldChanged);
|
||||||
on<RestorePasswordPhoneVerificationFormChanged>(_onLoginFormChanged);
|
on<RestorePasswordPhoneVerificationFormChanged>(_onLoginFormChanged);
|
||||||
on<RestorePasswordPhoneVerificationSubmitted>((event, emit) async {
|
on<RestorePasswordPhoneVerificationSubmitted>((event, emit) async {
|
||||||
if (!formKey.currentState!.validate()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emit(RestorePasswordPhoneVerificationLoading());
|
emit(RestorePasswordPhoneVerificationLoading());
|
||||||
try {
|
try {
|
||||||
// Simulate API call
|
Map<String, dynamic> dataForm = {
|
||||||
await Future.delayed(const Duration(seconds: 2));
|
"countryId": event.id,
|
||||||
// Replace the next line with actual API call
|
"phoneNumber": event.phoneNumber
|
||||||
const isSuccess = true;
|
};
|
||||||
if (isSuccess) {
|
ResponseData response =
|
||||||
|
await ForgotPasswordApi().forgotPasswordApi(dataForm);
|
||||||
|
|
||||||
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
|
var data = response.data["data"];
|
||||||
|
await secureStorageService.write('temp_token', data["token"]);
|
||||||
|
Globalconst.token = data["token"];
|
||||||
emit(RestorePasswordPhoneVerificationSuccess());
|
emit(RestorePasswordPhoneVerificationSuccess());
|
||||||
} else {
|
} else {
|
||||||
emit(const RestorePasswordPhoneVerificationFailure(
|
emit(RestorePasswordPhoneVerificationFailure(response.message));
|
||||||
"Failed. Please check your credentials."));
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(RestorePasswordPhoneVerificationFailure(e.toString()));
|
emit(RestorePasswordPhoneVerificationFailure(e.toString()));
|
||||||
@@ -62,13 +72,6 @@ class RestorePasswordPhoneVerificationBloc extends Bloc<
|
|||||||
countrySelectionTextField.clear();
|
countrySelectionTextField.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock API function, replace with actual API call
|
|
||||||
Future<bool> _mockLoginApi(
|
|
||||||
String phoneNumber,
|
|
||||||
) async {
|
|
||||||
return phoneNumber == "1234567891";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
phoneNumberTextField.dispose();
|
phoneNumberTextField.dispose();
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ class RestorePasswordPhoneVerificationSubmitted
|
|||||||
extends RestorePasswordPhoneVerificationEvent {
|
extends RestorePasswordPhoneVerificationEvent {
|
||||||
final String phoneNumber;
|
final String phoneNumber;
|
||||||
final String countryResidence;
|
final String countryResidence;
|
||||||
|
final String id;
|
||||||
|
|
||||||
const RestorePasswordPhoneVerificationSubmitted(
|
const RestorePasswordPhoneVerificationSubmitted(
|
||||||
this.phoneNumber,
|
this.phoneNumber,
|
||||||
this.countryResidence,
|
this.countryResidence,
|
||||||
|
this.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/features/forgotPassword/presentation/pages/restore_password_phone_verification_layout.dart';
|
import 'package:tanami_app/features/forgotPassword/presentation/pages/restore_password_phone_verification_layout.dart';
|
||||||
|
|
||||||
import '../../../../core/styles/app_color.dart';
|
import '../../../../core/styles/app_color.dart';
|
||||||
|
import '../../../countrySelection/bloc/choose_country_bloc.dart';
|
||||||
import '../bloc/restore_password_phone_verification_bloc.dart';
|
import '../bloc/restore_password_phone_verification_bloc.dart';
|
||||||
|
|
||||||
class RestorePasswordPhoneVerificationScreen extends StatelessWidget {
|
class RestorePasswordPhoneVerificationScreen extends StatelessWidget {
|
||||||
@@ -10,18 +12,27 @@ class RestorePasswordPhoneVerificationScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
backgroundColor: AppColor.plainWhite,
|
final radioBloc = context.read<RadioBloc>();
|
||||||
resizeToAvoidBottomInset: true,
|
return WillPopScope(
|
||||||
body: MultiBlocProvider(
|
onWillPop: () async {
|
||||||
// Define the providers for the OnboardingBloc and other blocs
|
radioBloc.resetSelection();
|
||||||
providers: [
|
return true;
|
||||||
BlocProvider(
|
},
|
||||||
// Create an instance of the OnboardingBloc
|
child: Scaffold(
|
||||||
create: (context) => RestorePasswordPhoneVerificationBloc(),
|
backgroundColor: AppColor.plainWhite,
|
||||||
),
|
resizeToAvoidBottomInset: true,
|
||||||
],
|
body: MultiBlocProvider(
|
||||||
child: const RestorePasswordPhoneVerificationLayout(),
|
// Define the providers for the OnboardingBloc and other blocs
|
||||||
|
providers: [
|
||||||
|
BlocProvider(
|
||||||
|
// Create an instance of the OnboardingBloc
|
||||||
|
create: (context) => RestorePasswordPhoneVerificationBloc(
|
||||||
|
secureStorageService: secureStorageService),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: const RestorePasswordPhoneVerificationLayout(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ class RestorePasswordBottomSection extends StatelessWidget {
|
|||||||
if (state is RestorePasswordLoading) {
|
if (state is RestorePasswordLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is RestorePasswordSuccess) {
|
} else if (state is RestorePasswordSuccess) {
|
||||||
successToastMessage(context, "Password resetted successful !");
|
successToastMessage(context,
|
||||||
|
localizations.translate(AppText.passwordResetSucessful));
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
radioBloc.resetSelection();
|
radioBloc.resetSelection();
|
||||||
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class RestorePasswordForm extends StatelessWidget {
|
|||||||
create: (_) => PasswordVisibilityBloc(),
|
create: (_) => PasswordVisibilityBloc(),
|
||||||
child: FormLabelTextField(
|
child: FormLabelTextField(
|
||||||
hintText: localizations.translate(AppText.enterPassword),
|
hintText: localizations.translate(AppText.enterPassword),
|
||||||
title: "New Password",
|
title: localizations.translate(AppText.newPasswordText),
|
||||||
type: AppText.password.toLowerCase(),
|
type: AppText.password.toLowerCase(),
|
||||||
textEditingController: restorePasswordBloc.passwordTextField,
|
textEditingController: restorePasswordBloc.passwordTextField,
|
||||||
),
|
),
|
||||||
@@ -49,6 +49,8 @@ class RestorePasswordForm extends StatelessWidget {
|
|||||||
type: AppText.password.toLowerCase(),
|
type: AppText.password.toLowerCase(),
|
||||||
textEditingController:
|
textEditingController:
|
||||||
restorePasswordBloc.repeatPasswordTextField,
|
restorePasswordBloc.repeatPasswordTextField,
|
||||||
|
originalPasswordController:
|
||||||
|
restorePasswordBloc.passwordTextField,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
final radioBloc = context.read<RadioBloc>();
|
final radioBloc = context.read<RadioBloc>();
|
||||||
|
final restorePasswordBloc =
|
||||||
|
context.read<RestorePasswordPhoneVerificationBloc>();
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
BlocConsumer<RestorePasswordPhoneVerificationBloc,
|
BlocConsumer<RestorePasswordPhoneVerificationBloc,
|
||||||
@@ -34,7 +36,8 @@ class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
|
|||||||
if (state is RestorePasswordPhoneVerificationLoading) {
|
if (state is RestorePasswordPhoneVerificationLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is RestorePasswordPhoneVerificationSuccess) {
|
} else if (state is RestorePasswordPhoneVerificationSuccess) {
|
||||||
successToastMessage(context, "OTP send successful !");
|
successToastMessage(context,
|
||||||
|
localizations.translate(AppText.otpSendSuccessfulText));
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
radioBloc.resetSelection();
|
radioBloc.resetSelection();
|
||||||
goRouter.pushNamed(RouteName.otpScreen,
|
goRouter.pushNamed(RouteName.otpScreen,
|
||||||
@@ -76,7 +79,8 @@ class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
|
|||||||
RestorePasswordPhoneVerificationBloc>()
|
RestorePasswordPhoneVerificationBloc>()
|
||||||
.phoneNumberTextField
|
.phoneNumberTextField
|
||||||
.text,
|
.text,
|
||||||
""),
|
"",
|
||||||
|
restorePasswordBloc.countryId),
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
},
|
},
|
||||||
@@ -91,6 +95,7 @@ class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
|
|||||||
const Gap(5),
|
const Gap(5),
|
||||||
ButtonWidget().textBtn(
|
ButtonWidget().textBtn(
|
||||||
function: () {
|
function: () {
|
||||||
|
radioBloc.resetSelection();
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
},
|
},
|
||||||
text: TextWidget().text14W700(
|
text: TextWidget().text14W700(
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
|
|
||||||
|
|
||||||
|
import '../../../../core/styles/app_color.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
import '../../../../core/utils/phone_number_hint_generator/phone_number_hint_generator.dart';
|
||||||
|
import '../../../../shared/api/api_endpoints.dart';
|
||||||
import '../../../../shared/components/form_label_textfield.dart';
|
import '../../../../shared/components/form_label_textfield.dart';
|
||||||
|
import '../../../countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
||||||
|
import '../../../countrySelection/bloc/GetCountry/get_country_state.dart';
|
||||||
import '../../../countrySelection/bloc/choose_country_bloc.dart';
|
import '../../../countrySelection/bloc/choose_country_bloc.dart';
|
||||||
import '../../../countrySelection/bloc/choose_country_state.dart';
|
import '../../../countrySelection/bloc/choose_country_state.dart';
|
||||||
import '../bloc/restore_password_phone_verification_bloc.dart';
|
import '../bloc/restore_password_phone_verification_bloc.dart';
|
||||||
@@ -15,21 +22,41 @@ class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
String flag = "";
|
||||||
|
final countrydata = context.read<GetCountryBlock>();
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
final restorePasswordBloc =
|
final restorePasswordBloc =
|
||||||
context.read<RestorePasswordPhoneVerificationBloc>();
|
context.read<RestorePasswordPhoneVerificationBloc>();
|
||||||
|
|
||||||
// Reset fields when the screen is built
|
// Reset fields when the screen is built
|
||||||
restorePasswordBloc.resetFields();
|
restorePasswordBloc.resetFields();
|
||||||
|
String hintText = '00 000 000';
|
||||||
|
|
||||||
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
||||||
int selectedCountry = -1;
|
int selectedCountry = -1;
|
||||||
if (state is RadioSelectionChanged) {
|
if (state is RadioSelectionChanged) {
|
||||||
|
final countryState = countrydata.state;
|
||||||
selectedCountry = state.selectedIndex;
|
selectedCountry = state.selectedIndex;
|
||||||
restorePasswordBloc.countrySelectionTextField.text =
|
if (countryState is CountryLoaded) {
|
||||||
countryName[selectedCountry];
|
restorePasswordBloc.isdcode =
|
||||||
restorePasswordBloc.phoneNumberTextField.text =
|
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||||
"${isoCountryCode[selectedCountry]} ";
|
restorePasswordBloc.countrySelectionTextField.text = countryState
|
||||||
|
.countryModel.data![selectedCountry].countryName
|
||||||
|
.toString();
|
||||||
|
restorePasswordBloc.phoneNumberTextField.text = "";
|
||||||
|
if (PhoneNumberHintGenerator().countryPhoneLengths.containsKey(
|
||||||
|
restorePasswordBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength = PhoneNumberHintGenerator()
|
||||||
|
.countryPhoneLengths[restorePasswordBloc.isdcode];
|
||||||
|
hintText = PhoneNumberHintGenerator().formatPhoneNumber(
|
||||||
|
restorePasswordBloc.isdcode, expectedLength!);
|
||||||
|
}
|
||||||
|
restorePasswordBloc.countryId =
|
||||||
|
countryState.countryModel.data![selectedCountry].id!;
|
||||||
|
flag =
|
||||||
|
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
int selectedCountry = -1;
|
int selectedCountry = -1;
|
||||||
@@ -51,10 +78,41 @@ class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
|||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
prefixWidget: selectedCountry == -1
|
prefixWidget: selectedCountry == -1
|
||||||
? null
|
? null
|
||||||
: Image.asset(
|
: Padding(
|
||||||
countryFlag[selectedCountry],
|
padding: EdgeInsets.only(left: 12.w),
|
||||||
width: 20,
|
child: SizedBox(
|
||||||
height: 20,
|
height: 50.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(100)),
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
maxHeightDiskCache: 200,
|
||||||
|
maxWidthDiskCache: 200,
|
||||||
|
cacheKey: restorePasswordBloc
|
||||||
|
.countrySelectionTextField.text,
|
||||||
|
key: UniqueKey(),
|
||||||
|
imageUrl: "${ApiEndpoints.baseurl}$flag",
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
placeholder: (context, url) => SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child:
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
errorWidget: (context, url, error) =>
|
||||||
|
const Icon(Icons.error),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
hintText: localizations.translate(AppText.chooseCountry),
|
hintText: localizations.translate(AppText.chooseCountry),
|
||||||
title: localizations.translate(AppText.countryOfResidence),
|
title: localizations.translate(AppText.countryOfResidence),
|
||||||
@@ -66,12 +124,58 @@ class RestorePasswordPhoneVerificationForm extends StatelessWidget {
|
|||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
prefixWidget: selectedCountry == -1
|
prefixWidget: selectedCountry == -1
|
||||||
? null
|
? null
|
||||||
: Image.asset(
|
: Row(
|
||||||
countryFlag[selectedCountry],
|
mainAxisSize: MainAxisSize.min,
|
||||||
width: 20,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
height: 20,
|
children: [
|
||||||
|
const Gap(10),
|
||||||
|
SizedBox(
|
||||||
|
height: 50.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(100)),
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
maxHeightDiskCache: 200,
|
||||||
|
maxWidthDiskCache: 200,
|
||||||
|
key: UniqueKey(),
|
||||||
|
imageUrl: flag,
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
placeholder: (context, url) => SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child:
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
errorWidget: (context, url, error) =>
|
||||||
|
const Icon(Icons.error),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(5),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(top: 10),
|
||||||
|
height: 30.h,
|
||||||
|
width: 40.w,
|
||||||
|
child: Text(
|
||||||
|
restorePasswordBloc.isdcode,
|
||||||
|
style: GoogleFonts.dmSans(
|
||||||
|
color: AppColor.charcoalColor,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
hintText: "+0 (000) 000 00 00",
|
hintText: hintText,
|
||||||
title: localizations.translate(AppText.phoneNumber),
|
title: localizations.translate(AppText.phoneNumber),
|
||||||
type: "phone number",
|
type: "phone number",
|
||||||
textEditingController:
|
textEditingController:
|
||||||
|
|||||||
@@ -1,37 +1,40 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||||
|
import 'package:tanami_app/Globalconst.dart';
|
||||||
import 'package:tanami_app/features/login/Repository/LoginAPI.dart';
|
import 'package:tanami_app/features/login/Repository/LoginAPI.dart';
|
||||||
|
|
||||||
|
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||||
import 'login_event.dart';
|
import 'login_event.dart';
|
||||||
import 'login_state.dart';
|
import 'login_state.dart';
|
||||||
|
|
||||||
class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController countrySelectionTextField =
|
final TextEditingController countrySelectionTextField =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
final TextEditingController phoneNumberTextField = TextEditingController();
|
final TextEditingController phoneNumberTextField = TextEditingController();
|
||||||
final TextEditingController passwordTextField = TextEditingController();
|
final TextEditingController passwordTextField = TextEditingController();
|
||||||
String countryId = "";
|
String countryId = "";
|
||||||
|
String isdcode = "";
|
||||||
GlobalKey<FormState> getFormKey() {
|
GlobalKey<FormState> getFormKey() {
|
||||||
return formKey;
|
return formKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoginBloc() : super(LoginInitial()) {
|
LoginBloc({required this.secureStorageService}) : super(LoginInitial()) {
|
||||||
phoneNumberTextField.addListener(_onFormFieldChanged);
|
phoneNumberTextField.addListener(_onFormFieldChanged);
|
||||||
passwordTextField.addListener(_onFormFieldChanged);
|
passwordTextField.addListener(_onFormFieldChanged);
|
||||||
countrySelectionTextField.addListener(_onFormFieldChanged);
|
countrySelectionTextField.addListener(_onFormFieldChanged);
|
||||||
on<LoginFormChanged>(_onLoginFormChanged);
|
on<LoginFormChanged>(_onLoginFormChanged);
|
||||||
on<LoginSubmitted>((event, emit) async {
|
on<LoginSubmitted>((event, emit) async {
|
||||||
if (!formKey.currentState!.validate()) {
|
if (!formKey.currentState!.validate()) {
|
||||||
|
emit(LoginLoading());
|
||||||
emit(
|
emit(
|
||||||
const LoginFailure("Login failed. Please check your credentials."));
|
const LoginFailure("Login failed. Please check your credentials."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit(LoginLoading());
|
emit(LoginLoading());
|
||||||
try {
|
try {
|
||||||
// Simulate API call
|
|
||||||
//await Future.delayed(const Duration(seconds: 2));
|
|
||||||
Map<String, dynamic> logindata = {
|
Map<String, dynamic> logindata = {
|
||||||
"countryId": event.countryId,
|
"countryId": event.countryId,
|
||||||
"phoneNumber": event.phoneNumber,
|
"phoneNumber": event.phoneNumber,
|
||||||
@@ -39,20 +42,25 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
|||||||
};
|
};
|
||||||
ResponseData response = await LoginAPI().LoginRequest(logindata);
|
ResponseData response = await LoginAPI().LoginRequest(logindata);
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
|
await secureStorageService.write(
|
||||||
|
'first_name', response.data['data']['firstName']);
|
||||||
|
Globalconst.firstName = response.data['data']['firstName'];
|
||||||
|
await secureStorageService.write(
|
||||||
|
'temp_token', response.data['data']['token']);
|
||||||
|
|
||||||
emit(LoginSuccess());
|
emit(LoginSuccess());
|
||||||
|
} else if (response.status == ResponseStatus.PRIVATE) {
|
||||||
|
if (response.message.toString() == "Master Pin is not created") {
|
||||||
|
await secureStorageService.write(
|
||||||
|
'temp_token', response.data['data']['user']);
|
||||||
|
emit(LoginMasterPinPending());
|
||||||
|
} else {
|
||||||
|
emit(LoginFailure(response.message.toString()));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emit(const LoginFailure(
|
emit(const LoginFailure(
|
||||||
"Login failed. Please check your credentials."));
|
"Login failed. Please check your credentials."));
|
||||||
}
|
}
|
||||||
// Replace the next line with actual API call
|
|
||||||
/* final isSuccess = await _mockLoginApi(
|
|
||||||
event.phoneNumber, event.password, event.countryResidence);
|
|
||||||
if (isSuccess) {
|
|
||||||
emit(LoginSuccess());
|
|
||||||
} else {
|
|
||||||
emit(const LoginFailure(
|
|
||||||
"Login failed. Please check your credentials."));
|
|
||||||
} */
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(LoginFailure(e.toString()));
|
emit(LoginFailure(e.toString()));
|
||||||
}
|
}
|
||||||
@@ -80,15 +88,6 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
|
|||||||
countrySelectionTextField.clear();
|
countrySelectionTextField.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock API function, replace with actual API call
|
|
||||||
Future<bool> _mockLoginApi(
|
|
||||||
String phoneNumber,
|
|
||||||
String password,
|
|
||||||
String countryResidence,
|
|
||||||
) async {
|
|
||||||
return password == "123456";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
phoneNumberTextField.dispose();
|
phoneNumberTextField.dispose();
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class LoginLoading extends LoginState {}
|
|||||||
|
|
||||||
class LoginSuccess extends LoginState {}
|
class LoginSuccess extends LoginState {}
|
||||||
|
|
||||||
|
class LoginMasterPinPending extends LoginState {}
|
||||||
|
|
||||||
class LoginFailure extends LoginState {
|
class LoginFailure extends LoginState {
|
||||||
final String error;
|
final String error;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
|
|
||||||
import '../../../../core/styles/app_color.dart';
|
import '../../../../core/styles/app_color.dart';
|
||||||
import '../../../../shared/components/exit_app_dialog.dart';
|
import '../../../../shared/components/exit_app_dialog.dart';
|
||||||
@@ -13,6 +14,7 @@ class LoginScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
final radioBloc = context.read<RadioBloc>();
|
final radioBloc = context.read<RadioBloc>();
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
@@ -34,7 +36,8 @@ class LoginScreen extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
// Create an instance of the OnboardingBloc
|
// Create an instance of the OnboardingBloc
|
||||||
create: (context) => LoginBloc(),
|
create: (context) =>
|
||||||
|
LoginBloc(secureStorageService: secureStorageService),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: LoginLayout(
|
child: LoginLayout(
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/shared/components/loader.dart';
|
|
||||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
|
||||||
|
|
||||||
import '../../../../core/routes/route_name.dart';
|
import '../../../../core/routes/route_name.dart';
|
||||||
import '../../../../core/routes/routes.dart';
|
import '../../../../core/routes/routes.dart';
|
||||||
@@ -12,7 +10,9 @@ import '../../../../core/styles/app_color.dart';
|
|||||||
import '../../../../core/styles/app_text.dart';
|
import '../../../../core/styles/app_text.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
import '../../../../shared/components/button_widget.dart';
|
import '../../../../shared/components/button_widget.dart';
|
||||||
|
import '../../../../shared/components/loader.dart';
|
||||||
import '../../../../shared/components/text_widget.dart';
|
import '../../../../shared/components/text_widget.dart';
|
||||||
|
import '../../../../shared/components/toast_message.dart';
|
||||||
import '../../../countrySelection/bloc/choose_country_bloc.dart';
|
import '../../../countrySelection/bloc/choose_country_bloc.dart';
|
||||||
import '../bloc/login_bloc.dart';
|
import '../bloc/login_bloc.dart';
|
||||||
import '../bloc/login_event.dart';
|
import '../bloc/login_event.dart';
|
||||||
@@ -38,6 +38,9 @@ class BottomSection extends StatelessWidget {
|
|||||||
alignment: Alignment.topRight,
|
alignment: Alignment.topRight,
|
||||||
child: ButtonWidget().textBtn(
|
child: ButtonWidget().textBtn(
|
||||||
function: () {
|
function: () {
|
||||||
|
// Reset fields when the screen is built
|
||||||
|
loginbloc.resetFields();
|
||||||
|
radioBloc.resetSelection();
|
||||||
goRouter
|
goRouter
|
||||||
.pushNamed(RouteName.forgotPasswordPhoneVerificationScreen);
|
.pushNamed(RouteName.forgotPasswordPhoneVerificationScreen);
|
||||||
},
|
},
|
||||||
@@ -52,7 +55,7 @@ class BottomSection extends StatelessWidget {
|
|||||||
if (state is LoginLoading) {
|
if (state is LoginLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is LoginSuccess) {
|
} else if (state is LoginSuccess) {
|
||||||
goRouter.goNamed('mainScreen');
|
// goRouter.goNamed('mainScreen');
|
||||||
successToastMessage(context, "login successful !");
|
successToastMessage(context, "login successful !");
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
radioBloc.resetSelection();
|
radioBloc.resetSelection();
|
||||||
@@ -61,6 +64,11 @@ class BottomSection extends StatelessWidget {
|
|||||||
"fromScreen":
|
"fromScreen":
|
||||||
fromScreen == "forgot-pin" ? "forgot-pin" : "login",
|
fromScreen == "forgot-pin" ? "forgot-pin" : "login",
|
||||||
}); //Push Or GO Need to Check
|
}); //Push Or GO Need to Check
|
||||||
|
} else if (state is LoginMasterPinPending) {
|
||||||
|
goRouter.pop();
|
||||||
|
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||||
|
"fromScreen": "login-master-pending",
|
||||||
|
});
|
||||||
} else if (state is LoginFailure) {
|
} else if (state is LoginFailure) {
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
errorToastMessage(
|
errorToastMessage(
|
||||||
@@ -87,11 +95,15 @@ class BottomSection extends StatelessWidget {
|
|||||||
? AppColor.plainWhite
|
? AppColor.plainWhite
|
||||||
: AppColor.inactiveBtnTxtColor,
|
: AppColor.inactiveBtnTxtColor,
|
||||||
function: () {
|
function: () {
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
isButtonEnabled
|
isButtonEnabled
|
||||||
? loginbloc.add(
|
? loginbloc.add(
|
||||||
LoginSubmitted(loginbloc.phoneNumberTextField.text,
|
LoginSubmitted(
|
||||||
loginbloc.passwordTextField.text, "",loginbloc.countryId),
|
loginbloc.phoneNumberTextField.text,
|
||||||
)
|
loginbloc.passwordTextField.text,
|
||||||
|
"",
|
||||||
|
loginbloc.countryId),
|
||||||
|
)
|
||||||
: null;
|
: null;
|
||||||
},
|
},
|
||||||
text: localizations.translate(AppText.loginText),
|
text: localizations.translate(AppText.loginText),
|
||||||
@@ -105,6 +117,7 @@ class BottomSection extends StatelessWidget {
|
|||||||
const Gap(10),
|
const Gap(10),
|
||||||
ButtonWidget().textBorderBtn(
|
ButtonWidget().textBorderBtn(
|
||||||
function: () {
|
function: () {
|
||||||
|
loginbloc.resetFields();
|
||||||
radioBloc.resetSelection();
|
radioBloc.resetSelection();
|
||||||
fromScreen == "forgot-pin"
|
fromScreen == "forgot-pin"
|
||||||
? goRouter.pop()
|
? goRouter.pop()
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
|
import 'package:tanami_app/core/utils/phone_number_hint_generator/phone_number_hint_generator.dart';
|
||||||
|
|
||||||
import '../../../../Globalconst.dart';
|
import '../../../../Globalconst.dart';
|
||||||
|
import '../../../../core/styles/app_color.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
import '../../../../shared/api/api_endpoints.dart';
|
import '../../../../shared/api/api_endpoints.dart';
|
||||||
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
|
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
|
||||||
@@ -29,6 +33,8 @@ class LoginForm extends StatelessWidget {
|
|||||||
// Reset fields when the screen is built
|
// Reset fields when the screen is built
|
||||||
loginBloc.resetFields();
|
loginBloc.resetFields();
|
||||||
|
|
||||||
|
String hintText = '00 000 000';
|
||||||
|
|
||||||
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
||||||
int selectedCountry = -1;
|
int selectedCountry = -1;
|
||||||
if (state is RadioSelectionChanged) {
|
if (state is RadioSelectionChanged) {
|
||||||
@@ -38,9 +44,19 @@ class LoginForm extends StatelessWidget {
|
|||||||
loginBloc.countrySelectionTextField.text = countryState
|
loginBloc.countrySelectionTextField.text = countryState
|
||||||
.countryModel.data![selectedCountry].countryName
|
.countryModel.data![selectedCountry].countryName
|
||||||
.toString();
|
.toString();
|
||||||
loginBloc.phoneNumberTextField.text =
|
loginBloc.phoneNumberTextField.text = "";
|
||||||
|
loginBloc.isdcode =
|
||||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||||
loginBloc.countryId="${countryState.countryModel.data![selectedCountry].id}";
|
if (PhoneNumberHintGenerator().countryPhoneLengths.containsKey(
|
||||||
|
loginBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength = PhoneNumberHintGenerator()
|
||||||
|
.countryPhoneLengths[loginBloc.isdcode];
|
||||||
|
hintText = PhoneNumberHintGenerator()
|
||||||
|
.formatPhoneNumber(loginBloc.isdcode, expectedLength!);
|
||||||
|
}
|
||||||
|
loginBloc.countryId =
|
||||||
|
"${countryState.countryModel.data![selectedCountry].id}";
|
||||||
flag =
|
flag =
|
||||||
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
||||||
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;
|
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;
|
||||||
@@ -72,10 +88,41 @@ class LoginForm extends StatelessWidget {
|
|||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
prefixWidget: selectedCountry == -1
|
prefixWidget: selectedCountry == -1
|
||||||
? null
|
? null
|
||||||
: Image.asset(
|
: Padding(
|
||||||
countryFlag[selectedCountry],
|
padding: EdgeInsets.only(left: 12.w),
|
||||||
width: 20,
|
child: SizedBox(
|
||||||
height: 20,
|
height: 50.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(100)),
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
maxHeightDiskCache: 200,
|
||||||
|
maxWidthDiskCache: 200,
|
||||||
|
cacheKey: loginBloc
|
||||||
|
.countrySelectionTextField.text,
|
||||||
|
key: UniqueKey(),
|
||||||
|
imageUrl: "${ApiEndpoints.baseurl}$flag",
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
placeholder: (context, url) => SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child:
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
errorWidget: (context, url, error) =>
|
||||||
|
const Icon(Icons.error),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
hintText: localizations.translate(AppText.chooseCountry),
|
hintText: localizations.translate(AppText.chooseCountry),
|
||||||
title: localizations.translate(AppText.countryOfResidence),
|
title: localizations.translate(AppText.countryOfResidence),
|
||||||
@@ -86,12 +133,60 @@ class LoginForm extends StatelessWidget {
|
|||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
prefixWidget: selectedCountry == -1
|
prefixWidget: selectedCountry == -1
|
||||||
? null
|
? null
|
||||||
: Image.asset(
|
: Row(
|
||||||
countryFlag[selectedCountry],
|
mainAxisSize: MainAxisSize.min,
|
||||||
width: 20,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
height: 20,
|
children: [
|
||||||
|
const Gap(10),
|
||||||
|
SizedBox(
|
||||||
|
height: 50.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(100)),
|
||||||
|
child: CachedNetworkImage(
|
||||||
|
maxHeightDiskCache: 200,
|
||||||
|
maxWidthDiskCache: 200,
|
||||||
|
cacheKey: loginBloc
|
||||||
|
.countrySelectionTextField.text,
|
||||||
|
key: UniqueKey(),
|
||||||
|
imageUrl: flag,
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
placeholder: (context, url) => SizedBox(
|
||||||
|
height: 30.h,
|
||||||
|
width: 30.w,
|
||||||
|
child:
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
errorWidget: (context, url, error) =>
|
||||||
|
const Icon(Icons.error),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(5),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(top: 10),
|
||||||
|
height: 30.h,
|
||||||
|
width: 40.w,
|
||||||
|
child: Text(
|
||||||
|
loginBloc.isdcode,
|
||||||
|
style: GoogleFonts.dmSans(
|
||||||
|
color: AppColor.charcoalColor,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
hintText: "+0 (000) 000 00 00",
|
hintText: hintText,
|
||||||
title: localizations.translate(AppText.phoneNumber),
|
title: localizations.translate(AppText.phoneNumber),
|
||||||
type: "phone number",
|
type: "phone number",
|
||||||
textEditingController: loginBloc.phoneNumberTextField,
|
textEditingController: loginBloc.phoneNumberTextField,
|
||||||
|
|||||||
@@ -21,27 +21,8 @@ class OTPBloc extends Bloc<OTPEvent, OTPState> {
|
|||||||
} else {
|
} else {
|
||||||
emit(OTPFailed("Oops something went wrong"));
|
emit(OTPFailed("Oops something went wrong"));
|
||||||
}
|
}
|
||||||
print("//");
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(OTPError("Oops something went wrong"));
|
emit(OTPError("Oops something went wrong"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Future<void> VerifyOTPCall(
|
|
||||||
GetCountry event, Emitter<GetCountryState> emit) async {
|
|
||||||
if (event is GetCountry) {
|
|
||||||
emit(CountryLoading());
|
|
||||||
try {
|
|
||||||
ResponseData response = await GetCountryAPI().getcountryAPI();
|
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
|
||||||
GetCountryModel countryModel =
|
|
||||||
GetCountryModel.fromJson(response.data);
|
|
||||||
emit(CountryLoaded(countryModel));
|
|
||||||
}
|
|
||||||
print("//");
|
|
||||||
} catch (e) {
|
|
||||||
emit(CountryError("Oops Something went wrong"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:sms_autofill/sms_autofill.dart';
|
import 'package:sms_autofill/sms_autofill.dart';
|
||||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||||
import 'package:tanami_app/Globalconst.dart';
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
|
|
||||||
import '../../domain/Repository/otp_api.dart';
|
import '../../domain/Repository/otp_api.dart';
|
||||||
import 'otp_event.dart';
|
import 'otp_event.dart';
|
||||||
import 'otp_state.dart';
|
import 'otp_state.dart';
|
||||||
|
|
||||||
class OtpBloc extends Bloc<OtpEvent, OtpState> {
|
class OtpBloc extends Bloc<OtpEvent, OtpState> {
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
final TextEditingController otpController = TextEditingController();
|
final TextEditingController otpController = TextEditingController();
|
||||||
OtpBloc() : super(OtpInitial()) {
|
OtpBloc({required this.secureStorageService}) : super(OtpInitial()) {
|
||||||
on<StartListeningForOtp>(_onStartListeningForOtp);
|
on<StartListeningForOtp>(_onStartListeningForOtp);
|
||||||
on<OtpCodeChanged>(_onOtpCodeChanged);
|
on<OtpCodeChanged>(_onOtpCodeChanged);
|
||||||
on<OtpSubmit>(_onOtpSubmit);
|
on<OtpSubmit>(_onOtpSubmit);
|
||||||
@@ -33,7 +34,7 @@ class OtpBloc extends Bloc<OtpEvent, OtpState> {
|
|||||||
emit(OtpSubmitting());
|
emit(OtpSubmitting());
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> otpdata = {
|
Map<String, dynamic> otpdata = {
|
||||||
"token": Globalconst.token,
|
"token": await secureStorageService.read("temp_token"),
|
||||||
"otp": otpController.text
|
"otp": otpController.text
|
||||||
};
|
};
|
||||||
ResponseData response = await OTPAPI().verifyOTP(otpdata);
|
ResponseData response = await OTPAPI().verifyOTP(otpdata);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/features/otpVerification/presentation/bloc/otp_bloc.dart';
|
import 'package:tanami_app/features/otpVerification/presentation/bloc/otp_bloc.dart';
|
||||||
import 'package:tanami_app/features/otpVerification/presentation/pages/otp_layout.dart';
|
import 'package:tanami_app/features/otpVerification/presentation/pages/otp_layout.dart';
|
||||||
|
|
||||||
@@ -19,14 +20,17 @@ class OtpScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColor.plainWhite,
|
backgroundColor: AppColor.plainWhite,
|
||||||
resizeToAvoidBottomInset: true,
|
resizeToAvoidBottomInset: true,
|
||||||
body: MultiBlocProvider(
|
body: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
// Create an instance of the OnboardingBloc
|
// Create an instance of the OnboardingBloc
|
||||||
create: (context) => OtpBloc()..add(StartListeningForOtp()),
|
create: (context) =>
|
||||||
|
OtpBloc(secureStorageService: secureStorageService)
|
||||||
|
..add(StartListeningForOtp()),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
@@ -34,8 +38,9 @@ class OtpScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
//RegisterBloc
|
//RegisterBloc
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) =>
|
create: (context) => RegisterBloc(
|
||||||
RegisterBloc(), // Start the timer here
|
secureStorageService:
|
||||||
|
secureStorageService), // Start the timer here
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: OtpLayout(fromScreen: fromScreen),
|
child: OtpLayout(fromScreen: fromScreen),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
import 'package:tanami_app/shared/components/toast_message.dart';
|
||||||
|
|
||||||
@@ -21,25 +22,30 @@ class ResendOtpSection extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String token = "";
|
String token = "";
|
||||||
|
getToken() async {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
|
token = await secureStorageService.read('temp_token') ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
getToken();
|
||||||
var loginBloc = context.read<RegisterBloc>();
|
var loginBloc = context.read<RegisterBloc>();
|
||||||
loginBloc.isdcode = Globalconst.isdcode;
|
loginBloc.isdcode = Globalconst.isdcode;
|
||||||
loginBloc.phoneNumberTextField.text = Globalconst.phonenumber;
|
loginBloc.phoneNumberTextField.text = Globalconst.phonenumber;
|
||||||
loginBloc.countrySelectionTextField.text = Globalconst.name;
|
loginBloc.countrySelectionTextField.text = Globalconst.name;
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
return BlocBuilder<TimerBloc, TimerState>(
|
return BlocBuilder<TimerBloc, TimerState>(
|
||||||
builder: (context, state) {
|
builder: (context, timerState) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
TextWidget().text14W500(
|
TextWidget().text14W500(
|
||||||
state.formattedDuration,
|
timerState.formattedDuration,
|
||||||
clr: AppColor.plainBlack,
|
clr: AppColor.plainBlack,
|
||||||
),
|
),
|
||||||
BlocConsumer<RegisterBloc, RegisterState>(
|
BlocConsumer<RegisterBloc, RegisterState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
print(loginBloc.state);
|
|
||||||
if (state is RegisterLoading) {
|
if (state is RegisterLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is RegisterSuccess) {
|
} else if (state is RegisterSuccess) {
|
||||||
@@ -64,12 +70,14 @@ class ResendOtpSection extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
loginBloc.add(
|
if (timerState is TimerRunComplete) {
|
||||||
Resendotp(Globalconst.token),
|
loginBloc.add(
|
||||||
);
|
Resendotp(token),
|
||||||
print("///");
|
);
|
||||||
|
} else {
|
||||||
// successToastMessage(context, "OTP Resend Sucessfully !");
|
errorToastMessage(context,
|
||||||
|
"Please wait ${timerState.formattedDuration} Minutes before resending OTP");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: TextWidget().text14W500(
|
child: TextWidget().text14W500(
|
||||||
localizations.translate(AppText.resendSms),
|
localizations.translate(AppText.resendSms),
|
||||||
@@ -81,24 +89,6 @@ class ResendOtpSection extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
/* GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
regbloc.add(
|
|
||||||
RegisterSubmitted(
|
|
||||||
loginBloc.phoneNumberTextField.text,
|
|
||||||
loginBloc.countrySelectionTextField.text,
|
|
||||||
loginBloc.isdcode
|
|
||||||
),
|
|
||||||
);
|
|
||||||
print("///");
|
|
||||||
// successToastMessage(context, "OTP Resend Sucessfully !");
|
|
||||||
},
|
|
||||||
child: TextWidget().text14W500(
|
|
||||||
localizations.translate(AppText.resendSms),
|
|
||||||
clr: AppColor.plainBlack,
|
|
||||||
textDecoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
) */
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,24 +2,26 @@ import 'package:bloc/bloc.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../../../../Api_Helper/base_manager.dart';
|
import '../../../../Api_Helper/base_manager.dart';
|
||||||
import '../../../../Globalconst.dart';
|
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||||
import '../../../otpVerification/domain/Repository/otp_api.dart';
|
import '../../../otpVerification/domain/Repository/otp_api.dart';
|
||||||
import 'register_event.dart';
|
import 'register_event.dart';
|
||||||
import 'register_state.dart';
|
import 'register_state.dart';
|
||||||
|
|
||||||
class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController countrySelectionTextField =
|
final TextEditingController countrySelectionTextField =
|
||||||
TextEditingController();
|
TextEditingController();
|
||||||
String isdcode="";
|
String isdcode = "";
|
||||||
String countryId="";
|
String countryId = "";
|
||||||
final TextEditingController phoneNumberTextField = TextEditingController();
|
final TextEditingController phoneNumberTextField = TextEditingController();
|
||||||
|
|
||||||
GlobalKey<FormState> getFormKey() {
|
GlobalKey<FormState> getFormKey() {
|
||||||
return formKey;
|
return formKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterBloc() : super(RegisterInitial()) {
|
RegisterBloc({required this.secureStorageService})
|
||||||
|
: super(RegisterInitial()) {
|
||||||
phoneNumberTextField.addListener(_onFormFieldChanged);
|
phoneNumberTextField.addListener(_onFormFieldChanged);
|
||||||
countrySelectionTextField.addListener(_onFormFieldChanged);
|
countrySelectionTextField.addListener(_onFormFieldChanged);
|
||||||
on<RegisterFormChanged>(_onLoginFormChanged);
|
on<RegisterFormChanged>(_onLoginFormChanged);
|
||||||
@@ -29,21 +31,18 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
|||||||
}
|
}
|
||||||
emit(RegisterLoading());
|
emit(RegisterLoading());
|
||||||
try {
|
try {
|
||||||
Map<String,dynamic> requestdata={
|
Map<String, dynamic> requestdata = {
|
||||||
"countryId":event.id,
|
"countryId": event.id,
|
||||||
"phoneNumber":event.phoneNumber
|
"phoneNumber": event.phoneNumber
|
||||||
};
|
};
|
||||||
ResponseData response = await OTPAPI().requestOTP(requestdata);
|
ResponseData response = await OTPAPI().requestOTP(requestdata);
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
print("///////success");
|
|
||||||
var data = response.data["data"];
|
var data = response.data["data"];
|
||||||
String token = data["token"];
|
String token = data["token"];
|
||||||
Globalconst.token = token;
|
await secureStorageService.write('temp_token', token);
|
||||||
emit(RegisterSuccess(token)); //emit(OTPLoaded());
|
emit(RegisterSuccess(token)); //emit(OTPLoaded());
|
||||||
} else {
|
} else {
|
||||||
emit(const RegisterFailure(
|
emit(RegisterFailure(response.message));
|
||||||
"Register failed. Please check your credentials."));
|
|
||||||
//emit(OTPFailed("Oops something went wrong"));
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(RegisterFailure(e.toString()));
|
emit(RegisterFailure(e.toString()));
|
||||||
@@ -54,7 +53,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
|||||||
emit(RegisterLoading());
|
emit(RegisterLoading());
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> requestdata = {
|
Map<String, dynamic> requestdata = {
|
||||||
"token": Globalconst.token,
|
"token": await secureStorageService.read('temp_token'),
|
||||||
};
|
};
|
||||||
ResponseData response = await OTPAPI().resendOTPRequest(requestdata);
|
ResponseData response = await OTPAPI().resendOTPRequest(requestdata);
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
@@ -83,14 +82,6 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
|
|||||||
emit(RegisterFieldsState(areFieldsFilled));
|
emit(RegisterFieldsState(areFieldsFilled));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock API function, replace with actual API call
|
|
||||||
Future<bool> _mockLoginApi(
|
|
||||||
String phoneNumber,
|
|
||||||
String countryResidence,
|
|
||||||
) async {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
phoneNumberTextField.dispose();
|
phoneNumberTextField.dispose();
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||||
import 'package:tanami_app/Globalconst.dart';
|
|
||||||
import 'package:tanami_app/features/register/Repository/RegisterApi.dart';
|
import 'package:tanami_app/features/register/Repository/RegisterApi.dart';
|
||||||
|
|
||||||
|
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||||
import 'register_user_event.dart';
|
import 'register_user_event.dart';
|
||||||
import 'register_user_state.dart';
|
import 'register_user_state.dart';
|
||||||
|
|
||||||
class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
||||||
|
final SecureStorageService secureStorageService;
|
||||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController firstNameTextField = TextEditingController();
|
final TextEditingController firstNameTextField = TextEditingController();
|
||||||
final TextEditingController lastNameTextField = TextEditingController();
|
final TextEditingController lastNameTextField = TextEditingController();
|
||||||
@@ -19,7 +20,8 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
|||||||
return formKey;
|
return formKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterUserBloc() : super(RegisterUserInitial()) {
|
RegisterUserBloc({required this.secureStorageService})
|
||||||
|
: super(RegisterUserInitial()) {
|
||||||
firstNameTextField.addListener(_onFormFieldChanged);
|
firstNameTextField.addListener(_onFormFieldChanged);
|
||||||
passwordTextField.addListener(_onFormFieldChanged);
|
passwordTextField.addListener(_onFormFieldChanged);
|
||||||
lastNameTextField.addListener(_onFormFieldChanged);
|
lastNameTextField.addListener(_onFormFieldChanged);
|
||||||
@@ -43,12 +45,11 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
|||||||
ResponseData response =
|
ResponseData response =
|
||||||
await RegisterAPIService().RegisterRequest(registerdata);
|
await RegisterAPIService().RegisterRequest(registerdata);
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
var data=response.data["data"];
|
var data = response.data["data"];
|
||||||
Globalconst.token=data["token"].toString();
|
secureStorageService.write("temp_token", data["token"].toString());
|
||||||
emit(RegisterUserSuccess());
|
emit(RegisterUserSuccess());
|
||||||
} else {
|
} else {
|
||||||
emit( RegisterUserFailure(
|
emit(RegisterUserFailure(response.message));
|
||||||
response.message));
|
|
||||||
}
|
}
|
||||||
// Simulate API call
|
// Simulate API call
|
||||||
await Future.delayed(const Duration(seconds: 2));
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
@@ -91,17 +92,6 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
|
|||||||
emit(RegisterUserFieldsState(areFieldsFilled));
|
emit(RegisterUserFieldsState(areFieldsFilled));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock API function, replace with actual API call
|
|
||||||
Future<bool> _mockLoginApi(
|
|
||||||
String firstName,
|
|
||||||
String password,
|
|
||||||
String confirmPassword,
|
|
||||||
String email,
|
|
||||||
String lastName,
|
|
||||||
) async {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
firstNameTextField.dispose();
|
firstNameTextField.dispose();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/features/register/presentation/bloc/register_bloc.dart';
|
import 'package:tanami_app/features/register/presentation/bloc/register_bloc.dart';
|
||||||
|
|
||||||
import '../../../../core/styles/app_color.dart';
|
import '../../../../core/styles/app_color.dart';
|
||||||
@@ -11,6 +12,7 @@ class RegisterScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
final radioBloc = context.read<RadioBloc>();
|
final radioBloc = context.read<RadioBloc>();
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
@@ -24,7 +26,8 @@ class RegisterScreen extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
// Create an instance of the OnboardingBloc
|
// Create an instance of the OnboardingBloc
|
||||||
create: (context) => RegisterBloc(),
|
create: (context) =>
|
||||||
|
RegisterBloc(secureStorageService: secureStorageService),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: const RegisterLayout(),
|
child: const RegisterLayout(),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/features/register/presentation/pages/register_user_details_layout.dart';
|
import 'package:tanami_app/features/register/presentation/pages/register_user_details_layout.dart';
|
||||||
import 'package:tanami_app/shared/components/bloc/checkbox/checkbox_bloc.dart';
|
import 'package:tanami_app/shared/components/bloc/checkbox/checkbox_bloc.dart';
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ class RegisterUserDetailsScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColor.plainWhite,
|
backgroundColor: AppColor.plainWhite,
|
||||||
resizeToAvoidBottomInset: true,
|
resizeToAvoidBottomInset: true,
|
||||||
@@ -20,7 +22,8 @@ class RegisterUserDetailsScreen extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
// Create an instance of the OnboardingBloc
|
// Create an instance of the OnboardingBloc
|
||||||
create: (context) => RegisterUserBloc(),
|
create: (context) =>
|
||||||
|
RegisterUserBloc(secureStorageService: secureStorageService),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
// Create an instance of the OnboardingBloc
|
// Create an instance of the OnboardingBloc
|
||||||
|
|||||||
@@ -37,18 +37,17 @@ class RegisterBottomSection extends StatelessWidget {
|
|||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
const Gap(36),
|
const Gap(36),
|
||||||
BlocConsumer<RegisterBloc, RegisterState>(
|
BlocConsumer<RegisterBloc, RegisterState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
print(loginBloc.state);
|
|
||||||
if (state is RegisterLoading) {
|
if (state is RegisterLoading) {
|
||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is RegisterSuccess) {
|
} else if (state is RegisterSuccess) {
|
||||||
successToastMessage(context, "successful !");
|
successToastMessage(
|
||||||
|
context, localizations.translate(AppText.successfulText));
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
|
|
||||||
goRouter.pushNamed(RouteName.otpScreen,
|
goRouter.pushNamed(RouteName.otpScreen,
|
||||||
pathParameters: {"fromScreen": "register"});
|
pathParameters: {"fromScreen": "register"});
|
||||||
|
|
||||||
} else if (state is RegisterFailure) {
|
} else if (state is RegisterFailure) {
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
errorToastMessage(
|
errorToastMessage(
|
||||||
@@ -75,16 +74,15 @@ class RegisterBottomSection extends StatelessWidget {
|
|||||||
? AppColor.plainWhite
|
? AppColor.plainWhite
|
||||||
: AppColor.inactiveBtnTxtColor,
|
: AppColor.inactiveBtnTxtColor,
|
||||||
function: () {
|
function: () {
|
||||||
Globalconst.phonenumber=loginBloc.phoneNumberTextField.text;
|
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;
|
||||||
|
|
||||||
isButtonEnabled
|
isButtonEnabled
|
||||||
? context.read<RegisterBloc>().add(
|
? context.read<RegisterBloc>().add(
|
||||||
RegisterSubmitted(
|
RegisterSubmitted(
|
||||||
loginBloc.phoneNumberTextField.text,
|
loginBloc.phoneNumberTextField.text,
|
||||||
loginBloc.countrySelectionTextField.text,
|
loginBloc.countrySelectionTextField.text,
|
||||||
loginBloc.isdcode,
|
loginBloc.isdcode,
|
||||||
loginBloc.countryId
|
loginBloc.countryId),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
|
||||||
import '../../../../Globalconst.dart';
|
import '../../../../Globalconst.dart';
|
||||||
|
import '../../../../core/styles/app_color.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
import '../../../../core/utils/phone_number_hint_generator/phone_number_hint_generator.dart';
|
||||||
import '../../../../shared/api/api_endpoints.dart';
|
import '../../../../shared/api/api_endpoints.dart';
|
||||||
import '../../../../shared/components/form_label_textfield.dart';
|
import '../../../../shared/components/form_label_textfield.dart';
|
||||||
import '../../../countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
import '../../../countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
||||||
@@ -21,25 +24,35 @@ class RegisterForm extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
final loginBloc = context.read<RegisterBloc>();
|
final registerBloc = context.read<RegisterBloc>();
|
||||||
final countrydata = context.read<GetCountryBlock>();
|
final countrydata = context.read<GetCountryBlock>();
|
||||||
int selectedCountry = -1;
|
int selectedCountry = -1;
|
||||||
String flag = "";
|
String flag = "";
|
||||||
|
String hintText = '00 000 000';
|
||||||
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
return BlocConsumer<RadioBloc, RadioState>(listener: (context, state) {
|
||||||
if (state is RadioSelectionChanged) {
|
if (state is RadioSelectionChanged) {
|
||||||
selectedCountry = state.selectedIndex;
|
selectedCountry = state.selectedIndex;
|
||||||
final countryState = countrydata.state;
|
final countryState = countrydata.state;
|
||||||
if (countryState is CountryLoaded) {
|
if (countryState is CountryLoaded) {
|
||||||
loginBloc.countrySelectionTextField.text = countryState
|
registerBloc.countrySelectionTextField.text = countryState
|
||||||
.countryModel.data![selectedCountry].countryName
|
.countryModel.data![selectedCountry].countryName
|
||||||
.toString();
|
.toString();
|
||||||
loginBloc.phoneNumberTextField.text =
|
registerBloc.phoneNumberTextField.text = "";
|
||||||
|
registerBloc.isdcode =
|
||||||
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
"${countryState.countryModel.data![selectedCountry].isdCode}";
|
||||||
loginBloc.isdcode="${countryState.countryModel.data![selectedCountry].isdCode}";
|
if (PhoneNumberHintGenerator().countryPhoneLengths.containsKey(
|
||||||
loginBloc.countryId="${countryState.countryModel.data![selectedCountry].id}";
|
registerBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength = PhoneNumberHintGenerator()
|
||||||
|
.countryPhoneLengths[registerBloc.isdcode];
|
||||||
|
hintText = PhoneNumberHintGenerator()
|
||||||
|
.formatPhoneNumber(registerBloc.isdcode, expectedLength!);
|
||||||
|
}
|
||||||
|
registerBloc.countryId =
|
||||||
|
"${countryState.countryModel.data![selectedCountry].id}";
|
||||||
flag =
|
flag =
|
||||||
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
"${ApiEndpoints.base}${countryState.countryModel.data![selectedCountry].flagIcon}";
|
||||||
Globalconst.phonenumber = loginBloc.phoneNumberTextField.text;
|
Globalconst.phonenumber = registerBloc.phoneNumberTextField.text;
|
||||||
|
|
||||||
Globalconst.name = countryState
|
Globalconst.name = countryState
|
||||||
.countryModel.data![selectedCountry].countryName
|
.countryModel.data![selectedCountry].countryName
|
||||||
@@ -55,7 +68,7 @@ class RegisterForm extends StatelessWidget {
|
|||||||
selectedCountry = -1;
|
selectedCountry = -1;
|
||||||
}
|
}
|
||||||
return Form(
|
return Form(
|
||||||
key: loginBloc.formKey,
|
key: registerBloc.formKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 14,
|
horizontal: 14,
|
||||||
@@ -85,10 +98,10 @@ class RegisterForm extends StatelessWidget {
|
|||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
maxHeightDiskCache: 200,
|
maxHeightDiskCache: 200,
|
||||||
maxWidthDiskCache: 200,
|
maxWidthDiskCache: 200,
|
||||||
cacheKey: loginBloc
|
cacheKey: registerBloc
|
||||||
.countrySelectionTextField.text,
|
.countrySelectionTextField.text,
|
||||||
key: UniqueKey(),
|
key: UniqueKey(),
|
||||||
imageUrl: flag,
|
imageUrl: "${ApiEndpoints.baseurl}$flag",
|
||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
placeholder: (context, url) => SizedBox(
|
placeholder: (context, url) => SizedBox(
|
||||||
@@ -113,7 +126,7 @@ class RegisterForm extends StatelessWidget {
|
|||||||
hintText: localizations.translate(AppText.chooseCountry),
|
hintText: localizations.translate(AppText.chooseCountry),
|
||||||
title: localizations.translate(AppText.countryOfResidence),
|
title: localizations.translate(AppText.countryOfResidence),
|
||||||
type: "country selection",
|
type: "country selection",
|
||||||
textEditingController: loginBloc.countrySelectionTextField,
|
textEditingController: registerBloc.countrySelectionTextField,
|
||||||
),
|
),
|
||||||
const Gap(20),
|
const Gap(20),
|
||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
@@ -121,38 +134,58 @@ class RegisterForm extends StatelessWidget {
|
|||||||
? null
|
? null
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: EdgeInsets.only(left: 12.w),
|
padding: EdgeInsets.only(left: 12.w),
|
||||||
child: SizedBox(
|
child: Row(
|
||||||
height: 50.h,
|
mainAxisSize: MainAxisSize.min,
|
||||||
width: 30.w,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
child: Align(
|
children: [
|
||||||
alignment: Alignment.centerLeft,
|
SizedBox(
|
||||||
child: SizedBox(
|
height: 50.h,
|
||||||
height: 30.h,
|
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
child: ClipRRect(
|
child: Align(
|
||||||
borderRadius: const BorderRadius.all(
|
alignment: Alignment.centerLeft,
|
||||||
Radius.circular(100)),
|
child: SizedBox(
|
||||||
child: CachedNetworkImage(
|
height: 30.h,
|
||||||
maxHeightDiskCache: 200,
|
width: 30.w,
|
||||||
maxWidthDiskCache: 200,
|
child: ClipRRect(
|
||||||
cacheKey: loginBloc
|
borderRadius: const BorderRadius.all(
|
||||||
.countrySelectionTextField.text,
|
Radius.circular(100)),
|
||||||
key: UniqueKey(),
|
child: CachedNetworkImage(
|
||||||
imageUrl: flag,
|
maxHeightDiskCache: 200,
|
||||||
height: 30.h,
|
maxWidthDiskCache: 200,
|
||||||
width: 30.w,
|
cacheKey: registerBloc
|
||||||
placeholder: (context, url) => SizedBox(
|
.countrySelectionTextField.text,
|
||||||
height: 30.h,
|
key: UniqueKey(),
|
||||||
width: 30.w,
|
imageUrl: flag,
|
||||||
child:
|
height: 30.h,
|
||||||
const CircularProgressIndicator(),
|
width: 30.w,
|
||||||
),
|
placeholder: (context, url) =>
|
||||||
errorWidget: (context, url, error) =>
|
SizedBox(
|
||||||
const Icon(Icons.error),
|
height: 30.h,
|
||||||
fit: BoxFit.cover),
|
width: 30.w,
|
||||||
|
child:
|
||||||
|
const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
errorWidget: (context, url, error) =>
|
||||||
|
const Icon(Icons.error),
|
||||||
|
fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const Gap(5),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(top: 10),
|
||||||
|
height: 30.h,
|
||||||
|
width: 40.w,
|
||||||
|
child: Text(
|
||||||
|
registerBloc.isdcode,
|
||||||
|
style: GoogleFonts.dmSans(
|
||||||
|
color: AppColor.charcoalColor,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
/* Image.asset(
|
/* Image.asset(
|
||||||
@@ -160,10 +193,10 @@ class RegisterForm extends StatelessWidget {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
), */
|
), */
|
||||||
hintText: "+0 (000) 000 00 00",
|
hintText: hintText,
|
||||||
title: localizations.translate(AppText.phoneNumber),
|
title: localizations.translate(AppText.phoneNumber),
|
||||||
type: "phone number",
|
type: "phone number",
|
||||||
textEditingController: loginBloc.phoneNumberTextField,
|
textEditingController: registerBloc.phoneNumberTextField,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,11 +4,26 @@ import 'package:tanami_app/core/styles/app_color.dart';
|
|||||||
import 'package:tanami_app/core/utils/constant/register_step_data.dart';
|
import 'package:tanami_app/core/utils/constant/register_step_data.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
|
||||||
|
import '../../../../core/styles/app_text.dart';
|
||||||
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
|
||||||
class RegisterStepCount extends StatelessWidget {
|
class RegisterStepCount extends StatelessWidget {
|
||||||
const RegisterStepCount({super.key});
|
const RegisterStepCount({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var localizations = AppLocalizations.of(context);
|
||||||
|
List<String> title = [
|
||||||
|
localizations.translate(AppText.step1),
|
||||||
|
localizations.translate(AppText.step2),
|
||||||
|
localizations.translate(AppText.step3),
|
||||||
|
];
|
||||||
|
|
||||||
|
List<String> description = [
|
||||||
|
localizations.translate(AppText.enterYourCountryOfResidence),
|
||||||
|
localizations.translate(AppText.enterNameEmailPassword),
|
||||||
|
localizations.translate(AppText.enableBiometricAuthentication),
|
||||||
|
];
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:tanami_app/Globalconst.dart';
|
|
||||||
import 'package:tanami_app/core/styles/app_images.dart';
|
import 'package:tanami_app/core/styles/app_images.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/shared/components/checkbox_widget.dart';
|
import 'package:tanami_app/shared/components/checkbox_widget.dart';
|
||||||
import 'package:tanami_app/shared/components/loader.dart';
|
import 'package:tanami_app/shared/components/loader.dart';
|
||||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
import 'package:tanami_app/shared/components/toast_message.dart';
|
||||||
@@ -31,8 +31,17 @@ class RegisterUserBottomSection extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
String token = "";
|
||||||
|
getToken() async {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
|
token = await secureStorageService.read("temp_token") ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
getToken();
|
||||||
|
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
var registerbloc = context.read<RegisterUserBloc>();
|
var registerbloc = context.read<RegisterUserBloc>();
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Gap(40),
|
const Gap(40),
|
||||||
@@ -99,7 +108,9 @@ class RegisterUserBottomSection extends StatelessWidget {
|
|||||||
Loader.loader(context);
|
Loader.loader(context);
|
||||||
} else if (state is RegisterUserSuccess) {
|
} else if (state is RegisterUserSuccess) {
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
permissionDialog(context,);
|
permissionDialog(
|
||||||
|
context,
|
||||||
|
);
|
||||||
} else if (state is RegisterUserFailure) {
|
} else if (state is RegisterUserFailure) {
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
errorToastMessage(
|
errorToastMessage(
|
||||||
@@ -130,29 +141,26 @@ class RegisterUserBottomSection extends StatelessWidget {
|
|||||||
? AppColor.plainWhite
|
? AppColor.plainWhite
|
||||||
: AppColor.inactiveBtnTxtColor,
|
: AppColor.inactiveBtnTxtColor,
|
||||||
function: () {
|
function: () {
|
||||||
|
if (isButtonEnabled == true) {
|
||||||
if(isButtonEnabled==true){
|
if (registerbloc.passwordTextField.text !=
|
||||||
if (registerbloc.passwordTextField.text !=
|
registerbloc.repeatPasswordTextField.text) {
|
||||||
registerbloc.repeatPasswordTextField.text) {
|
errorToastMessage(
|
||||||
errorToastMessage(
|
context,
|
||||||
context,
|
"Password and Repeat Password does not match.",
|
||||||
"Password and Repeat Password does not match.",
|
);
|
||||||
);
|
} else {
|
||||||
}else{
|
registerbloc.add(
|
||||||
registerbloc.add(
|
RegisterUserSubmitted(
|
||||||
RegisterUserSubmitted(
|
registerbloc.firstNameTextField.text,
|
||||||
registerbloc.firstNameTextField.text,
|
registerbloc.passwordTextField.text,
|
||||||
registerbloc.passwordTextField.text,
|
registerbloc.lastNameTextField.text,
|
||||||
registerbloc.lastNameTextField.text,
|
registerbloc.repeatPasswordTextField.text,
|
||||||
registerbloc.repeatPasswordTextField.text,
|
registerbloc.emailTextField.text,
|
||||||
registerbloc.emailTextField.text,
|
token,
|
||||||
Globalconst.token
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
text: localizations.translate(AppText.nextText),
|
text: localizations.translate(AppText.nextText),
|
||||||
clr: isButtonEnabled
|
clr: isButtonEnabled
|
||||||
@@ -162,7 +170,7 @@ class RegisterUserBottomSection extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Gap(5),
|
const Gap(8),
|
||||||
ButtonWidget().textBorderBtn(
|
ButtonWidget().textBorderBtn(
|
||||||
clr: AppColor.plainWhite,
|
clr: AppColor.plainWhite,
|
||||||
function: () {
|
function: () {
|
||||||
@@ -171,6 +179,7 @@ class RegisterUserBottomSection extends StatelessWidget {
|
|||||||
text: localizations.translate(AppText.backText),
|
text: localizations.translate(AppText.backText),
|
||||||
borderClr: AppColor.txtBorderColor,
|
borderClr: AppColor.txtBorderColor,
|
||||||
),
|
),
|
||||||
|
const Gap(10),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class RegisterUserForm extends StatelessWidget {
|
|||||||
FormLabelTextField(
|
FormLabelTextField(
|
||||||
hintText: localizations.translate(AppText.enterEmail),
|
hintText: localizations.translate(AppText.enterEmail),
|
||||||
title: localizations.translate(AppText.emailText),
|
title: localizations.translate(AppText.emailText),
|
||||||
type: AppText.emailText,
|
type: "email",
|
||||||
textEditingController: registerUserBloc.emailTextField,
|
textEditingController: registerUserBloc.emailTextField,
|
||||||
),
|
),
|
||||||
const Gap(12),
|
const Gap(12),
|
||||||
@@ -64,9 +64,11 @@ class RegisterUserForm extends StatelessWidget {
|
|||||||
child: FormLabelTextField(
|
child: FormLabelTextField(
|
||||||
hintText: localizations.translate(AppText.repeatPasswordText),
|
hintText: localizations.translate(AppText.repeatPasswordText),
|
||||||
title: localizations.translate(AppText.repeatPasswordText),
|
title: localizations.translate(AppText.repeatPasswordText),
|
||||||
type: AppText.password.toLowerCase(),
|
type: "repeat-password",
|
||||||
textEditingController:
|
textEditingController:
|
||||||
registerUserBloc.repeatPasswordTextField,
|
registerUserBloc.repeatPasswordTextField,
|
||||||
|
originalPasswordController:
|
||||||
|
registerUserBloc.passwordTextField,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ class PinAPIServices {
|
|||||||
final response = await NetworkApiService().post(url, data);
|
final response = await NetworkApiService().post(url, data);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
Future<ResponseData> Verifypin(Map<String, dynamic> data) async {
|
|
||||||
String url = ApiEndpoints.confirmpinapi;
|
Future<ResponseData> Verifypin(Map<String, dynamic> data) async {
|
||||||
|
String url = ApiEndpoints.verifypinapi;
|
||||||
final response = await NetworkApiService().post(url, data);
|
final response = await NetworkApiService().post(url, data);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||||
import 'package:tanami_app/Globalconst.dart';
|
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
|
||||||
|
import '../../../../core/routes/routes.dart';
|
||||||
import '../../../../core/utils/secure/secure_storage_service.dart';
|
import '../../../../core/utils/secure/secure_storage_service.dart';
|
||||||
import '../../Repository/PinAPIServices.dart';
|
import '../../Repository/PinAPIServices.dart';
|
||||||
|
|
||||||
@@ -23,43 +24,33 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
|||||||
final newPin = state.pin + event.number;
|
final newPin = state.pin + event.number;
|
||||||
|
|
||||||
if (newPin.length <= 6) {
|
if (newPin.length <= 6) {
|
||||||
|
if ((event.fromscreen == "login" ||
|
||||||
|
event.fromscreen == "LoginedInUser") &&
|
||||||
if (newPin.length == 6) {
|
newPin.length < 6) {
|
||||||
if (event.fromscreen == "login") {
|
emit(state.copyWith(
|
||||||
Map<String, dynamic> verifypindata = {
|
|
||||||
"token": Globalconst.token,
|
|
||||||
"masterPin": newPin
|
|
||||||
};
|
|
||||||
ResponseData response =
|
|
||||||
await PinAPIServices().Verifypin(verifypindata);
|
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
|
||||||
var data = response.data["user"];
|
|
||||||
String accesstoken = data["accessToken"];
|
|
||||||
String refreshtoken = data["refreshToken"];
|
|
||||||
await secureStorageService.write('accesstoken', accesstoken);
|
|
||||||
await secureStorageService.write('refreshtoken', refreshtoken);
|
|
||||||
|
|
||||||
emit(state.copyWith(
|
|
||||||
isVerified: false,
|
|
||||||
error: AppText.incorrectPinCode,
|
|
||||||
verifiedOnce: true,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
emit(state.copyWith(
|
|
||||||
pin: newPin,
|
|
||||||
pinComplete: newPin.length == 6,
|
|
||||||
error: 'has error',
|
|
||||||
isVerified: false,
|
|
||||||
verifiedOnce: false));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emit(state.copyWith(
|
|
||||||
pin: newPin,
|
pin: newPin,
|
||||||
pinComplete: newPin.length == 6,
|
pinComplete: newPin.length == 6,
|
||||||
error: '',
|
error: '',
|
||||||
verifiedOnce: false));
|
verifiedOnce: false,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
if ((event.fromscreen != "login" &&
|
||||||
|
event.fromscreen != "LoginedInUser")) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
pin: newPin,
|
||||||
|
pinComplete: newPin.length == 6,
|
||||||
|
error: '',
|
||||||
|
verifiedOnce: false,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPin.length == 6) {
|
||||||
|
if (event.fromscreen == "confirmpin") {
|
||||||
add(VerifyPinPressed(newPin, event.fromscreen));
|
add(VerifyPinPressed(newPin, event.fromscreen));
|
||||||
|
} else if (event.fromscreen == "login" ||
|
||||||
|
event.fromscreen == "LoginedInUser") {
|
||||||
|
add(VerifyLoginPinPressed(newPin, event.fromscreen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,9 +72,10 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
on<VerifyPinPressed>((event, emit) async {
|
on<VerifyPinPressed>((event, emit) async {
|
||||||
|
emit(const PinLoading());
|
||||||
final storedPin = await secureStorageService.read('pin_code');
|
final storedPin = await secureStorageService.read('pin_code');
|
||||||
Map<String, dynamic> pindata = {
|
Map<String, dynamic> pindata = {
|
||||||
"token": Globalconst.token,
|
"token": await secureStorageService.read("temp_token"),
|
||||||
"masterPin": event.pin
|
"masterPin": event.pin
|
||||||
};
|
};
|
||||||
if (storedPin == event.pin) {
|
if (storedPin == event.pin) {
|
||||||
@@ -92,8 +84,13 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
|||||||
await secureStorageService.write('userMPIN', storedPin.toString());
|
await secureStorageService.write('userMPIN', storedPin.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(state.copyWith(isVerified: true, error: '', verifiedOnce: true));
|
emit(state.copyWith(
|
||||||
|
isVerified: true,
|
||||||
|
error: '',
|
||||||
|
verifiedOnce: true,
|
||||||
|
pinComplete: true));
|
||||||
} else {
|
} else {
|
||||||
|
goRouter.pop();
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isVerified: false,
|
isVerified: false,
|
||||||
error: AppText.incorrectPinCode,
|
error: AppText.incorrectPinCode,
|
||||||
@@ -101,5 +98,36 @@ class PinBloc extends Bloc<PinEvent, PinState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
on<VerifyLoginPinPressed>((event, emit) async {
|
||||||
|
emit(const PinLoading());
|
||||||
|
Map<String, dynamic> pindata = {
|
||||||
|
"token": await secureStorageService.read("temp_token"),
|
||||||
|
"masterPin": event.pin
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseData response = await PinAPIServices().Verifypin(pindata);
|
||||||
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
|
await secureStorageService.write(
|
||||||
|
'accesstoken', response.data["data"]["accessToken"]);
|
||||||
|
await secureStorageService.write(
|
||||||
|
'refreshtoken', response.data["data"]["refreshToken"]);
|
||||||
|
emit(state.copyWith(
|
||||||
|
pinComplete: true,
|
||||||
|
pin: state.pin,
|
||||||
|
isVerified: true,
|
||||||
|
error: '',
|
||||||
|
verifiedOnce: false));
|
||||||
|
} else {
|
||||||
|
goRouter.pop();
|
||||||
|
emit(state.copyWith(
|
||||||
|
pinComplete: true,
|
||||||
|
pin: state.pin,
|
||||||
|
isVerified: false,
|
||||||
|
error: "Incorrect Pin Code",
|
||||||
|
verifiedOnce: true,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ class NumberPressed extends PinEvent {
|
|||||||
final String number;
|
final String number;
|
||||||
final String fromscreen;
|
final String fromscreen;
|
||||||
|
|
||||||
const NumberPressed(this.number,this.fromscreen);
|
const NumberPressed(this.number, this.fromscreen);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [number];
|
List<Object> get props => [number, fromscreen];
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackspacePressed extends PinEvent {}
|
class BackspacePressed extends PinEvent {}
|
||||||
@@ -24,8 +24,17 @@ class SavePinPressed extends PinEvent {}
|
|||||||
class VerifyPinPressed extends PinEvent {
|
class VerifyPinPressed extends PinEvent {
|
||||||
final String pin;
|
final String pin;
|
||||||
final String fromscreen;
|
final String fromscreen;
|
||||||
const VerifyPinPressed(this.pin,this.fromscreen);
|
const VerifyPinPressed(this.pin, this.fromscreen);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [pin,fromscreen];
|
List<Object> get props => [pin, fromscreen];
|
||||||
|
}
|
||||||
|
|
||||||
|
class VerifyLoginPinPressed extends PinEvent {
|
||||||
|
final String pin;
|
||||||
|
final String fromscreen;
|
||||||
|
const VerifyLoginPinPressed(this.pin, this.fromscreen);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [pin, fromscreen];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,3 +34,13 @@ class PinState extends Equatable {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [pin, pinComplete, isVerified, error, verifiedOnce];
|
List<Object> get props => [pin, pinComplete, isVerified, error, verifiedOnce];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PinLoading extends PinState {
|
||||||
|
const PinLoading()
|
||||||
|
: super(
|
||||||
|
pin: '',
|
||||||
|
pinComplete: false,
|
||||||
|
isVerified: false,
|
||||||
|
error: '',
|
||||||
|
verifiedOnce: false);
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ class PinLayout extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
PinTopSection(fromScreen: fromScreen),
|
PinTopSection(
|
||||||
|
fromScreen: fromScreen,
|
||||||
|
),
|
||||||
PinKey(
|
PinKey(
|
||||||
fromScreen: fromScreen,
|
fromScreen: fromScreen,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ class PinScreen extends StatelessWidget {
|
|||||||
final secureStorageService = SecureStorageService();
|
final secureStorageService = SecureStorageService();
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
if (fromScreen == "LoginedInUser") {
|
if (fromScreen == "login" ||
|
||||||
|
fromScreen == "LoginedInUser" ||
|
||||||
|
fromScreen == "login-master-pending") {
|
||||||
exitAppDialog(context);
|
exitAppDialog(context);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@@ -29,7 +31,9 @@ class PinScreen extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: AppColor.plainWhite,
|
backgroundColor: AppColor.plainWhite,
|
||||||
appBar: fromScreen == "register" || fromScreen == "reset-pin"
|
appBar: fromScreen == "register" ||
|
||||||
|
fromScreen == "reset-pin" ||
|
||||||
|
fromScreen == "login-master-pending"
|
||||||
? AppBarWidget(
|
? AppBarWidget(
|
||||||
height: 75,
|
height: 75,
|
||||||
titleTxt: fromScreen == "reset-pin"
|
titleTxt: fromScreen == "reset-pin"
|
||||||
|
|||||||
@@ -4,8 +4,13 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:tanami_app/core/routes/route_name.dart';
|
import 'package:tanami_app/core/routes/route_name.dart';
|
||||||
import 'package:tanami_app/core/routes/routes.dart';
|
import 'package:tanami_app/core/routes/routes.dart';
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
import 'package:tanami_app/shared/components/toast_message.dart';
|
||||||
|
|
||||||
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
import '../../../../shared/components/loader.dart';
|
||||||
import '../bloc/pin_bloc.dart';
|
import '../bloc/pin_bloc.dart';
|
||||||
|
|
||||||
class ConfirmPinKey extends StatelessWidget {
|
class ConfirmPinKey extends StatelessWidget {
|
||||||
@@ -13,13 +18,23 @@ class ConfirmPinKey extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var localizations = AppLocalizations.of(context);
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Gap(20),
|
const Gap(20),
|
||||||
BlocConsumer<PinBloc, PinState>(
|
BlocConsumer<PinBloc, PinState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) async {
|
||||||
|
if (state is PinLoading) {
|
||||||
|
Loader.loader(context);
|
||||||
|
}
|
||||||
if (state.pinComplete && state.isVerified) {
|
if (state.pinComplete && state.isVerified) {
|
||||||
// successToastMessage(context, "Pin verified successfully");
|
goRouter.pop();
|
||||||
|
successToastMessage(
|
||||||
|
context,
|
||||||
|
localizations
|
||||||
|
.translate(AppText.masterPinAddedSucessfullyText));
|
||||||
|
await secureStorageService.write('isLoginedIn', "true");
|
||||||
goRouter.goNamed(RouteName.mainScreen);
|
goRouter.goNamed(RouteName.mainScreen);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -91,7 +106,9 @@ class ConfirmPinKey extends StatelessWidget {
|
|||||||
final number = index == 10 ? '0' : '${index + 1}';
|
final number = index == 10 ? '0' : '${index + 1}';
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.read<PinBloc>().add(NumberPressed(number,"confirmpin"));
|
context
|
||||||
|
.read<PinBloc>()
|
||||||
|
.add(NumberPressed(number, "confirmpin"));
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.all(12),
|
margin: const EdgeInsets.all(12),
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import 'dart:developer';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/core/routes/route_name.dart';
|
|
||||||
import 'package:tanami_app/core/routes/routes.dart';
|
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
import 'package:tanami_app/features/countrySelection/bloc/choose_country_bloc.dart';
|
||||||
import 'package:tanami_app/features/securePin/presentation/widgets/forgot_pin_dialog.dart';
|
import 'package:tanami_app/features/securePin/presentation/widgets/forgot_pin_dialog.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
import 'package:tanami_app/shared/components/toast_message.dart';
|
|
||||||
|
|
||||||
|
import '../../../../core/routes/route_name.dart';
|
||||||
|
import '../../../../core/routes/routes.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
import '../../../../shared/components/loader.dart';
|
||||||
|
import '../../../../shared/components/toast_message.dart';
|
||||||
|
import '../../../login/presentation/bloc/login_bloc.dart';
|
||||||
import '../bloc/pin_bloc.dart';
|
import '../bloc/pin_bloc.dart';
|
||||||
|
|
||||||
class PinKey extends StatelessWidget {
|
class PinKey extends StatelessWidget {
|
||||||
@@ -23,34 +24,39 @@ class PinKey extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print(fromScreen);
|
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
|
final loginBloc = context.read<LoginBloc>();
|
||||||
|
final radioBloc = context.read<RadioBloc>();
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
const Gap(20),
|
const Gap(20),
|
||||||
BlocConsumer<PinBloc, PinState>(
|
BlocConsumer<PinBloc, PinState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
|
if (state is PinLoading) {
|
||||||
|
Loader.loader(context);
|
||||||
|
}
|
||||||
if (state.pinComplete &&
|
if (state.pinComplete &&
|
||||||
state.error.isEmpty &&
|
state.error.isEmpty &&
|
||||||
!state.verifiedOnce) {
|
!state.verifiedOnce) {
|
||||||
if (fromScreen == "login" || fromScreen == "LoginedInUser") {
|
if (fromScreen == "login" || fromScreen == "LoginedInUser") {
|
||||||
print("login true");
|
goRouter.pop();
|
||||||
|
loginBloc.resetFields();
|
||||||
|
radioBloc.resetSelection();
|
||||||
successToastMessage(context,
|
successToastMessage(context,
|
||||||
localizations.translate(AppText.pinVerifiedSucess));
|
localizations.translate(AppText.pinVerifiedSucess));
|
||||||
goRouter.pushNamed(RouteName.mainScreen);
|
goRouter.pushNamed(RouteName.mainScreen);
|
||||||
} else if (fromScreen == "reset-pin") {
|
} else if (fromScreen == "reset-pin") {
|
||||||
print("reset true");
|
|
||||||
|
|
||||||
log("Running this");
|
|
||||||
successToastMessage(
|
successToastMessage(
|
||||||
context, localizations.translate(AppText.pinUpdatedSucess));
|
context, localizations.translate(AppText.pinUpdatedSucess));
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
} else {
|
} else {
|
||||||
|
goRouter.pop();
|
||||||
context.read<PinBloc>().add(SavePinPressed());
|
context.read<PinBloc>().add(SavePinPressed());
|
||||||
goRouter.pushNamed(RouteName.confirmPinScreen);
|
goRouter.pushNamed(RouteName.confirmPinScreen);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// goRouter.pop();
|
||||||
if (state.pinComplete) {
|
if (state.pinComplete) {
|
||||||
errorToastMessage(
|
errorToastMessage(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:tanami_app/core/styles/app_color.dart';
|
|||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
|
||||||
|
import '../../../../Globalconst.dart';
|
||||||
import '../../../../core/styles/app_images.dart';
|
import '../../../../core/styles/app_images.dart';
|
||||||
import '../../../../core/utils/language/localizations_delegate.dart';
|
import '../../../../core/utils/language/localizations_delegate.dart';
|
||||||
|
|
||||||
@@ -38,8 +39,9 @@ class PinTopSection extends StatelessWidget {
|
|||||||
TextWidget().text14W500(
|
TextWidget().text14W500(
|
||||||
localizations.translate(AppText.welcomeBackText),
|
localizations.translate(AppText.welcomeBackText),
|
||||||
clr: AppColor.smokeGrayColor),
|
clr: AppColor.smokeGrayColor),
|
||||||
TextWidget()
|
TextWidget().text14W700(
|
||||||
.text14W700(", Pooja", clr: AppColor.plainBlack),
|
", ${Globalconst.firstName.trim()}",
|
||||||
|
clr: AppColor.plainBlack),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
TextWidget().text14W500(
|
TextWidget().text14W500(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:tanami_app/Globalconst.dart';
|
||||||
import 'package:tanami_app/core/routes/route_name.dart';
|
import 'package:tanami_app/core/routes/route_name.dart';
|
||||||
import 'package:tanami_app/core/routes/routes.dart';
|
import 'package:tanami_app/core/routes/routes.dart';
|
||||||
|
|
||||||
@@ -48,6 +49,9 @@ class SplashScreen extends StatelessWidget {
|
|||||||
await secureStorageService.read('biometric') == 'on') {
|
await secureStorageService.read('biometric') == 'on') {
|
||||||
goRouter.goNamed(RouteName.biometricScreen);
|
goRouter.goNamed(RouteName.biometricScreen);
|
||||||
} else {
|
} else {
|
||||||
|
Globalconst.firstName =
|
||||||
|
await secureStorageService.read("first_name") ?? "";
|
||||||
|
|
||||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||||
"fromScreen": "LoginedInUser",
|
"fromScreen": "LoginedInUser",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:tanami_app/features/welcome/presentation/pages/welcome_layout.dart';
|
import 'package:tanami_app/features/welcome/presentation/pages/welcome_layout.dart';
|
||||||
|
|
||||||
import '../../../../core/styles/app_color.dart';
|
import '../../../../core/styles/app_color.dart';
|
||||||
|
import '../../../../shared/components/exit_app_dialog.dart';
|
||||||
import '../bloc/onboarding_bloc.dart';
|
import '../bloc/onboarding_bloc.dart';
|
||||||
|
|
||||||
class WelcomeScreen extends StatelessWidget {
|
class WelcomeScreen extends StatelessWidget {
|
||||||
@@ -10,17 +11,23 @@ class WelcomeScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return WillPopScope(
|
||||||
backgroundColor: AppColor.plainWhite,
|
onWillPop: () async {
|
||||||
body: MultiBlocProvider(
|
exitAppDialog(context);
|
||||||
// Define the providers for the OnboardingBloc and other blocs
|
return false;
|
||||||
providers: [
|
},
|
||||||
BlocProvider(
|
child: Scaffold(
|
||||||
// Create an instance of the OnboardingBloc
|
backgroundColor: AppColor.plainWhite,
|
||||||
create: (_) => OnboardingBloc(),
|
body: MultiBlocProvider(
|
||||||
),
|
// Define the providers for the OnboardingBloc and other blocs
|
||||||
],
|
providers: [
|
||||||
child: WelcomeLayout(),
|
BlocProvider(
|
||||||
|
// Create an instance of the OnboardingBloc
|
||||||
|
create: (_) => OnboardingBloc(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: WelcomeLayout(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
import 'package:tanami_app/core/styles/app_images.dart';
|
import 'package:tanami_app/core/styles/app_images.dart';
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
|
||||||
|
import '../../../../shared/components/language_change_bottom_sheet.dart';
|
||||||
import 'login_signup_button.dart';
|
import 'login_signup_button.dart';
|
||||||
import 'welcome_indicator.dart';
|
import 'welcome_indicator.dart';
|
||||||
|
|
||||||
@@ -23,7 +22,21 @@ Widget buildOnboardingPage(
|
|||||||
}) {
|
}) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Gap(80),
|
index == 0 ? const Gap(40) : const Gap(0),
|
||||||
|
index == 0
|
||||||
|
? Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showLanguageBottomSheet(context);
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.language_outlined,
|
||||||
|
size: 30,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
index == 0 ? const Gap(20) : const Gap(80),
|
||||||
SvgPicture.asset(AppImages.welcomeLogo),
|
SvgPicture.asset(AppImages.welcomeLogo),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
imageAsset,
|
imageAsset,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
import 'package:local_auth/local_auth.dart';
|
||||||
|
import 'package:tanami_app/features/login/presentation/bloc/login_bloc.dart';
|
||||||
|
|
||||||
import 'core/routes/routes.dart';
|
import 'core/routes/routes.dart';
|
||||||
import 'core/utils/connectivity/network_connectivity.dart';
|
import 'core/utils/connectivity/network_connectivity.dart';
|
||||||
@@ -13,7 +14,9 @@ import 'features/biometric/presentation/bloc/biometric_bloc.dart';
|
|||||||
import 'features/biometric/presentation/bloc/biometric_event.dart';
|
import 'features/biometric/presentation/bloc/biometric_event.dart';
|
||||||
import 'features/countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
import 'features/countrySelection/bloc/GetCountry/get_country_bloc.dart';
|
||||||
import 'features/countrySelection/bloc/choose_country_bloc.dart';
|
import 'features/countrySelection/bloc/choose_country_bloc.dart';
|
||||||
|
import 'features/forgotPassword/presentation/bloc/restore_password_phone_verification_bloc.dart';
|
||||||
import 'features/otpVerification/bloc/otp_bloc.dart';
|
import 'features/otpVerification/bloc/otp_bloc.dart';
|
||||||
|
import 'features/register/presentation/bloc/register_bloc.dart';
|
||||||
import 'shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
|
import 'shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
|
||||||
import 'shared/components/bloc/language/lng_bloc.dart';
|
import 'shared/components/bloc/language/lng_bloc.dart';
|
||||||
import 'shared/components/bloc/language/lng_event.dart';
|
import 'shared/components/bloc/language/lng_event.dart';
|
||||||
@@ -98,7 +101,16 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) =>
|
create: (_) =>
|
||||||
BiometricBloc(LocalAuthentication())..add(CheckBiometricEvent()),
|
RegisterBloc(secureStorageService: secureStorageService),
|
||||||
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => LoginBloc(secureStorageService: secureStorageService),
|
||||||
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => BiometricBloc(
|
||||||
|
LocalAuthentication(),
|
||||||
|
secureStorageService,
|
||||||
|
)..add(CheckBiometricEvent()),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => LocalizationBloc(),
|
create: (_) => LocalizationBloc(),
|
||||||
@@ -109,6 +121,10 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => OTPBloc(),
|
create: (_) => OTPBloc(),
|
||||||
),
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => RestorePasswordPhoneVerificationBloc(
|
||||||
|
secureStorageService: secureStorageService),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: ScreenUtilInit(
|
child: ScreenUtilInit(
|
||||||
builder: (BuildContext context, Widget? child) =>
|
builder: (BuildContext context, Widget? child) =>
|
||||||
|
|||||||
@@ -3,13 +3,29 @@ class ApiEndpoints {
|
|||||||
static const baseurl =
|
static const baseurl =
|
||||||
"https://tanami.betadelivery.com/api/development/v1/"; //App Base url
|
"https://tanami.betadelivery.com/api/development/v1/"; //App Base url
|
||||||
|
|
||||||
|
//Country
|
||||||
static const getcountryurl = "${baseurl}country/getAllCountry";
|
static const getcountryurl = "${baseurl}country/getAllCountry";
|
||||||
|
|
||||||
|
//Register
|
||||||
static const requestotpapi = "${baseurl}auth/public/register";
|
static const requestotpapi = "${baseurl}auth/public/register";
|
||||||
|
static const registerrequestapi = "${baseurl}auth/public/email-register";
|
||||||
|
|
||||||
|
//OTP
|
||||||
static const requestresendotp = "${baseurl}auth/public/resend-otp";
|
static const requestresendotp = "${baseurl}auth/public/resend-otp";
|
||||||
static const verifyotp = "${baseurl}auth/public/verify-otp";
|
static const verifyotp = "${baseurl}auth/public/verify-otp";
|
||||||
static const registerrequestapi = "${baseurl}auth/public/email-register";
|
|
||||||
|
//Biometric
|
||||||
static const biometricUpdateapi = "${baseurl}auth/public/biometric-update";
|
static const biometricUpdateapi = "${baseurl}auth/public/biometric-update";
|
||||||
static const confirmpinapi="${baseurl}auth/public/masterPin";
|
static const biometricLoginapi = "${baseurl}auth/public/biometric-login";
|
||||||
static const loginapi="${baseurl}auth/public/login";
|
|
||||||
static const verifypinapi="${baseurl}auth/public/verify-materPin";
|
//PIN
|
||||||
|
static const confirmpinapi = "${baseurl}auth/public/masterPin";
|
||||||
|
static const verifypinapi = "${baseurl}auth/public/verify-materPin";
|
||||||
|
|
||||||
|
//Login
|
||||||
|
static const loginapi = "${baseurl}auth/public/login";
|
||||||
|
|
||||||
|
//Forgot Password
|
||||||
|
static const forgotPasswordApi = "${baseurl}auth/public/forgot-password";
|
||||||
|
static const resetPasswordApi = "${baseurl}auth/public/reset-password";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,22 @@ import 'package:flutter/foundation.dart';
|
|||||||
import '../../Api_Helper/base_manager.dart';
|
import '../../Api_Helper/base_manager.dart';
|
||||||
|
|
||||||
class NetworkApiService {
|
class NetworkApiService {
|
||||||
final Dio _dio = Dio();
|
final Dio _dio = Dio(BaseOptions(
|
||||||
|
validateStatus: (status) {
|
||||||
|
return status != null &&
|
||||||
|
status < 500; // Allow any status code less than 500
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
// Common function for GET requests
|
// Common function for GET requests
|
||||||
Future<ResponseData> get(String url,
|
Future<ResponseData> get(String url,
|
||||||
{Map<String, dynamic>? queryParameters}) async {
|
{Map<String, dynamic>? queryParameters}) async {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print("api url is >>> $url");
|
print("api url is >>> $url");
|
||||||
}
|
}
|
||||||
Response response;
|
Response response;
|
||||||
try {
|
try {
|
||||||
response = await _dio.get(url);
|
response = await _dio.get(url);
|
||||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||||
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
||||||
data: response.data);
|
data: response.data);
|
||||||
@@ -29,10 +34,11 @@ class NetworkApiService {
|
|||||||
data: response.data,
|
data: response.data,
|
||||||
response.statusMessage!,
|
response.statusMessage!,
|
||||||
ResponseStatus.FAILED);
|
ResponseStatus.FAILED);
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ResponseData<dynamic>(
|
return ResponseData<dynamic>(
|
||||||
"Something went wrong", ResponseStatus.FAILED);
|
"Something went wrong", ResponseStatus.FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,24 +49,52 @@ class NetworkApiService {
|
|||||||
print("api url is >>> $url");
|
print("api url is >>> $url");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var response= await _dio.post(url, data: data);
|
var response = await _dio.post(
|
||||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
url,
|
||||||
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
data: data,
|
||||||
|
);
|
||||||
|
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||||
|
return ResponseData<dynamic>("success", ResponseStatus.SUCCESS,
|
||||||
data: response.data);
|
data: response.data);
|
||||||
}else {
|
} else if (response.statusCode == 400) {
|
||||||
|
if (response.data['message'] == "Master Pin is not created") {
|
||||||
|
return ResponseData<dynamic>(
|
||||||
|
response.data['message'], ResponseStatus.PRIVATE,
|
||||||
|
data: response.data);
|
||||||
|
} else if (response.data['error']['message'] ==
|
||||||
|
"MASTER PIN NOT MATCH") {
|
||||||
|
return ResponseData<dynamic>(
|
||||||
|
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||||
|
data: response.data);
|
||||||
|
} else if (response.data['error']['message'] ==
|
||||||
|
"Account already exists. Please Login instead.") {
|
||||||
|
return ResponseData<dynamic>(
|
||||||
|
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||||
|
data: response.data);
|
||||||
|
} else {
|
||||||
|
return ResponseData<dynamic>(
|
||||||
|
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||||
|
data: response.data);
|
||||||
|
}
|
||||||
|
} else if (response.statusCode == 401) {
|
||||||
|
return ResponseData<dynamic>(
|
||||||
|
response.data['error']['message'], ResponseStatus.PRIVATE,
|
||||||
|
data: response.data);
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
return ResponseData<dynamic>(
|
return ResponseData<dynamic>(
|
||||||
response.data['message'].toString(), ResponseStatus.FAILED);
|
response.data['error']['message'].toString(),
|
||||||
|
ResponseStatus.FAILED);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return ResponseData<dynamic>(
|
return ResponseData<dynamic>(
|
||||||
data: response.data,
|
data: response.data,
|
||||||
response.statusMessage!,
|
response.statusMessage!,
|
||||||
ResponseStatus.FAILED);
|
ResponseStatus.FAILED);
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ResponseData<dynamic>(
|
return ResponseData<dynamic>(
|
||||||
"Oops something went wrong",
|
"Oops something went wrong", ResponseStatus.FAILED);
|
||||||
ResponseStatus.FAILED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
|
||||||
import '../../core/utils/language/localizations_delegate.dart';
|
import '../../core/utils/language/localizations_delegate.dart';
|
||||||
import 'bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
|
import 'bloc/bottom_nav_bar/bottom_navigation_bloc.dart';
|
||||||
@@ -45,7 +46,7 @@ Widget bottomnavigationbar(
|
|||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
),
|
),
|
||||||
label: localizations.translate('Wallet'),
|
label: localizations.translate(AppText.walletText),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
@@ -58,7 +59,7 @@ Widget bottomnavigationbar(
|
|||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
),
|
),
|
||||||
label: localizations.translate('Portfolio'),
|
label: localizations.translate(AppText.portfolioBottomText),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
@@ -71,7 +72,7 @@ Widget bottomnavigationbar(
|
|||||||
height: 28.h,
|
height: 28.h,
|
||||||
width: 28.w,
|
width: 28.w,
|
||||||
),
|
),
|
||||||
label: localizations.translate('Invest'),
|
label: localizations.translate(AppText.investText),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
@@ -84,7 +85,7 @@ Widget bottomnavigationbar(
|
|||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
),
|
),
|
||||||
label: localizations.translate('Academy'),
|
label: localizations.translate(AppText.academyText),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Image.asset(
|
icon: Image.asset(
|
||||||
@@ -97,7 +98,7 @@ Widget bottomnavigationbar(
|
|||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: 30.w,
|
width: 30.w,
|
||||||
),
|
),
|
||||||
label: localizations.translate('Settings'),
|
label: localizations.translate(AppText.settingsText),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/core/routes/routes.dart';
|
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
import 'package:tanami_app/features/biometric/presentation/bloc/biometric_bloc.dart';
|
import 'package:tanami_app/features/biometric/presentation/bloc/biometric_bloc.dart';
|
||||||
|
|
||||||
|
import '../../Globalconst.dart';
|
||||||
|
import '../../core/routes/route_name.dart';
|
||||||
|
import '../../core/routes/routes.dart';
|
||||||
import '../../core/utils/language/localizations_delegate.dart';
|
import '../../core/utils/language/localizations_delegate.dart';
|
||||||
import '../../features/biometric/presentation/bloc/biometric_event.dart';
|
|
||||||
import '../../features/biometric/presentation/bloc/biometric_state.dart';
|
import '../../features/biometric/presentation/bloc/biometric_state.dart';
|
||||||
import 'text_widget.dart';
|
import 'text_widget.dart';
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ deviceLockedDialog(
|
|||||||
context,
|
context,
|
||||||
) {
|
) {
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
return showDialog(
|
return showDialog(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
context: context,
|
context: context,
|
||||||
@@ -106,11 +109,19 @@ deviceLockedDialog(
|
|||||||
),
|
),
|
||||||
Gap(15.w),
|
Gap(15.w),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
goRouter.pop();
|
// goRouter.pop();
|
||||||
context
|
// context
|
||||||
.read<BiometricBloc>()
|
// .read<BiometricBloc>()
|
||||||
.add(AuthenticateBiometricEvent());
|
// .add(AuthenticateBiometricEvent());
|
||||||
|
Globalconst.firstName =
|
||||||
|
await secureStorageService.read("first_name") ??
|
||||||
|
"";
|
||||||
|
|
||||||
|
goRouter
|
||||||
|
.goNamed(RouteName.pinScreen, pathParameters: {
|
||||||
|
"fromScreen": "LoginedInUser",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 48.h,
|
height: 48.h,
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
import 'package:tanami_app/core/styles/app_text.dart';
|
import 'package:tanami_app/core/styles/app_text.dart';
|
||||||
|
import 'package:tanami_app/features/login/presentation/bloc/login_bloc.dart';
|
||||||
import 'package:tanami_app/shared/components/password_text_form_field.dart';
|
import 'package:tanami_app/shared/components/password_text_form_field.dart';
|
||||||
import 'package:tanami_app/shared/components/text_widget.dart';
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
|
||||||
import '../../core/routes/route_name.dart';
|
import '../../core/routes/route_name.dart';
|
||||||
import '../../core/routes/routes.dart';
|
import '../../core/routes/routes.dart';
|
||||||
import '../../core/utils/language/localizations_delegate.dart';
|
import '../../core/utils/language/localizations_delegate.dart';
|
||||||
|
import '../../features/forgotPassword/presentation/bloc/restore_password_phone_verification_bloc.dart';
|
||||||
|
import '../../features/register/presentation/bloc/register_bloc.dart';
|
||||||
import 'text_from_field_widget.dart';
|
import 'text_from_field_widget.dart';
|
||||||
|
|
||||||
class FormLabelTextField extends StatelessWidget {
|
class FormLabelTextField extends StatelessWidget {
|
||||||
@@ -20,6 +24,7 @@ class FormLabelTextField extends StatelessWidget {
|
|||||||
required this.hintText,
|
required this.hintText,
|
||||||
this.prefixWidget,
|
this.prefixWidget,
|
||||||
this.onChangeFun,
|
this.onChangeFun,
|
||||||
|
this.originalPasswordController,
|
||||||
});
|
});
|
||||||
final String title;
|
final String title;
|
||||||
final String type;
|
final String type;
|
||||||
@@ -27,9 +32,24 @@ class FormLabelTextField extends StatelessWidget {
|
|||||||
final TextEditingController textEditingController;
|
final TextEditingController textEditingController;
|
||||||
final Widget? prefixWidget;
|
final Widget? prefixWidget;
|
||||||
final Function(String)? onChangeFun;
|
final Function(String)? onChangeFun;
|
||||||
|
final TextEditingController? originalPasswordController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// Map of country codes to phone number lengths
|
||||||
|
final Map<String, int> countryPhoneLengths = {
|
||||||
|
"+973": 8, // Bahrain
|
||||||
|
"+965": 8, // Kuwait
|
||||||
|
"+968": 8, // Oman
|
||||||
|
"+974": 8, // Qatar
|
||||||
|
"+966": 9, // Saudi Arabia
|
||||||
|
"+971": 9, // United Arab Emirates
|
||||||
|
"+91": 10,
|
||||||
|
};
|
||||||
|
var registerBloc = context.read<RegisterBloc>();
|
||||||
|
var loginBloc = context.read<LoginBloc>();
|
||||||
|
var restorePasswordBloc =
|
||||||
|
context.read<RestorePasswordPhoneVerificationBloc>();
|
||||||
var localizations = AppLocalizations.of(context);
|
var localizations = AppLocalizations.of(context);
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -40,10 +60,11 @@ class FormLabelTextField extends StatelessWidget {
|
|||||||
txtAlign: type == "description" ? TextAlign.start : TextAlign.center,
|
txtAlign: type == "description" ? TextAlign.start : TextAlign.center,
|
||||||
),
|
),
|
||||||
const Gap(10),
|
const Gap(10),
|
||||||
type == "password"
|
(type == "password" || type == "repeat-password")
|
||||||
? PasswordField(
|
? PasswordField(
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
|
originalPasswordController: originalPasswordController,
|
||||||
)
|
)
|
||||||
: textFormField(
|
: textFormField(
|
||||||
onInput: onChangeFun,
|
onInput: onChangeFun,
|
||||||
@@ -52,6 +73,47 @@ class FormLabelTextField extends StatelessWidget {
|
|||||||
if (value != null && value.isEmpty) {
|
if (value != null && value.isEmpty) {
|
||||||
return localizations.translate(AppText.enterPhoneNo);
|
return localizations.translate(AppText.enterPhoneNo);
|
||||||
}
|
}
|
||||||
|
if (registerBloc.isdcode.isNotEmpty) {
|
||||||
|
// Validate phone number length based on selected country
|
||||||
|
if (countryPhoneLengths.containsKey(
|
||||||
|
registerBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength =
|
||||||
|
countryPhoneLengths[registerBloc.isdcode];
|
||||||
|
if (value.length != expectedLength) {
|
||||||
|
return localizations.translate(
|
||||||
|
"Invalid Phone Number",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (loginBloc.isdcode.isNotEmpty) {
|
||||||
|
// Validate phone number length based on selected country
|
||||||
|
if (countryPhoneLengths.containsKey(
|
||||||
|
loginBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength =
|
||||||
|
countryPhoneLengths[loginBloc.isdcode];
|
||||||
|
if (value.length != expectedLength) {
|
||||||
|
return localizations.translate(
|
||||||
|
"Invalid Phone Number",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (restorePasswordBloc.isdcode.isNotEmpty) {
|
||||||
|
// Validate phone number length based on selected country
|
||||||
|
if (countryPhoneLengths.containsKey(
|
||||||
|
restorePasswordBloc.isdcode,
|
||||||
|
)) {
|
||||||
|
final expectedLength =
|
||||||
|
countryPhoneLengths[restorePasswordBloc.isdcode];
|
||||||
|
if (value.length != expectedLength) {
|
||||||
|
return localizations.translate(
|
||||||
|
"Invalid Phone Number",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} else if (type == "country selection") {
|
} else if (type == "country selection") {
|
||||||
if (textEditingController.text.isEmpty) {
|
if (textEditingController.text.isEmpty) {
|
||||||
@@ -64,13 +126,38 @@ class FormLabelTextField extends StatelessWidget {
|
|||||||
.translate(AppText.pleaseEnteraDescription);
|
.translate(AppText.pleaseEnteraDescription);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
} else if (type == "email") {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Please enter an email address.';
|
||||||
|
}
|
||||||
|
// Email validation
|
||||||
|
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
|
||||||
|
return 'Please enter a valid email address.';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputFormatters: [
|
inputFormatters: (type == "phone number")
|
||||||
LengthLimitingTextInputFormatter(350),
|
? registerBloc.isdcode.isNotEmpty
|
||||||
],
|
? [
|
||||||
|
LengthLimitingTextInputFormatter(
|
||||||
|
countryPhoneLengths[registerBloc.isdcode]),
|
||||||
|
]
|
||||||
|
: restorePasswordBloc.isdcode.isNotEmpty
|
||||||
|
? [
|
||||||
|
LengthLimitingTextInputFormatter(
|
||||||
|
countryPhoneLengths[
|
||||||
|
restorePasswordBloc.isdcode]),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
LengthLimitingTextInputFormatter(
|
||||||
|
countryPhoneLengths[loginBloc.isdcode]),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
LengthLimitingTextInputFormatter(350),
|
||||||
|
],
|
||||||
maxlines: type == "description" ? 6 : 1,
|
maxlines: type == "description" ? 6 : 1,
|
||||||
texttype: type == "phone number"
|
texttype: type == "phone number"
|
||||||
? TextInputType.phone
|
? TextInputType.phone
|
||||||
|
|||||||
108
lib/shared/components/language_change_bottom_sheet.dart
Normal file
108
lib/shared/components/language_change_bottom_sheet.dart
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:tanami_app/core/routes/routes.dart';
|
||||||
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
|
import 'package:tanami_app/core/utils/secure/secure_storage_service.dart';
|
||||||
|
import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.dart';
|
||||||
|
import 'package:tanami_app/shared/components/text_widget.dart';
|
||||||
|
|
||||||
|
import 'bloc/language/lng_bloc.dart';
|
||||||
|
import 'bloc/language/lng_event.dart';
|
||||||
|
|
||||||
|
void showLanguageBottomSheet(BuildContext context) {
|
||||||
|
final SecureStorageService secureStorageService = SecureStorageService();
|
||||||
|
showModalBottomSheet(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 1.sw,
|
||||||
|
height: 168.7.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Colors.black87),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Gap(10),
|
||||||
|
Center(
|
||||||
|
child: TextWidget()
|
||||||
|
.text17W700("Language", clr: Colors.white60),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
const Divider(
|
||||||
|
color: AppColor.plainWhite,
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
context
|
||||||
|
.read<LocalizationBloc>()
|
||||||
|
.add(const ChangeLanguage(Locale('en')));
|
||||||
|
|
||||||
|
await secureStorageService.write(
|
||||||
|
'languageSelected', "en");
|
||||||
|
goRouter.pop();
|
||||||
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (_) => const WelcomeScreen()));
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child:
|
||||||
|
TextWidget().text15W700("English", clr: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
const Divider(
|
||||||
|
color: AppColor.plainWhite,
|
||||||
|
),
|
||||||
|
const Gap(10),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
context
|
||||||
|
.read<LocalizationBloc>()
|
||||||
|
.add(const ChangeLanguage(Locale('ar')));
|
||||||
|
|
||||||
|
await secureStorageService.write(
|
||||||
|
'languageSelected', "ar");
|
||||||
|
goRouter.pop();
|
||||||
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (_) => const WelcomeScreen()));
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: TextWidget().text15W700("عربي", clr: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(20),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(18),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
goRouter.pop();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 1.sw,
|
||||||
|
height: 56.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Colors.black87),
|
||||||
|
child: Center(
|
||||||
|
child:
|
||||||
|
TextWidget().text14W500("Dismiss", clr: Colors.white60),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(18),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -89,6 +89,9 @@ buildprofilelogoutdialog(context) {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
context.read<BottomNavigationBloc>().add(TabChanged(2));
|
context.read<BottomNavigationBloc>().add(TabChanged(2));
|
||||||
await secureStorageService.write('isLoginedIn', "false");
|
await secureStorageService.write('isLoginedIn', "false");
|
||||||
|
await secureStorageService.write('accesstoken', '');
|
||||||
|
await secureStorageService.write('refreshtoken', '');
|
||||||
|
|
||||||
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
goRouter.goNamed(RouteName.loginScreen, pathParameters: {
|
||||||
"fromScreen": "registerStep",
|
"fromScreen": "registerStep",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:control_style/control_style.dart';
|
import 'package:control_style/control_style.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@@ -15,8 +16,13 @@ import 'bloc/password_field/password_visibility_state.dart';
|
|||||||
class PasswordField extends StatelessWidget {
|
class PasswordField extends StatelessWidget {
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final String hintText;
|
final String hintText;
|
||||||
const PasswordField(
|
final TextEditingController? originalPasswordController;
|
||||||
{super.key, required this.controller, required this.hintText});
|
const PasswordField({
|
||||||
|
super.key,
|
||||||
|
required this.controller,
|
||||||
|
required this.hintText,
|
||||||
|
this.originalPasswordController,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -25,9 +31,31 @@ class PasswordField extends StatelessWidget {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return TextFormField(
|
return TextFormField(
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value != null && value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return localizations.translate(AppText.enterPassword);
|
return localizations.translate(AppText.enterPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Password validation rules
|
||||||
|
if (value.length < 8 || value.length > 20) {
|
||||||
|
return localizations.translate(AppText.passwordLength);
|
||||||
|
}
|
||||||
|
if (!RegExp(r'[a-z]').hasMatch(value)) {
|
||||||
|
return localizations.translate(AppText.passwordLowerCase);
|
||||||
|
}
|
||||||
|
if (!RegExp(r'[A-Z]').hasMatch(value)) {
|
||||||
|
return localizations.translate(AppText.passwordUpperCase);
|
||||||
|
}
|
||||||
|
if (!RegExp(r'\d').hasMatch(value)) {
|
||||||
|
return localizations.translate(AppText.passwordDigit);
|
||||||
|
}
|
||||||
|
if (!RegExp(r'[!@#$%&*()\-+=^]').hasMatch(value)) {
|
||||||
|
return localizations.translate(AppText.passwordSpecialCharacter);
|
||||||
|
}
|
||||||
|
if (originalPasswordController != null &&
|
||||||
|
value != originalPasswordController!.text) {
|
||||||
|
return localizations.translate("Passwords do not match");
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
controller: controller,
|
controller: controller,
|
||||||
@@ -38,7 +66,12 @@ class PasswordField extends StatelessWidget {
|
|||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
|
inputFormatters: [
|
||||||
|
LengthLimitingTextInputFormatter(20),
|
||||||
|
FilteringTextInputFormatter.deny(RegExp(r'\s')),
|
||||||
|
],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
errorMaxLines: 2,
|
||||||
errorStyle: GoogleFonts.dmSans(
|
errorStyle: GoogleFonts.dmSans(
|
||||||
color: AppColor.txtErrorColor,
|
color: AppColor.txtErrorColor,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
import 'package:tanami_app/Api_Helper/base_manager.dart';
|
||||||
import 'package:tanami_app/Globalconst.dart';
|
|
||||||
import 'package:tanami_app/core/styles/app_color.dart';
|
import 'package:tanami_app/core/styles/app_color.dart';
|
||||||
|
import 'package:tanami_app/shared/components/loader.dart';
|
||||||
|
|
||||||
import '../../core/routes/route_name.dart';
|
import '../../core/routes/route_name.dart';
|
||||||
import '../../core/routes/routes.dart';
|
import '../../core/routes/routes.dart';
|
||||||
@@ -85,16 +85,7 @@ permissionDialog(
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () {
|
||||||
Map<String, dynamic> biometricdata = {
|
|
||||||
"token": Globalconst.token,
|
|
||||||
"is_2FA_on": false
|
|
||||||
};
|
|
||||||
|
|
||||||
await RegisterAPIService()
|
|
||||||
.BiometricUpdate(biometricdata);
|
|
||||||
|
|
||||||
successToastMessage(context, "successful !");
|
|
||||||
goRouter.pop();
|
goRouter.pop();
|
||||||
|
|
||||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
||||||
@@ -119,24 +110,29 @@ permissionDialog(
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
Loader.loader(context);
|
||||||
Map<String, dynamic> biometricdata = {
|
Map<String, dynamic> biometricdata = {
|
||||||
"token": Globalconst.token,
|
"token":
|
||||||
|
await secureStorageService.read("temp_token"),
|
||||||
"is_2FA_on": true
|
"is_2FA_on": true
|
||||||
};
|
};
|
||||||
|
|
||||||
ResponseData response = await RegisterAPIService()
|
ResponseData response = await RegisterAPIService()
|
||||||
.BiometricUpdate(biometricdata);
|
.BiometricUpdate(biometricdata);
|
||||||
if (response.status == ResponseStatus.SUCCESS) {
|
if (response.status == ResponseStatus.SUCCESS) {
|
||||||
await secureStorageService.write("biometric", 'on');
|
goRouter.pop();
|
||||||
}
|
|
||||||
successToastMessage(
|
|
||||||
context, "Biometric/Face Id Enabled Sucessfully !");
|
|
||||||
// successToastMessage(context, "successful !");
|
|
||||||
goRouter.pop();
|
|
||||||
|
|
||||||
goRouter.goNamed(RouteName.pinScreen, pathParameters: {
|
await secureStorageService.write("biometric", 'on');
|
||||||
"fromScreen": "register",
|
successToastMessage(context,
|
||||||
});
|
"Biometric/Face Id Enabled Sucessfully !");
|
||||||
|
// successToastMessage(context, "successful !");
|
||||||
|
goRouter.pop();
|
||||||
|
|
||||||
|
goRouter
|
||||||
|
.goNamed(RouteName.pinScreen, pathParameters: {
|
||||||
|
"fromScreen": "register",
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 48.h,
|
height: 48.h,
|
||||||
|
|||||||
Reference in New Issue
Block a user