feat: auth done

This commit is contained in:
jahongireshonqulov
2025-10-30 14:41:55 +05:00
parent f47e78a9a2
commit ab1ac6e6fa
26 changed files with 1702 additions and 195 deletions

View File

@@ -183,7 +183,21 @@
"example": "Uber" "example": "Uber"
} }
} }
},
"otp_code_incomplete": "Code is incomplete. Please enter the full code.",
"passwords_do_not_match": "Passwords do not match.",
"reset_password": "Reset password",
"new_password": "New password",
"enter_otp_code": "Enter the 5-digit code sent to you at {phoneNumber}",
"@enter_otp_code":{
"placeholders": {
"phoneNumber": {
"type": "String"
} }
}
},
"resend_otp_after": "You can resend OTP after"

View File

@@ -178,7 +178,20 @@
"example": "Uber" "example": "Uber"
} }
} }
},
"otp_code_incomplete": "Код неполный. Пожалуйста, введите полный код.",
"passwords_do_not_match": "Пароли не совпадают.",
"reset_password": "Восстановить пароль",
"new_password": "Новый пароль",
"enter_otp_code": "Введите 5-значный код, отправленный на номер {phoneNumber}",
"@enter_otp_code":{
"placeholders": {
"phoneNumber": {
"type": "String"
} }
}
},
"resend_otp_after": "Вы можете повторно отправить код через"

View File

@@ -178,7 +178,20 @@
"example": "Uber" "example": "Uber"
} }
} }
},
"otp_code_incomplete": "Kod yetarli emas. Iltimos, toliq kodni kiriting.",
"passwords_do_not_match": "Parollar mos kelmadi.",
"reset_password": "Parolni qayta tiklash",
"new_password": "Yangi parol",
"enter_otp_code": "{phoneNumber} raqamiga yuborilgan 5 xonali kodni kiriting",
"@enter_otp_code":{
"placeholders": {
"phoneNumber": {
"type": "String"
} }
}
},
"resend_otp_after": "OTP kodni qayta yuborish mumkin boladi"

View File

@@ -30,6 +30,10 @@ import '../../feature/auth/domain/usecases/verify_phone_register_usecase.dart'
as _i664; as _i664;
import '../../feature/auth/presentation/blocs/login_bloc/login_bloc.dart' import '../../feature/auth/presentation/blocs/login_bloc/login_bloc.dart'
as _i1065; as _i1065;
import '../../feature/auth/presentation/blocs/register_bloc/register_bloc.dart'
as _i1050;
import '../../feature/auth/presentation/blocs/reset_password_bloc/reset_password_bloc.dart'
as _i97;
import '../../feature/auth/presentation/blocs/verify_otp_bloc/verify_otp_bloc.dart' import '../../feature/auth/presentation/blocs/verify_otp_bloc/verify_otp_bloc.dart'
as _i323; as _i323;
import '../../feature/auth/presentation/blocs/verify_phone_bloc/verify_phone_bloc.dart' import '../../feature/auth/presentation/blocs/verify_phone_bloc/verify_phone_bloc.dart'
@@ -119,6 +123,12 @@ extension GetItInjectableX on _i174.GetIt {
gh<_i664.VerifyPhoneRegisterUseCase>(), gh<_i664.VerifyPhoneRegisterUseCase>(),
), ),
); );
gh.factory<_i1050.RegisterBloc>(
() => _i1050.RegisterBloc(gh<_i607.RegisterUseCase>()),
);
gh.factory<_i97.ResetPasswordBloc>(
() => _i97.ResetPasswordBloc(gh<_i694.ResetPasswordUseCase>()),
);
gh.factory<_i1065.LoginBloc>( gh.factory<_i1065.LoginBloc>(
() => _i1065.LoginBloc( () => _i1065.LoginBloc(
gh<_i241.LoginUseCase>(), gh<_i241.LoginUseCase>(),

View File

@@ -19,10 +19,31 @@ abstract class Validators {
return null; return null;
} }
static String? validateRepeatPassword(
String repeatPassword,
String password,
) {
if (repeatPassword.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty;
} else if (repeatPassword != password) {
return navigatorKey.currentContext?.loc.passwords_do_not_match;
}
return null;
}
static String? validateFields(String value) { static String? validateFields(String value) {
if (value.isEmpty) { if (value.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty; return navigatorKey.currentContext?.loc.field_cannot_be_empty;
} }
return null; return null;
} }
static String? validateOtpFields(String value) {
if (value.isEmpty) {
return navigatorKey.currentContext?.loc.field_cannot_be_empty;
} else if (value.length < 5) {
return navigatorKey.currentContext?.loc.otp_code_incomplete;
}
return null;
}
} }

View File

@@ -867,6 +867,42 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'By proceeding, you consent to get calls or SMS messages, including by automated means, from {appName} and its affiliates to the number provided.'** /// **'By proceeding, you consent to get calls or SMS messages, including by automated means, from {appName} and its affiliates to the number provided.'**
String consent_message(String appName); String consent_message(String appName);
/// No description provided for @otp_code_incomplete.
///
/// In en, this message translates to:
/// **'Code is incomplete. Please enter the full code.'**
String get otp_code_incomplete;
/// No description provided for @passwords_do_not_match.
///
/// In en, this message translates to:
/// **'Passwords do not match.'**
String get passwords_do_not_match;
/// No description provided for @reset_password.
///
/// In en, this message translates to:
/// **'Reset password'**
String get reset_password;
/// No description provided for @new_password.
///
/// In en, this message translates to:
/// **'New password'**
String get new_password;
/// No description provided for @enter_otp_code.
///
/// In en, this message translates to:
/// **'Enter the 5-digit code sent to you at {phoneNumber}'**
String enter_otp_code(String phoneNumber);
/// No description provided for @resend_otp_after.
///
/// In en, this message translates to:
/// **'You can resend OTP after'**
String get resend_otp_after;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View File

@@ -406,4 +406,25 @@ class AppLocalizationsEn extends AppLocalizations {
String consent_message(String appName) { String consent_message(String appName) {
return 'By proceeding, you consent to get calls or SMS messages, including by automated means, from $appName and its affiliates to the number provided.'; return 'By proceeding, you consent to get calls or SMS messages, including by automated means, from $appName and its affiliates to the number provided.';
} }
@override
String get otp_code_incomplete =>
'Code is incomplete. Please enter the full code.';
@override
String get passwords_do_not_match => 'Passwords do not match.';
@override
String get reset_password => 'Reset password';
@override
String get new_password => 'New password';
@override
String enter_otp_code(String phoneNumber) {
return 'Enter the 5-digit code sent to you at $phoneNumber';
}
@override
String get resend_otp_after => 'You can resend OTP after';
} }

