api integration

This commit is contained in:
jayesh
2024-07-19 16:20:14 +05:30
parent 948777ee21
commit 4e768e6f6a
44 changed files with 166 additions and 113 deletions

View File

@@ -5,4 +5,5 @@ class Globalconst {
static String isdcode = ""; static String isdcode = "";
static String createdpin = ""; static String createdpin = "";
static String firstName = ""; static String firstName = "";
static String languageSelected = "en";
} }

View File

@@ -2,10 +2,11 @@ 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/Globalconst.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/features/biometric/domain/repository/biometric_api.dart'; import 'package:tanami_app/features/biometric/domain/repository/biometric_api.dart';
import '../../../../Api_Helper/base_manager.dart'; import '../../../Api_Helper/base_manager.dart';
import 'biometric_event.dart'; import 'biometric_event.dart';
import 'biometric_state.dart'; import 'biometric_state.dart';
@@ -33,7 +34,9 @@ class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
bool authenticated = false; bool authenticated = false;
if (Platform.isIOS) { if (Platform.isIOS) {
authenticated = await localAuthentication.authenticate( authenticated = await localAuthentication.authenticate(
localizedReason: 'Please authenticate to access the app', localizedReason: Globalconst.languageSelected == "en"
? 'Please authenticate to access the app'
: 'يرجى المصادقة للوصول إلى التطبيق',
options: const AuthenticationOptions( options: const AuthenticationOptions(
useErrorDialogs: true, useErrorDialogs: true,
stickyAuth: true, stickyAuth: true,
@@ -42,7 +45,9 @@ class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
); );
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
authenticated = await localAuthentication.authenticate( authenticated = await localAuthentication.authenticate(
localizedReason: 'Please authenticate to access the app', localizedReason: Globalconst.languageSelected == "en"
? 'Please authenticate to access the app'
: 'يرجى المصادقة للوصول إلى التطبيق',
options: const AuthenticationOptions( options: const AuthenticationOptions(
useErrorDialogs: true, useErrorDialogs: true,
stickyAuth: true, stickyAuth: true,
@@ -64,10 +69,18 @@ class BiometricBloc extends Bloc<BiometricEvent, BiometricState> {
'refreshtoken', response.data["data"]["refreshToken"]); 'refreshtoken', response.data["data"]["refreshToken"]);
emit(BiometricAuthenticated()); emit(BiometricAuthenticated());
} else { } else {
emit(BiometricFailed('Authentication failed')); if (Globalconst.languageSelected == "en") {
emit(BiometricFailed('Authentication failed'));
} else {
emit(BiometricFailed('المصادقة فشلت'));
}
} }
} else { } else {
emit(BiometricFailed('Authentication failed')); if (Globalconst.languageSelected == "en") {
emit(BiometricFailed('Authentication failed'));
} else {
emit(BiometricFailed('المصادقة فشلت'));
}
} }
} catch (e) { } catch (e) {
emit(BiometricFailed(e.toString())); emit(BiometricFailed(e.toString()));

View File

@@ -10,9 +10,9 @@ import '../../../../core/routes/route_name.dart';
import '../../../../core/routes/routes.dart'; import '../../../../core/routes/routes.dart';
import '../../../../core/styles/app_images.dart'; import '../../../../core/styles/app_images.dart';
import '../../../../shared/components/device_locked_dialog.dart'; import '../../../../shared/components/device_locked_dialog.dart';
import '../bloc/biometric_bloc.dart'; import '../../bloc/biometric_bloc.dart';
import '../bloc/biometric_event.dart'; import '../../bloc/biometric_event.dart';
import '../bloc/biometric_state.dart'; import '../../bloc/biometric_state.dart';
class BiometricLayout extends StatelessWidget { class BiometricLayout extends StatelessWidget {
const BiometricLayout({super.key}); const BiometricLayout({super.key});

View File

@@ -6,7 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
import '../../../../core/styles/app_color.dart'; 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 '../bloc/change_password_bloc.dart'; import '../../bloc/change_password_bloc.dart';
import 'change_password_layout.dart'; import 'change_password_layout.dart';
class ChangePasswordScreen extends StatelessWidget { class ChangePasswordScreen extends StatelessWidget {

View File

@@ -10,9 +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 '../bloc/change_password_bloc.dart'; import '../../bloc/change_password_bloc.dart';
import '../bloc/change_password_event.dart'; import '../../bloc/change_password_event.dart';
import '../bloc/change_password_state.dart'; import '../../bloc/change_password_state.dart';
class RestorePasswordBottomSection extends StatelessWidget { class RestorePasswordBottomSection extends StatelessWidget {
const RestorePasswordBottomSection({ const RestorePasswordBottomSection({

View File

@@ -11,7 +11,7 @@ import '../../../../shared/components/bloc/password_field/password_visibility_bl
import '../../../../shared/components/button_widget.dart'; import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/form_label_textfield.dart'; import '../../../../shared/components/form_label_textfield.dart';
import '../../../../shared/components/text_widget.dart'; import '../../../../shared/components/text_widget.dart';
import '../bloc/change_password_bloc.dart'; import '../../bloc/change_password_bloc.dart';
class RestorePasswordForm extends StatelessWidget { class RestorePasswordForm extends StatelessWidget {
const RestorePasswordForm({super.key}); const RestorePasswordForm({super.key});

View File

@@ -2,6 +2,7 @@ import 'package:bloc/bloc.dart';
import 'package:tanami_app/features/countrySelection/bloc/GetCountry/get_country_event.dart'; import 'package:tanami_app/features/countrySelection/bloc/GetCountry/get_country_event.dart';
import '../../../../Api_Helper/base_manager.dart'; import '../../../../Api_Helper/base_manager.dart';
import '../../../../Globalconst.dart';
import '../../domain/model/get_country_model.dart'; import '../../domain/model/get_country_model.dart';
import '../../repositories/get_country_api.dart'; import '../../repositories/get_country_api.dart';
import 'get_country_state.dart'; import 'get_country_state.dart';
@@ -20,7 +21,9 @@ class GetCountryBlock extends Bloc<GetCountryEvent, GetCountryState> {
emit(CountryLoaded(countryModel)); emit(CountryLoaded(countryModel));
} }
} catch (e) { } catch (e) {
emit(CountryError("Oops Something went wrong")); emit(CountryError(Globalconst.languageSelected == "en"
? 'Oops Something went wrong'
: "تبا شيء ما حدث بشكل خاطئ"));
} }
} }
} }

View File

@@ -4,8 +4,8 @@ import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tanami_app/Globalconst.dart'; import 'package:tanami_app/Globalconst.dart';
import '../../../../Api_Helper/base_manager.dart'; import '../../../Api_Helper/base_manager.dart';
import '../../domain/repository/forgot_password_api.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';

View File

@@ -2,9 +2,9 @@ import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tanami_app/Globalconst.dart'; import 'package:tanami_app/Globalconst.dart';
import '../../../../Api_Helper/base_manager.dart'; import '../../../Api_Helper/base_manager.dart';
import '../../../../core/utils/secure/secure_storage_service.dart'; import '../../../core/utils/secure/secure_storage_service.dart';
import '../../domain/repository/forgot_password_api.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';

View File

@@ -5,7 +5,7 @@ import 'package:tanami_app/features/forgotPassword/presentation/pages/restore_pa
import '../../../../core/styles/app_color.dart'; import '../../../../core/styles/app_color.dart';
import '../../../countrySelection/bloc/choose_country_bloc.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 {
const RestorePasswordPhoneVerificationScreen({super.key}); const RestorePasswordPhoneVerificationScreen({super.key});

View File

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../core/styles/app_color.dart'; import '../../../../core/styles/app_color.dart';
import '../bloc/restore_password_bloc.dart'; import '../../bloc/restore_password_bloc.dart';
import 'restore_password_layout.dart'; import 'restore_password_layout.dart';
class RestorePasswordScreen extends StatelessWidget { class RestorePasswordScreen extends StatelessWidget {

View File

@@ -13,9 +13,9 @@ import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart'; import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart'; import '../../../../shared/components/text_widget.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart'; import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/restore_password_bloc.dart'; import '../../bloc/restore_password_bloc.dart';
import '../bloc/restore_password_event.dart'; import '../../bloc/restore_password_event.dart';
import '../bloc/restore_password_state.dart'; import '../../bloc/restore_password_state.dart';
class RestorePasswordBottomSection extends StatelessWidget { class RestorePasswordBottomSection extends StatelessWidget {
const RestorePasswordBottomSection({ const RestorePasswordBottomSection({

View File

@@ -2,7 +2,7 @@ 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/styles/app_text.dart'; import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/features/forgotPassword/presentation/bloc/restore_password_bloc.dart'; import 'package:tanami_app/features/forgotPassword/bloc/restore_password_bloc.dart';
import '../../../../core/utils/language/localizations_delegate.dart'; import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart'; import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';

View File

@@ -13,9 +13,9 @@ import '../../../../core/utils/language/localizations_delegate.dart';
import '../../../../shared/components/button_widget.dart'; import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart'; import '../../../../shared/components/text_widget.dart';
import '../../../countrySelection/bloc/choose_country_bloc.dart'; import '../../../countrySelection/bloc/choose_country_bloc.dart';
import '../bloc/restore_password_phone_verification_bloc.dart'; import '../../bloc/restore_password_phone_verification_bloc.dart';
import '../bloc/restore_password_phone_verification_event.dart'; import '../../bloc/restore_password_phone_verification_event.dart';
import '../bloc/restore_password_phone_verification_state.dart'; import '../../bloc/restore_password_phone_verification_state.dart';
class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget { class RestorePasswordPhoneVerificationBottomSection extends StatelessWidget {
const RestorePasswordPhoneVerificationBottomSection({ const RestorePasswordPhoneVerificationBottomSection({

View File

@@ -15,7 +15,7 @@ import '../../../countrySelection/bloc/GetCountry/get_country_bloc.dart';
import '../../../countrySelection/bloc/GetCountry/get_country_state.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';
class RestorePasswordPhoneVerificationForm extends StatelessWidget { class RestorePasswordPhoneVerificationForm extends StatelessWidget {
const RestorePasswordPhoneVerificationForm({super.key}); const RestorePasswordPhoneVerificationForm({super.key});

View File

@@ -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:gap/gap.dart'; import 'package:gap/gap.dart';
import '../../../../Globalconst.dart';
import '../../../../core/routes/routes.dart'; import '../../../../core/routes/routes.dart';
import '../../../../core/styles/app_color.dart'; import '../../../../core/styles/app_color.dart';
import '../../../../core/styles/app_text.dart'; import '../../../../core/styles/app_text.dart';
@@ -37,8 +38,10 @@ Widget bottomSection(BuildContext context) {
context.read<LocalizationBloc>().add(ChangeLanguage(newLocale)); context.read<LocalizationBloc>().add(ChangeLanguage(newLocale));
if (radioBloc.selectedCountry == 1) { if (radioBloc.selectedCountry == 1) {
await secureStorageService.write('languageSelected', "ar"); await secureStorageService.write('languageSelected', "ar");
Globalconst.languageSelected = "ar";
} else { } else {
await secureStorageService.write('languageSelected', "en"); await secureStorageService.write('languageSelected', "en");
Globalconst.languageSelected = "en";
} }
goRouter.pop(); goRouter.pop();
}, },

View File

@@ -29,8 +29,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
on<LoginSubmitted>((event, emit) async { on<LoginSubmitted>((event, emit) async {
if (!formKey.currentState!.validate()) { if (!formKey.currentState!.validate()) {
emit(LoginLoading()); emit(LoginLoading());
emit( emit(LoginFailure(Globalconst.languageSelected == "en"
const LoginFailure("Login failed. Please check your credentials.")); ? "Login failed. Please check your credentials."
: "فشل تسجيل الدخول. يرجى التحقق من بيانات الاعتماد الخاصة بك."));
return; return;
} }
emit(LoginLoading()); emit(LoginLoading());
@@ -58,8 +59,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
emit(LoginFailure(response.message.toString())); emit(LoginFailure(response.message.toString()));
} }
} else { } else {
emit(const LoginFailure( emit(LoginFailure(response.message.toString()));
"Login failed. Please check your credentials."));
} }
} catch (e) { } catch (e) {
emit(LoginFailure(e.toString())); emit(LoginFailure(e.toString()));

View File

@@ -16,6 +16,7 @@ class LoginScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final SecureStorageService secureStorageService = SecureStorageService(); final SecureStorageService secureStorageService = SecureStorageService();
final radioBloc = context.read<RadioBloc>(); final radioBloc = context.read<RadioBloc>();
return WillPopScope( return WillPopScope(
onWillPop: () async { onWillPop: () async {
if (fromScreen == "welcome" || if (fromScreen == "welcome" ||

View File

@@ -59,6 +59,7 @@ class BottomSection extends StatelessWidget {
successToastMessage(context, "login successful !"); successToastMessage(context, "login successful !");
goRouter.pop(); goRouter.pop();
radioBloc.resetSelection(); radioBloc.resetSelection();
loginbloc.resetFields();
await secureStorageService.write('isLoginedIn', "true"); await secureStorageService.write('isLoginedIn', "true");
goRouter.pushNamed(RouteName.pinScreen, pathParameters: { goRouter.pushNamed(RouteName.pinScreen, pathParameters: {
"fromScreen": "fromScreen":

View File

@@ -197,7 +197,7 @@ class LoginForm extends StatelessWidget {
child: FormLabelTextField( child: FormLabelTextField(
hintText: localizations.translate(AppText.enterPassword), hintText: localizations.translate(AppText.enterPassword),
title: localizations.translate(AppText.password), title: localizations.translate(AppText.password),
type: "password", type: "login-password",
textEditingController: loginBloc.passwordTextField, textEditingController: loginBloc.passwordTextField,
), ),
), ),

View File

@@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import '../../../Api_Helper/base_manager.dart'; import '../../../Api_Helper/base_manager.dart';
import '../../../Globalconst.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';
@@ -19,10 +20,12 @@ class OTPBloc extends Bloc<OTPEvent, OTPState> {
if (response.status == ResponseStatus.SUCCESS) { if (response.status == ResponseStatus.SUCCESS) {
emit(OTPLoaded()); emit(OTPLoaded());
} else { } else {
emit(OTPFailed("Oops something went wrong")); emit(OTPFailed(response.message.toString()));
} }
} catch (e) { } catch (e) {
emit(OTPError("Oops something went wrong")); emit(OTPError(Globalconst.languageSelected == "en"
? "تبا شيء ما حدث بشكل خاطئ"
: ""));
} }
} }
} }

View File

@@ -1,6 +1,7 @@
// timer_bloc.dart
import 'dart:async'; import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'timer_event.dart'; import 'timer_event.dart';
import 'timer_state.dart'; import 'timer_state.dart';
@@ -13,7 +14,7 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
} }
void _onStartTimer(StartTimer event, Emitter<TimerState> emit) { void _onStartTimer(StartTimer event, Emitter<TimerState> emit) {
const int duration = 300; // 5 minutes in seconds const int duration = 30; // 5 minutes in seconds
emit(const TimerRunInProgress(duration)); emit(const TimerRunInProgress(duration));
_startTicker(duration); _startTicker(duration);
} }

View File

@@ -1,4 +1,5 @@
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:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:sms_autofill/sms_autofill.dart'; import 'package:sms_autofill/sms_autofill.dart';
@@ -63,6 +64,8 @@ class OtpFillSection extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
PinFieldAutoFill( PinFieldAutoFill(
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
controller: otpBloc.otpController, controller: otpBloc.otpController,
currentCode: otpBloc.otpController.text, currentCode: otpBloc.otpController.text,
decoration: BoxLooseDecoration( decoration: BoxLooseDecoration(

View File

@@ -14,6 +14,7 @@ import '../../../register/presentation/bloc/register_bloc.dart';
import '../../../register/presentation/bloc/register_event.dart'; import '../../../register/presentation/bloc/register_event.dart';
import '../../../register/presentation/bloc/register_state.dart'; import '../../../register/presentation/bloc/register_state.dart';
import '../bloc/timer/timer_bloc.dart'; import '../bloc/timer/timer_bloc.dart';
import '../bloc/timer/timer_event.dart';
import '../bloc/timer/timer_state.dart'; import '../bloc/timer/timer_state.dart';
class ResendOtpSection extends StatelessWidget { class ResendOtpSection extends StatelessWidget {
@@ -49,6 +50,7 @@ class ResendOtpSection extends StatelessWidget {
if (state is RegisterLoading) { if (state is RegisterLoading) {
Loader.loader(context); Loader.loader(context);
} else if (state is RegisterSuccess) { } else if (state is RegisterSuccess) {
context.read<TimerBloc>().add(StartTimer()); // Reset timer
successToastMessage(context, "OTP Resend Sucessfully !"); successToastMessage(context, "OTP Resend Sucessfully !");
goRouter.pop(); goRouter.pop();
} else if (state is RegisterFailure) { } else if (state is RegisterFailure) {
@@ -75,13 +77,13 @@ class ResendOtpSection extends StatelessWidget {
Resendotp(token), Resendotp(token),
); );
} else { } else {
errorToastMessage(context, // errorToastMessage(context,
"Please wait ${timerState.formattedDuration} Minutes before resending OTP"); // "Please wait ${timerState.formattedDuration} Seconds before resending OTP");
} }
}, },
child: TextWidget().text14W500( child: TextWidget().text14W500(
localizations.translate(AppText.resendSms), localizations.translate(AppText.resendSms),
clr: isButtonEnabled clr: timerState is TimerRunComplete
? AppColor.plainBlack ? AppColor.plainBlack
: AppColor.indicatorInactiveColor, : AppColor.indicatorInactiveColor,
textDecoration: TextDecoration.underline, textDecoration: TextDecoration.underline,

View File

@@ -59,8 +59,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
if (response.status == ResponseStatus.SUCCESS) { if (response.status == ResponseStatus.SUCCESS) {
emit(RegisterSuccess(event.token)); //emit(OTPLoaded()); emit(RegisterSuccess(event.token)); //emit(OTPLoaded());
} else { } else {
emit(const RegisterFailure( emit(RegisterFailure(response.message.toString()));
"Register failed. Please check your credentials."));
//emit(OTPFailed("Oops something went wrong")); //emit(OTPFailed("Oops something went wrong"));
} }
} catch (e) { } catch (e) {

View File

@@ -51,22 +51,6 @@ class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
} else { } else {
emit(RegisterUserFailure(response.message)); emit(RegisterUserFailure(response.message));
} }
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
// Replace the next line with actual API call
/* final isSuccess = await _mockLoginApi(
event.firstName,
event.password,
event.lastName,
event.confirmPassword,
event.email,
);
if (isSuccess) {
emit(RegisterUserSuccess());
} else {
emit(const RegisterUserFailure(
"Register failed. Please check your credentials."));
} */
} catch (e) { } catch (e) {
emit(RegisterUserFailure(e.toString())); emit(RegisterUserFailure(e.toString()));
} }

View File

@@ -31,14 +31,14 @@ class RegisterUserForm extends StatelessWidget {
FormLabelTextField( FormLabelTextField(
hintText: localizations.translate(AppText.enterFirstName), hintText: localizations.translate(AppText.enterFirstName),
title: localizations.translate(AppText.firstNameText), title: localizations.translate(AppText.firstNameText),
type: localizations.translate(AppText.firstNameText), type: "first name",
textEditingController: registerUserBloc.firstNameTextField, textEditingController: registerUserBloc.firstNameTextField,
), ),
const Gap(12), const Gap(12),
FormLabelTextField( FormLabelTextField(
hintText: localizations.translate(AppText.enterLastName), hintText: localizations.translate(AppText.enterLastName),
title: localizations.translate(AppText.lastNameText), title: localizations.translate(AppText.lastNameText),
type: AppText.lastNameText, type: "first name",
textEditingController: registerUserBloc.lastNameTextField, textEditingController: registerUserBloc.lastNameTextField,
), ),
const Gap(12), const Gap(12),

View File

@@ -3,6 +3,7 @@ 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/core/styles/app_text.dart'; import 'package:tanami_app/core/styles/app_text.dart';
import '../../../../Globalconst.dart';
import '../../../../core/routes/routes.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';
@@ -109,9 +110,9 @@ class PinBloc extends Bloc<PinEvent, PinState> {
ResponseData response = await PinAPIServices().Verifypin(pindata); ResponseData response = await PinAPIServices().Verifypin(pindata);
if (response.status == ResponseStatus.SUCCESS) { if (response.status == ResponseStatus.SUCCESS) {
await secureStorageService.write( await secureStorageService.write(
'accesstoken', response.data["data"]["accessToken"]); 'accesstoken', response.data["user"]["accessToken"]);
await secureStorageService.write( await secureStorageService.write(
'refreshtoken', response.data["data"]["refreshToken"]); 'refreshtoken', response.data["user"]["refreshToken"]);
emit(state.copyWith( emit(state.copyWith(
pinComplete: true, pinComplete: true,
pin: state.pin, pin: state.pin,
@@ -124,7 +125,9 @@ class PinBloc extends Bloc<PinEvent, PinState> {
pinComplete: true, pinComplete: true,
pin: state.pin, pin: state.pin,
isVerified: false, isVerified: false,
error: "Incorrect Pin Code", error: Globalconst.languageSelected == "en"
? "Incorrect Pin Code"
: "رمز التعريف الشخصي غير صحيح",
verifiedOnce: true, verifiedOnce: true,
)); ));
} }

View File

@@ -89,10 +89,12 @@ class PinKey extends StatelessWidget {
); );
}, },
), ),
(fromScreen == "login" || fromScreen == "forgot-pin") (fromScreen == "login" ||
fromScreen == "forgot-pin" ||
fromScreen == "LoginedInUser")
? const Gap(20) ? const Gap(20)
: const Gap(0), : const Gap(0),
(fromScreen == "login") (fromScreen == "login" || fromScreen == "LoginedInUser")
? GestureDetector( ? GestureDetector(
onTap: () { onTap: () {
forgotPinDialog(context); forgotPinDialog(context);

View File

@@ -4,17 +4,18 @@ 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/Globalconst.dart';
import 'package:tanami_app/features/login/presentation/bloc/login_bloc.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';
import 'core/utils/language/localizations_delegate.dart'; import 'core/utils/language/localizations_delegate.dart';
import 'core/utils/secure/secure_storage_service.dart'; import 'core/utils/secure/secure_storage_service.dart';
import 'features/biometric/presentation/bloc/biometric_bloc.dart'; import 'features/biometric/bloc/biometric_bloc.dart';
import 'features/biometric/presentation/bloc/biometric_event.dart'; import 'features/biometric/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/forgotPassword/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 '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';
@@ -136,14 +137,17 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
context context
.read<LocalizationBloc>() .read<LocalizationBloc>()
.add(const ChangeLanguage(Locale('en'))); .add(const ChangeLanguage(Locale('en')));
Globalconst.languageSelected = "en";
} else if (languageSelected == "en") { } else if (languageSelected == "en") {
context context
.read<LocalizationBloc>() .read<LocalizationBloc>()
.add(const ChangeLanguage(Locale('en'))); .add(const ChangeLanguage(Locale('en')));
Globalconst.languageSelected = "en";
} else { } else {
context context
.read<LocalizationBloc>() .read<LocalizationBloc>()
.add(const ChangeLanguage(Locale('ar'))); .add(const ChangeLanguage(Locale('ar')));
Globalconst.languageSelected = "ar";
} }
}, },
); );

View File

@@ -9,7 +9,7 @@ class NetworkApiService {
final Dio _dio = Dio(BaseOptions( final Dio _dio = Dio(BaseOptions(
validateStatus: (status) { validateStatus: (status) {
return status != null && return status != null &&
status < 500; // Allow any status code less than 500 status <= 500; // Allow any status code less than 500
}, },
)); ));
@@ -25,6 +25,14 @@ class NetworkApiService {
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);
} else if (response.statusCode == 500) {
return ResponseData<dynamic>(
"Internal server error", ResponseStatus.PRIVATE,
data: response.data);
} else if (response.statusCode == 400) {
return ResponseData<dynamic>(
response.data['message'], ResponseStatus.PRIVATE,
data: response.data);
} else { } else {
try { try {
return ResponseData<dynamic>( return ResponseData<dynamic>(
@@ -80,6 +88,10 @@ class NetworkApiService {
return ResponseData<dynamic>( return ResponseData<dynamic>(
response.data['error']['message'], ResponseStatus.PRIVATE, response.data['error']['message'], ResponseStatus.PRIVATE,
data: response.data); data: response.data);
} else if (response.statusCode == 500) {
return ResponseData<dynamic>(
"Internal server error", ResponseStatus.PRIVATE,
data: response.data);
} else { } else {
try { try {
return ResponseData<dynamic>( return ResponseData<dynamic>(

View File

@@ -6,13 +6,13 @@ 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/core/utils/secure/secure_storage_service.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/bloc/biometric_bloc.dart';
import '../../Globalconst.dart'; import '../../Globalconst.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/biometric/presentation/bloc/biometric_state.dart'; import '../../features/biometric/bloc/biometric_state.dart';
import 'text_widget.dart'; import 'text_widget.dart';
deviceLockedDialog( deviceLockedDialog(

View File

@@ -11,7 +11,7 @@ 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/forgotPassword/bloc/restore_password_phone_verification_bloc.dart';
import '../../features/register/presentation/bloc/register_bloc.dart'; import '../../features/register/presentation/bloc/register_bloc.dart';
import 'text_from_field_widget.dart'; import 'text_from_field_widget.dart';
@@ -60,11 +60,14 @@ 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 == "repeat-password") (type == "password" ||
type == "repeat-password" ||
type == "login-password")
? PasswordField( ? PasswordField(
controller: textEditingController, controller: textEditingController,
hintText: hintText, hintText: hintText,
originalPasswordController: originalPasswordController, originalPasswordController: originalPasswordController,
type: type,
) )
: textFormField( : textFormField(
onInput: onChangeFun, onInput: onChangeFun,
@@ -139,25 +142,29 @@ class FormLabelTextField extends StatelessWidget {
return null; return null;
} }
}, },
inputFormatters: (type == "phone number") inputFormatters: (type == "first name")
? registerBloc.isdcode.isNotEmpty ? [
? [ LengthLimitingTextInputFormatter(35),
LengthLimitingTextInputFormatter( ]
countryPhoneLengths[registerBloc.isdcode]), : (type == "phone number")
] ? registerBloc.isdcode.isNotEmpty
: restorePasswordBloc.isdcode.isNotEmpty
? [ ? [
LengthLimitingTextInputFormatter( LengthLimitingTextInputFormatter(
countryPhoneLengths[ countryPhoneLengths[registerBloc.isdcode]),
restorePasswordBloc.isdcode]),
] ]
: [ : restorePasswordBloc.isdcode.isNotEmpty
LengthLimitingTextInputFormatter( ? [
countryPhoneLengths[loginBloc.isdcode]), LengthLimitingTextInputFormatter(
] countryPhoneLengths[
: [ restorePasswordBloc.isdcode]),
LengthLimitingTextInputFormatter(350), ]
], : [
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

View File

@@ -8,6 +8,7 @@ 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/features/welcome/presentation/pages/weclome_screen.dart';
import 'package:tanami_app/shared/components/text_widget.dart'; import 'package:tanami_app/shared/components/text_widget.dart';
import '../../Globalconst.dart';
import 'bloc/language/lng_bloc.dart'; import 'bloc/language/lng_bloc.dart';
import 'bloc/language/lng_event.dart'; import 'bloc/language/lng_event.dart';
@@ -49,6 +50,7 @@ void showLanguageBottomSheet(BuildContext context) {
await secureStorageService.write( await secureStorageService.write(
'languageSelected', "en"); 'languageSelected', "en");
goRouter.pop(); goRouter.pop();
Globalconst.languageSelected = "en";
Navigator.of(context).push(MaterialPageRoute( Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const WelcomeScreen())); builder: (_) => const WelcomeScreen()));
}, },
@@ -67,7 +69,7 @@ void showLanguageBottomSheet(BuildContext context) {
context context
.read<LocalizationBloc>() .read<LocalizationBloc>()
.add(const ChangeLanguage(Locale('ar'))); .add(const ChangeLanguage(Locale('ar')));
Globalconst.languageSelected = "ar";
await secureStorageService.write( await secureStorageService.write(
'languageSelected', "ar"); 'languageSelected', "ar");
goRouter.pop(); goRouter.pop();

View File

@@ -17,11 +17,13 @@ class PasswordField extends StatelessWidget {
final TextEditingController controller; final TextEditingController controller;
final String hintText; final String hintText;
final TextEditingController? originalPasswordController; final TextEditingController? originalPasswordController;
final String? type;
const PasswordField({ const PasswordField({
super.key, super.key,
required this.controller, required this.controller,
required this.hintText, required this.hintText,
this.originalPasswordController, this.originalPasswordController,
this.type,
}); });
@override @override
@@ -31,29 +33,36 @@ class PasswordField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return TextFormField( return TextFormField(
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (type == "login-password") {
return localizations.translate(AppText.enterPassword); if (value == null || value.isEmpty) {
} return localizations.translate(AppText.enterPassword);
}
} else {
if (value == null || value.isEmpty) {
return localizations.translate(AppText.enterPassword);
}
// Password validation rules // Password validation rules
if (value.length < 8 || value.length > 20) { if (value.length < 8 || value.length > 20) {
return localizations.translate(AppText.passwordLength); return localizations.translate(AppText.passwordLength);
} }
if (!RegExp(r'[a-z]').hasMatch(value)) { if (!RegExp(r'[a-z]').hasMatch(value)) {
return localizations.translate(AppText.passwordLowerCase); return localizations.translate(AppText.passwordLowerCase);
} }
if (!RegExp(r'[A-Z]').hasMatch(value)) { if (!RegExp(r'[A-Z]').hasMatch(value)) {
return localizations.translate(AppText.passwordUpperCase); return localizations.translate(AppText.passwordUpperCase);
} }
if (!RegExp(r'\d').hasMatch(value)) { if (!RegExp(r'\d').hasMatch(value)) {
return localizations.translate(AppText.passwordDigit); return localizations.translate(AppText.passwordDigit);
} }
if (!RegExp(r'[!@#$%&*()\-+=^]').hasMatch(value)) { if (!RegExp(r'[!@#$%&*()\-+=^]').hasMatch(value)) {
return localizations.translate(AppText.passwordSpecialCharacter); return localizations
} .translate(AppText.passwordSpecialCharacter);
if (originalPasswordController != null && }
value != originalPasswordController!.text) { if (originalPasswordController != null &&
return localizations.translate("Passwords do not match"); value != originalPasswordController!.text) {
return localizations.translate("Passwords do not match");
}
} }
return null; return null;