View File

@@ -406,4 +406,25 @@ class AppLocalizationsRu extends AppLocalizations {
String consent_message(String appName) { String consent_message(String appName) {
return 'Продолжая, вы соглашаетесь получать звонки или SMS-сообщения, включая автоматические, от $appName и его партнёров на указанный номер.'; return 'Продолжая, вы соглашаетесь получать звонки или SMS-сообщения, включая автоматические, от $appName и его партнёров на указанный номер.';
} }
@override
String get otp_code_incomplete =>
'Код неполный. Пожалуйста, введите полный код.';
@override
String get passwords_do_not_match => 'Пароли не совпадают.';
@override
String get reset_password => 'Восстановить пароль';
@override
String get new_password => 'Новый пароль';
@override
String enter_otp_code(String phoneNumber) {
return 'Введите 5-значный код, отправленный на номер $phoneNumber';
}
@override
String get resend_otp_after => 'Вы можете повторно отправить код через';
} }

View File

@@ -407,4 +407,25 @@ class AppLocalizationsUz extends AppLocalizations {
String consent_message(String appName) { String consent_message(String appName) {
return 'Davom etish orqali siz $appName va uning hamkorlaridan siz kiritgan raqamga, shu jumladan avtomatik vositalar orqali, qongiroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.'; return 'Davom etish orqali siz $appName va uning hamkorlaridan siz kiritgan raqamga, shu jumladan avtomatik vositalar orqali, qongiroqlar yoki SMS xabarlar olishingizga rozilik bildirasiz.';
} }
@override
String get otp_code_incomplete =>
'Kod yetarli emas. Iltimos, toliq kodni kiriting.';
@override
String get passwords_do_not_match => 'Parollar mos kelmadi.';
@override
String get reset_password => 'Parolni qayta tiklash';
@override
String get new_password => 'Yangi parol';
@override
String enter_otp_code(String phoneNumber) {
return '$phoneNumber raqamiga yuborilgan 5 xonali kodni kiriting';
}
@override
String get resend_otp_after => 'OTP kodni qayta yuborish mumkin boladi';
} }

View File

@@ -19,7 +19,7 @@ class VerifyOtpCodeForgotPasswordUseCase
} }
class VerifyOtpCodeParams { class VerifyOtpCodeParams {
final String otpCode; final dynamic otpCode;
final String phoneNumber; final String phoneNumber;
VerifyOtpCodeParams({required this.otpCode, required this.phoneNumber}); VerifyOtpCodeParams({required this.otpCode, required this.phoneNumber});

View File

@@ -0,0 +1,35 @@
import 'package:food_delivery_client/feature/auth/domain/usecases/register_usecase.dart';
import 'package:food_delivery_client/feature/common/presentation/widgets/w_toastification.dart';
import 'package:food_delivery_client/food_delivery_client.dart';
part 'register_event.dart';
part 'register_state.dart';
part 'register_bloc.freezed.dart';
@injectable
class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
final RegisterUseCase _registerUseCase;
RegisterBloc(this._registerUseCase) : super(const RegisterState()) {
on<_Loaded>(_onLoaded);
}
Future<void> _onLoaded(_Loaded event, Emitter<RegisterState> emit) async {
emit(state.copyWith(status: RequestStatus.loading));
final response = await _registerUseCase.call(event.params);
response.fold(
(l) {
showErrorToast(l.errorMessage);
emit(state.copyWith(status: RequestStatus.error));
},
(r) {
showSuccessToast(r.message);
emit(state.copyWith(status: RequestStatus.loaded));
},
);
}
}

View File

@@ -0,0 +1,535 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'register_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$RegisterEvent {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is RegisterEvent);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'RegisterEvent()';
}
}
/// @nodoc
class $RegisterEventCopyWith<$Res> {
$RegisterEventCopyWith(RegisterEvent _, $Res Function(RegisterEvent) __);
}
/// Adds pattern-matching-related methods to [RegisterEvent].
extension RegisterEventPatterns on RegisterEvent {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Loaded value)? loaded,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Loaded() when loaded != null:
return loaded(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Loaded value) loaded,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _Loaded():
return loaded(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Loaded value)? loaded,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Loaded() when loaded != null:
return loaded(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( RegisterParams params)? loaded,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Loaded() when loaded != null:
return loaded(_that.params);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( RegisterParams params) loaded,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _Loaded():
return loaded(_that.params);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( RegisterParams params)? loaded,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Loaded() when loaded != null:
return loaded(_that.params);case _:
return null;
}
}
}
/// @nodoc
class _Started implements RegisterEvent {
const _Started();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Started);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'RegisterEvent.started()';
}
}
/// @nodoc
class _Loaded implements RegisterEvent {
const _Loaded(this.params);
final RegisterParams params;
/// Create a copy of RegisterEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LoadedCopyWith<_Loaded> get copyWith => __$LoadedCopyWithImpl<_Loaded>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Loaded&&(identical(other.params, params) || other.params == params));
}
@override
int get hashCode => Object.hash(runtimeType,params);
@override
String toString() {
return 'RegisterEvent.loaded(params: $params)';
}
}
/// @nodoc
abstract mixin class _$LoadedCopyWith<$Res> implements $RegisterEventCopyWith<$Res> {
factory _$LoadedCopyWith(_Loaded value, $Res Function(_Loaded) _then) = __$LoadedCopyWithImpl;
@useResult
$Res call({
RegisterParams params
});
}
/// @nodoc
class __$LoadedCopyWithImpl<$Res>
implements _$LoadedCopyWith<$Res> {
__$LoadedCopyWithImpl(this._self, this._then);
final _Loaded _self;
final $Res Function(_Loaded) _then;
/// Create a copy of RegisterEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? params = null,}) {
return _then(_Loaded(
null == params ? _self.params : params // ignore: cast_nullable_to_non_nullable
as RegisterParams,
));
}
}
/// @nodoc
mixin _$RegisterState {
RequestStatus get status;
/// Create a copy of RegisterState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$RegisterStateCopyWith<RegisterState> get copyWith => _$RegisterStateCopyWithImpl<RegisterState>(this as RegisterState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is RegisterState&&(identical(other.status, status) || other.status == status));
}
@override
int get hashCode => Object.hash(runtimeType,status);
@override
String toString() {
return 'RegisterState(status: $status)';
}
}
/// @nodoc
abstract mixin class $RegisterStateCopyWith<$Res> {
factory $RegisterStateCopyWith(RegisterState value, $Res Function(RegisterState) _then) = _$RegisterStateCopyWithImpl;
@useResult
$Res call({
RequestStatus status
});
}
/// @nodoc
class _$RegisterStateCopyWithImpl<$Res>
implements $RegisterStateCopyWith<$Res> {
_$RegisterStateCopyWithImpl(this._self, this._then);
final RegisterState _self;
final $Res Function(RegisterState) _then;
/// Create a copy of RegisterState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? status = null,}) {
return _then(_self.copyWith(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,
));
}
}
/// Adds pattern-matching-related methods to [RegisterState].
extension RegisterStatePatterns on RegisterState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _RegisterState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _RegisterState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _RegisterState value) $default,){
final _that = this;
switch (_that) {
case _RegisterState():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _RegisterState value)? $default,){
final _that = this;
switch (_that) {
case _RegisterState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RequestStatus status)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _RegisterState() when $default != null:
return $default(_that.status);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RequestStatus status) $default,) {final _that = this;
switch (_that) {
case _RegisterState():
return $default(_that.status);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RequestStatus status)? $default,) {final _that = this;
switch (_that) {
case _RegisterState() when $default != null:
return $default(_that.status);case _:
return null;
}
}
}
/// @nodoc
class _RegisterState implements RegisterState {
const _RegisterState({this.status = RequestStatus.initial});
@override@JsonKey() final RequestStatus status;
/// Create a copy of RegisterState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$RegisterStateCopyWith<_RegisterState> get copyWith => __$RegisterStateCopyWithImpl<_RegisterState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RegisterState&&(identical(other.status, status) || other.status == status));
}
@override
int get hashCode => Object.hash(runtimeType,status);
@override
String toString() {
return 'RegisterState(status: $status)';
}
}
/// @nodoc
abstract mixin class _$RegisterStateCopyWith<$Res> implements $RegisterStateCopyWith<$Res> {
factory _$RegisterStateCopyWith(_RegisterState value, $Res Function(_RegisterState) _then) = __$RegisterStateCopyWithImpl;
@override @useResult
$Res call({
RequestStatus status
});
}
/// @nodoc
class __$RegisterStateCopyWithImpl<$Res>
implements _$RegisterStateCopyWith<$Res> {
__$RegisterStateCopyWithImpl(this._self, this._then);
final _RegisterState _self;
final $Res Function(_RegisterState) _then;
/// Create a copy of RegisterState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? status = null,}) {
return _then(_RegisterState(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,
));
}
}
// dart format on

View File

@@ -0,0 +1,8 @@
part of 'register_bloc.dart';
@freezed
class RegisterEvent with _$RegisterEvent {
const factory RegisterEvent.started() = _Started;
const factory RegisterEvent.loaded(RegisterParams params) = _Loaded;
}

View File

@@ -0,0 +1,8 @@
part of 'register_bloc.dart';
@freezed
abstract class RegisterState with _$RegisterState {
const factory RegisterState({
@Default(RequestStatus.initial) RequestStatus status,
}) = _RegisterState;
}

View File

@@ -0,0 +1,36 @@
import 'package:food_delivery_client/feature/auth/domain/usecases/reset_password_usecase.dart';
import 'package:food_delivery_client/feature/common/presentation/widgets/w_toastification.dart';
import 'package:food_delivery_client/food_delivery_client.dart';
part 'reset_password_event.dart';
part 'reset_password_state.dart';
part 'reset_password_bloc.freezed.dart';
@injectable
class ResetPasswordBloc extends Bloc<ResetPasswordEvent, ResetPasswordState> {
final ResetPasswordUseCase _passwordUseCase;
ResetPasswordBloc(this._passwordUseCase) : super(const ResetPasswordState()) {
on<_Loaded>(_onLoaded);
}
Future<void> _onLoaded(
_Loaded event,
Emitter<ResetPasswordState> emit,
) async {
emit(state.copyWith(status: RequestStatus.loading));
final response = await _passwordUseCase.call(event.params);
response.fold(
(l) {
showErrorToast(l.errorMessage);
emit(state.copyWith(status: RequestStatus.error));
},
(r) {
showSuccessToast(r.message);
emit(state.copyWith(status: RequestStatus.loaded));
},
);
}
}

View File

@@ -0,0 +1,535 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'reset_password_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$ResetPasswordEvent {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ResetPasswordEvent);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'ResetPasswordEvent()';
}
}
/// @nodoc
class $ResetPasswordEventCopyWith<$Res> {
$ResetPasswordEventCopyWith(ResetPasswordEvent _, $Res Function(ResetPasswordEvent) __);
}
/// Adds pattern-matching-related methods to [ResetPasswordEvent].
extension ResetPasswordEventPatterns on ResetPasswordEvent {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Loaded value)? loaded,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Loaded() when loaded != null:
return loaded(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Loaded value) loaded,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _Loaded():
return loaded(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Loaded value)? loaded,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Loaded() when loaded != null:
return loaded(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( ResetPasswordParams params)? loaded,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Loaded() when loaded != null:
return loaded(_that.params);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( ResetPasswordParams params) loaded,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _Loaded():
return loaded(_that.params);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( ResetPasswordParams params)? loaded,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Loaded() when loaded != null:
return loaded(_that.params);case _:
return null;
}
}
}
/// @nodoc
class _Started implements ResetPasswordEvent {
const _Started();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Started);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'ResetPasswordEvent.started()';
}
}
/// @nodoc
class _Loaded implements ResetPasswordEvent {
const _Loaded(this.params);
final ResetPasswordParams params;
/// Create a copy of ResetPasswordEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LoadedCopyWith<_Loaded> get copyWith => __$LoadedCopyWithImpl<_Loaded>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Loaded&&(identical(other.params, params) || other.params == params));
}
@override
int get hashCode => Object.hash(runtimeType,params);
@override
String toString() {
return 'ResetPasswordEvent.loaded(params: $params)';
}
}
/// @nodoc
abstract mixin class _$LoadedCopyWith<$Res> implements $ResetPasswordEventCopyWith<$Res> {
factory _$LoadedCopyWith(_Loaded value, $Res Function(_Loaded) _then) = __$LoadedCopyWithImpl;
@useResult
$Res call({
ResetPasswordParams params
});
}
/// @nodoc
class __$LoadedCopyWithImpl<$Res>
implements _$LoadedCopyWith<$Res> {
__$LoadedCopyWithImpl(this._self, this._then);
final _Loaded _self;
final $Res Function(_Loaded) _then;
/// Create a copy of ResetPasswordEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? params = null,}) {
return _then(_Loaded(
null == params ? _self.params : params // ignore: cast_nullable_to_non_nullable
as ResetPasswordParams,
));
}
}
/// @nodoc
mixin _$ResetPasswordState {
RequestStatus get status;
/// Create a copy of ResetPasswordState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$ResetPasswordStateCopyWith<ResetPasswordState> get copyWith => _$ResetPasswordStateCopyWithImpl<ResetPasswordState>(this as ResetPasswordState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ResetPasswordState&&(identical(other.status, status) || other.status == status));
}
@override
int get hashCode => Object.hash(runtimeType,status);
@override
String toString() {
return 'ResetPasswordState(status: $status)';
}
}
/// @nodoc
abstract mixin class $ResetPasswordStateCopyWith<$Res> {
factory $ResetPasswordStateCopyWith(ResetPasswordState value, $Res Function(ResetPasswordState) _then) = _$ResetPasswordStateCopyWithImpl;
@useResult
$Res call({
RequestStatus status
});
}
/// @nodoc
class _$ResetPasswordStateCopyWithImpl<$Res>
implements $ResetPasswordStateCopyWith<$Res> {
_$ResetPasswordStateCopyWithImpl(this._self, this._then);
final ResetPasswordState _self;
final $Res Function(ResetPasswordState) _then;
/// Create a copy of ResetPasswordState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? status = null,}) {
return _then(_self.copyWith(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,
));
}
}
/// Adds pattern-matching-related methods to [ResetPasswordState].
extension ResetPasswordStatePatterns on ResetPasswordState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _ResetPasswordState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _ResetPasswordState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _ResetPasswordState value) $default,){
final _that = this;
switch (_that) {
case _ResetPasswordState():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _ResetPasswordState value)? $default,){
final _that = this;
switch (_that) {
case _ResetPasswordState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RequestStatus status)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _ResetPasswordState() when $default != null:
return $default(_that.status);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RequestStatus status) $default,) {final _that = this;
switch (_that) {
case _ResetPasswordState():
return $default(_that.status);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RequestStatus status)? $default,) {final _that = this;
switch (_that) {
case _ResetPasswordState() when $default != null:
return $default(_that.status);case _:
return null;
}
}
}
/// @nodoc
class _ResetPasswordState implements ResetPasswordState {
const _ResetPasswordState({this.status = RequestStatus.initial});
@override@JsonKey() final RequestStatus status;
/// Create a copy of ResetPasswordState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$ResetPasswordStateCopyWith<_ResetPasswordState> get copyWith => __$ResetPasswordStateCopyWithImpl<_ResetPasswordState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ResetPasswordState&&(identical(other.status, status) || other.status == status));
}
@override
int get hashCode => Object.hash(runtimeType,status);
@override
String toString() {
return 'ResetPasswordState(status: $status)';
}
}
/// @nodoc
abstract mixin class _$ResetPasswordStateCopyWith<$Res> implements $ResetPasswordStateCopyWith<$Res> {
factory _$ResetPasswordStateCopyWith(_ResetPasswordState value, $Res Function(_ResetPasswordState) _then) = __$ResetPasswordStateCopyWithImpl;
@override @useResult
$Res call({
RequestStatus status
});
}
/// @nodoc
class __$ResetPasswordStateCopyWithImpl<$Res>
implements _$ResetPasswordStateCopyWith<$Res> {
__$ResetPasswordStateCopyWithImpl(this._self, this._then);
final _ResetPasswordState _self;
final $Res Function(_ResetPasswordState) _then;
/// Create a copy of ResetPasswordState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? status = null,}) {
return _then(_ResetPasswordState(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,
));
}
}
// dart format on

View File

@@ -0,0 +1,8 @@
part of 'reset_password_bloc.dart';
@freezed
class ResetPasswordEvent with _$ResetPasswordEvent {
const factory ResetPasswordEvent.started() = _Started;
const factory ResetPasswordEvent.loaded(ResetPasswordParams params) = _Loaded;
}

View File

@@ -0,0 +1,8 @@
part of 'reset_password_bloc.dart';
@freezed
abstract class ResetPasswordState with _$ResetPasswordState {
const factory ResetPasswordState({
@Default(RequestStatus.initial) RequestStatus status,
}) = _ResetPasswordState;
}

View File

@@ -67,6 +67,7 @@ class VerifyOtpBloc extends Bloc<VerifyOtpEvent, VerifyOtpState> {
emit(state.copyWith(status: RequestStatus.error)); emit(state.copyWith(status: RequestStatus.error));
}, },
(r) { (r) {
showSuccessToast(r.message);
emit(state.copyWith(status: RequestStatus.loaded)); emit(state.copyWith(status: RequestStatus.loaded));
add(VerifyOtpEvent.cancelTimer()); add(VerifyOtpEvent.cancelTimer());
}, },
@@ -86,6 +87,7 @@ class VerifyOtpBloc extends Bloc<VerifyOtpEvent, VerifyOtpState> {
emit(state.copyWith(status: RequestStatus.error)); emit(state.copyWith(status: RequestStatus.error));
}, },
(r) { (r) {
showSuccessToast(r.message);
emit(state.copyWith(status: RequestStatus.loaded)); emit(state.copyWith(status: RequestStatus.loaded));
add(VerifyOtpEvent.cancelTimer()); add(VerifyOtpEvent.cancelTimer());
}, },

View File

@@ -2,6 +2,7 @@ import 'package:food_delivery_client/core/helpers/formatters.dart';
import 'package:food_delivery_client/core/helpers/validator_helpers.dart'; import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart'; import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../../food_delivery_client.dart'; import '../../../../../../food_delivery_client.dart';
import '../../../../domain/usecases/login_usecase.dart';
import '../../../blocs/login_bloc/login_bloc.dart'; import '../../../blocs/login_bloc/login_bloc.dart';
class WLoginBody extends StatefulWidget { class WLoginBody extends StatefulWidget {
@@ -128,16 +129,15 @@ class _WLoginBodyState extends State<WLoginBody> {
).paddingOnly(left: 10), ).paddingOnly(left: 10),
onPressed: () { onPressed: () {
if (_formKey.currentState?.validate() ?? false) { if (_formKey.currentState?.validate() ?? false) {
context.go(Routes.main); context.read<LoginBloc>().add(
// context.read<LoginBloc>().add( LoginEvent.login(
// LoginEvent.login( LoginParams(
// LoginParams( phoneNumber:
// phoneNumber: "+998${_phoneController.text.trim().replaceAll(" ", "")}",
// "+998${_phoneController.text.trim().replaceAll(" ", "")}", password: _passwordController.text.trim(),
// password: _passwordController.text.trim(), ),
// ), ),
// ), );
// );
} }
}, },
borderRadius: 15, borderRadius: 15,

View File

@@ -1,6 +1,7 @@
import 'package:food_delivery_client/feature/auth/presentation/pages/register_page/widgets/w_register_body.dart'; import 'package:food_delivery_client/feature/auth/presentation/pages/register_page/widgets/w_register_body.dart';
import '../../../../../food_delivery_client.dart'; import '../../../../../food_delivery_client.dart';
import '../../blocs/register_bloc/register_bloc.dart';
class RegisterPage extends StatelessWidget { class RegisterPage extends StatelessWidget {
const RegisterPage({super.key, required this.phoneNumber}); const RegisterPage({super.key, required this.phoneNumber});
@@ -9,6 +10,16 @@ class RegisterPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WLayout(top: false, child: Scaffold(body: WRegisterBody())); return BlocProvider(
create: (context) => sl<RegisterBloc>(),
child: BlocBuilder<RegisterBloc, RegisterState>(
builder: (context, state) {
return WLayout(
top: false,
child: Scaffold(body: WRegisterBody(phoneNumber: phoneNumber)),
);
},
),
);
} }
} }

View File

@@ -1,9 +1,13 @@
import 'package:food_delivery_client/core/helpers/validator_helpers.dart'; import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/register_usecase.dart';
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart'; import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../../food_delivery_client.dart'; import '../../../../../../food_delivery_client.dart';
import '../../../blocs/register_bloc/register_bloc.dart';
class WRegisterBody extends StatefulWidget { class WRegisterBody extends StatefulWidget {
const WRegisterBody({super.key}); const WRegisterBody({super.key, required this.phoneNumber});
final String phoneNumber;
@override @override
State<WRegisterBody> createState() => _WRegisterBodyState(); State<WRegisterBody> createState() => _WRegisterBodyState();
@@ -40,6 +44,13 @@ class _WRegisterBodyState extends State<WRegisterBody> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocConsumer<RegisterBloc, RegisterState>(
listener: (context, state) {
if (state.status.isLoaded()) {
context.go(Routes.login);
}
},
builder: (context, state) {
return Form( return Form(
key: _formKey, key: _formKey,
child: WAuthBackground( child: WAuthBackground(
@@ -157,24 +168,33 @@ class _WRegisterBodyState extends State<WRegisterBody> {
borderRadius: AppUtils.kBorderRadius8, borderRadius: AppUtils.kBorderRadius8,
keyBoardType: TextInputType.visiblePassword, keyBoardType: TextInputType.visiblePassword,
validator: (value) { validator: (value) {
return Validators.validatePassword( return Validators.validateRepeatPassword(
_repeatPasswordController.text.trim(), _repeatPasswordController.text.trim(),
_passwordController.text.trim(),
); );
}, },
), ),
20.verticalSpace, 20.verticalSpace,
AppButton( AppButton(
isLoading: state.status.isLoading(),
name: context.loc.continue_str, name: context.loc.continue_str,
borderRadius: 15, borderRadius: 15,
backgroundColor: AppColors.c34A853, backgroundColor: AppColors.c34A853,
trailing: SvgPicture.asset( trailing: SvgPicture.asset(
AppIcons.icArrowRightLight, AppIcons.icArrowRightLight,
).paddingOnly(left: 8), ).paddingOnly(left: 8),
onPressed: () { onPressed: () {
if (_formKey.currentState?.validate() ?? false) { if (_formKey.currentState?.validate() ?? false) {
context.read<RegisterBloc>().add(
RegisterEvent.loaded(
RegisterParams(
phoneNumber: widget.phoneNumber,
password: _passwordController.text.trim(),
firstName: _firstNameController.text.trim(),
lastName: _lastNameController.text.trim(),
),
),
);
} }
}, },
), ),
@@ -204,5 +224,7 @@ class _WRegisterBodyState extends State<WRegisterBody> {
), ),
), ),
); );
},
);
} }
} }

View File

@@ -1,22 +1,138 @@
import 'package:food_delivery_client/core/helpers/validator_helpers.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/reset_password_usecase.dart';
import 'package:food_delivery_client/feature/auth/presentation/blocs/reset_password_bloc/reset_password_bloc.dart';
import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart'; import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_background.dart';
import '../../../../../food_delivery_client.dart'; import '../../../../../food_delivery_client.dart';
class ResetPasswordPage extends StatelessWidget { class ResetPasswordPage extends StatefulWidget {
const ResetPasswordPage({super.key, required this.phoneNumber}); const ResetPasswordPage({super.key, required this.phoneNumber});
final String phoneNumber; final String phoneNumber;
@override
State<ResetPasswordPage> createState() => _ResetPasswordPageState();
}
class _ResetPasswordPageState extends State<ResetPasswordPage> {
late TextEditingController _passwordController;
late TextEditingController _repeatPasswordController;
final _formKey = GlobalKey<FormState>();
@override
void initState() {
_passwordController = TextEditingController();
_repeatPasswordController = TextEditingController();
super.initState();
}
@override
void dispose() {
_passwordController.dispose();
_repeatPasswordController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WLayout( return BlocProvider(
create: (context) => sl<ResetPasswordBloc>(),
child: BlocConsumer<ResetPasswordBloc, ResetPasswordState>(
listener: (context, state) {
if (state.status.isLoaded()) {
context.go(Routes.login);
}
},
builder: (context, state) {
return Form(
key: _formKey,
child: WLayout(
top: false, top: false,
child: Scaffold( child: Scaffold(
body: WAuthBackground( body: WAuthBackground(
child: SizedBox(
width: context.w,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [], children: [
25.verticalSpace,
Text(
context.loc.reset_password,
style: AppTextStyles.size20Medium,
), ),
20.verticalSpace,
Text(
context.loc.new_password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
obscureText: true,
controller: _passwordController,
borderRadius: AppUtils.kBorderRadius8,
hintText: context.loc.enter_password,
keyBoardType: TextInputType.visiblePassword,
validator: (value) {
return Validators.validatePassword(
_passwordController.text.trim(),
);
},
),
20.verticalSpace,
Text(
context.loc.password,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6A6E7F,
),
),
5.verticalSpace,
AppTextFormField(
obscureText: true,
controller: _repeatPasswordController,
borderRadius: AppUtils.kBorderRadius8,
hintText: context.loc.enter_password,
keyBoardType: TextInputType.visiblePassword,
validator: (value) {
return Validators.validateRepeatPassword(
_repeatPasswordController.text.trim(),
_passwordController.text.trim(),
);
},
),
25.verticalSpace,
AppButton(
name: context.loc.continue_str,
trailing: SvgPicture.asset(
AppIcons.icArrowRightLight,
).paddingOnly(left: 8),
isLoading: state.status.isLoading(),
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
context.read<ResetPasswordBloc>().add(
ResetPasswordEvent.loaded(
ResetPasswordParams(
phoneNumber: widget.phoneNumber,
newPassword: _passwordController.text
.trim(),
), ),
), ),
); );
} }
},
backgroundColor: AppColors.c34A853,
borderRadius: 15,
),
],
).paddingSymmetric(horizontal: 16),
),
),
),
),
);
},
),
);
}
} }

View File

@@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:food_delivery_client/core/helpers/time_formatters.dart'; import 'package:food_delivery_client/core/helpers/time_formatters.dart';
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_otp_code_login_usecase.dart'; import 'package:food_delivery_client/feature/auth/domain/usecases/verify_otp_code_login_usecase.dart';
import 'package:food_delivery_client/feature/auth/presentation/blocs/verify_otp_bloc/verify_otp_bloc.dart'; import 'package:food_delivery_client/feature/auth/presentation/blocs/verify_otp_bloc/verify_otp_bloc.dart';
@@ -68,7 +69,7 @@ class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
children: [ children: [
40.verticalSpace, 40.verticalSpace,
Text( Text(
"Enter the 5-digit code sent to you at ${widget.params.phoneNumber}", context.loc.enter_otp_code(widget.params.phoneNumber),
style: AppTextStyles.size20Medium, style: AppTextStyles.size20Medium,
), ),
20.verticalSpace, 20.verticalSpace,
@@ -98,18 +99,25 @@ class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
}, },
), ),
10.verticalSpace, 10.verticalSpace,
Row( SizedBox(
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text("You can resend otp after"), Text(
context.loc.resend_otp_after,
style: AppTextStyles.size14Regular,
),
if (state.time != 0) if (state.time != 0)
Text(TimeFormatters.formatMinutesToTime(state.time)), Text(
TimeFormatters.formatMinutesToTime(state.time),
),
if (state.time == 0) if (state.time == 0)
state.resendStatus.isLoading() state.resendStatus.isLoading()
? CircularProgressIndicator.adaptive() ? CircularProgressIndicator.adaptive()
: TextButton( : IconButton(
onPressed: () { onPressed: () {
if (widget.params.isRegister) { if (widget.params.isRegister) {
context.read<VerifyOtpBloc>().add( context.read<VerifyOtpBloc>().add(
@@ -125,10 +133,14 @@ class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
); );
} }
}, },
child: Text("Resend"), icon: Icon(
CupertinoIcons.restart,
color: AppColors.c000000,
),
), ),
], ],
), ),
),
20.verticalSpace, 20.verticalSpace,
AppButton( AppButton(
@@ -153,9 +165,8 @@ class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
VerifyOtpEvent.verifyOtpReset( VerifyOtpEvent.verifyOtpReset(
VerifyOtpCodeParams( VerifyOtpCodeParams(
phoneNumber: widget.params.phoneNumber, phoneNumber: widget.params.phoneNumber,
otpCode: _controller.text.trim().substring( otpCode: int.tryParse(
0, _controller.text.trim().substring(0, 4),
4,
), ),
), ),
), ),
@@ -163,6 +174,7 @@ class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
} }
} }
}, },
isLoading: state.status.isLoading(),
backgroundColor: AppColors.c34A853, backgroundColor: AppColors.c34A853,
borderRadius: 15, borderRadius: 15,
trailing: SvgPicture.asset( trailing: SvgPicture.asset(

View File

@@ -115,6 +115,7 @@ class _VerifyPhoneNumberPageState extends State<VerifyPhoneNumberPage> {
} }
} }
}, },
isLoading: state.status.isLoading(),
name: context.loc.continue_str, name: context.loc.continue_str,
borderRadius: 15, borderRadius: 15,
backgroundColor: AppColors.c34A853, backgroundColor: AppColors.c34A853,

View File

@@ -14,8 +14,8 @@ class WAuthBackground extends StatelessWidget {
child: Image.asset(AppImages.imgBurger2, fit: BoxFit.cover), child: Image.asset(AppImages.imgBurger2, fit: BoxFit.cover),
), ),
SingleChildScrollView( SingleChildScrollView(
// keyboardDismissBehavior: keyboardDismissBehavior:
// ScrollViewKeyboardDismissBehavior.onDrag, ScrollViewKeyboardDismissBehavior.onDrag,
child: Column( child: Column(
children: [ children: [
SizedBox(height: context.h * .2), SizedBox(height: context.h * .2),