feat: sending otp and resend otp done
This commit is contained in:
@@ -3,5 +3,6 @@ abstract class TimeDelayConst {
|
|||||||
static const Duration durationMill300 = Duration(milliseconds: 300);
|
static const Duration durationMill300 = Duration(milliseconds: 300);
|
||||||
static const Duration durationMill800 = Duration(milliseconds: 800);
|
static const Duration durationMill800 = Duration(milliseconds: 800);
|
||||||
static const Duration durationMill3500 = Duration(milliseconds: 3500);
|
static const Duration durationMill3500 = Duration(milliseconds: 3500);
|
||||||
|
static const Duration duration1 = Duration(seconds: 1);
|
||||||
static const Duration duration3 = Duration(seconds: 3);
|
static const Duration duration3 = Duration(seconds: 3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/verify_otp_bloc/verify_otp_bloc.dart'
|
||||||
|
as _i323;
|
||||||
|
import '../../feature/auth/presentation/blocs/verify_phone_bloc/verify_phone_bloc.dart'
|
||||||
|
as _i224;
|
||||||
import '../../feature/basket/presentation/blocs/basket_bloc.dart' as _i728;
|
import '../../feature/basket/presentation/blocs/basket_bloc.dart' as _i728;
|
||||||
import '../../feature/browse/presentation/blocs/browse_bloc/browse_bloc.dart'
|
import '../../feature/browse/presentation/blocs/browse_bloc/browse_bloc.dart'
|
||||||
as _i991;
|
as _i991;
|
||||||
@@ -101,6 +105,20 @@ extension GetItInjectableX on _i174.GetIt {
|
|||||||
gh.factory<_i406.VerifyOtpCodeRegisterUseCase>(
|
gh.factory<_i406.VerifyOtpCodeRegisterUseCase>(
|
||||||
() => _i406.VerifyOtpCodeRegisterUseCase(gh<_i884.AuthRepository>()),
|
() => _i406.VerifyOtpCodeRegisterUseCase(gh<_i884.AuthRepository>()),
|
||||||
);
|
);
|
||||||
|
gh.factory<_i323.VerifyOtpBloc>(
|
||||||
|
() => _i323.VerifyOtpBloc(
|
||||||
|
gh<_i406.VerifyOtpCodeRegisterUseCase>(),
|
||||||
|
gh<_i318.VerifyOtpCodeForgotPasswordUseCase>(),
|
||||||
|
gh<_i664.VerifyPhoneRegisterUseCase>(),
|
||||||
|
gh<_i801.VerifyPhoneNumberLoginUseCase>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
gh.factory<_i224.VerifyPhoneBloc>(
|
||||||
|
() => _i224.VerifyPhoneBloc(
|
||||||
|
gh<_i801.VerifyPhoneNumberLoginUseCase>(),
|
||||||
|
gh<_i664.VerifyPhoneRegisterUseCase>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
gh.factory<_i1065.LoginBloc>(
|
gh.factory<_i1065.LoginBloc>(
|
||||||
() => _i1065.LoginBloc(
|
() => _i1065.LoginBloc(
|
||||||
gh<_i241.LoginUseCase>(),
|
gh<_i241.LoginUseCase>(),
|
||||||
|
|||||||
8
lib/core/helpers/time_formatters.dart
Normal file
8
lib/core/helpers/time_formatters.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
abstract class TimeFormatters {
|
||||||
|
static String formatMinutesToTime(int totalMinutes) {
|
||||||
|
final hours = totalMinutes ~/ 60;
|
||||||
|
final minutes = totalMinutes % 60;
|
||||||
|
|
||||||
|
return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_otp_code_login_usecase.dart';
|
||||||
import 'package:food_delivery_client/feature/auth/presentation/pages/forgot_password_page/forgot_password_page.dart';
|
import 'package:food_delivery_client/feature/auth/presentation/pages/forgot_password_page/forgot_password_page.dart';
|
||||||
import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/login_page.dart';
|
import 'package:food_delivery_client/feature/auth/presentation/pages/login_page/login_page.dart';
|
||||||
import 'package:food_delivery_client/feature/auth/presentation/pages/register_page/register_page.dart';
|
import 'package:food_delivery_client/feature/auth/presentation/pages/register_page/register_page.dart';
|
||||||
@@ -25,7 +26,9 @@ class AppRoutes {
|
|||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.register,
|
path: Routes.register,
|
||||||
pageBuilder: (context, state) => CupertinoPage(child: RegisterPage()),
|
pageBuilder: (context, state) => CupertinoPage(
|
||||||
|
child: RegisterPage(phoneNumber: state.extra as String),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.forgotPassword,
|
path: Routes.forgotPassword,
|
||||||
@@ -42,14 +45,15 @@ class AppRoutes {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.verifyOtpCode,
|
path: Routes.verifyOtpCode,
|
||||||
pageBuilder: (context, state) => CupertinoPage(
|
pageBuilder: (context, state) => CupertinoPage(
|
||||||
child: VerifyOtpCodePage(isRegister: state.extra as bool),
|
child: VerifyOtpCodePage(params: state.extra as OtpCodePageParams),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: Routes.resetPassword,
|
path: Routes.resetPassword,
|
||||||
pageBuilder: (context, state) =>
|
pageBuilder: (context, state) => CupertinoPage(
|
||||||
CupertinoPage(child: ResetPasswordPage()),
|
child: ResetPasswordPage(phoneNumber: state.extra as String),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import '../../../../core/usecase/usecase.dart';
|
|||||||
|
|
||||||
VerifyOtpCodeForgotPasswordUseCase(this._authRepository);
|
VerifyOtpCodeForgotPasswordUseCase(this._authRepository);
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Either<Failure, SuccessModel>> call(VerifyOtpCodeParams params) async {
|
Future<Either<Failure, SuccessModel>> call(VerifyOtpCodeParams params) async {
|
||||||
return _authRepository.verifyOtpCodeResetPassword(params: params);
|
return _authRepository.verifyOtpCodeResetPassword(params: params);
|
||||||
@@ -25,3 +24,10 @@ class VerifyOtpCodeParams {
|
|||||||
|
|
||||||
VerifyOtpCodeParams({required this.otpCode, required this.phoneNumber});
|
VerifyOtpCodeParams({required this.otpCode, required this.phoneNumber});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OtpCodePageParams {
|
||||||
|
final String phoneNumber;
|
||||||
|
final bool isRegister;
|
||||||
|
|
||||||
|
OtpCodePageParams({required this.phoneNumber, required this.isRegister});
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
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_register_usecase.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_login_usecase.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_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 'verify_otp_event.dart';
|
||||||
|
|
||||||
|
part 'verify_otp_state.dart';
|
||||||
|
|
||||||
|
part 'verify_otp_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class VerifyOtpBloc extends Bloc<VerifyOtpEvent, VerifyOtpState> {
|
||||||
|
final VerifyOtpCodeRegisterUseCase _registerUseCase;
|
||||||
|
final VerifyOtpCodeForgotPasswordUseCase _passwordUseCase;
|
||||||
|
final VerifyPhoneRegisterUseCase _phoneRegisterUseCase;
|
||||||
|
final VerifyPhoneNumberLoginUseCase _phoneNumberLoginUseCase;
|
||||||
|
|
||||||
|
VerifyOtpBloc(
|
||||||
|
this._registerUseCase,
|
||||||
|
this._passwordUseCase,
|
||||||
|
this._phoneRegisterUseCase,
|
||||||
|
this._phoneNumberLoginUseCase,
|
||||||
|
) : super(const VerifyOtpState()) {
|
||||||
|
Timer? timer1;
|
||||||
|
|
||||||
|
on<_CancelTimer>((event, emit) {
|
||||||
|
timer1?.cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
on<_Started>((event, emit) {
|
||||||
|
int seconds = state.time;
|
||||||
|
emit(state.copyWith(time: seconds));
|
||||||
|
timer1 = Timer.periodic(TimeDelayConst.duration1, (timer) {
|
||||||
|
if (seconds == 0) {
|
||||||
|
timer.cancel();
|
||||||
|
} else {
|
||||||
|
seconds--;
|
||||||
|
add(VerifyOtpEvent.ticked(seconds));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
on<_Ticked>(_onTicked);
|
||||||
|
on<_VerifyOtpReset>(_onVerifyOtpReset);
|
||||||
|
on<_VerifyOtpRegister>(_onVerifyOtpRegister);
|
||||||
|
on<_ResendRegister>(_onResendVerifyPhoneRegister);
|
||||||
|
on<_ResendForgot>(_onResendVerifyPhoneForgot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTicked(_Ticked event, Emitter<VerifyOtpState> emit) {
|
||||||
|
emit(state.copyWith(time: event.seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onVerifyOtpReset(
|
||||||
|
_VerifyOtpReset event,
|
||||||
|
Emitter<VerifyOtpState> 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) {
|
||||||
|
emit(state.copyWith(status: RequestStatus.loaded));
|
||||||
|
add(VerifyOtpEvent.cancelTimer());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onVerifyOtpRegister(
|
||||||
|
_VerifyOtpRegister event,
|
||||||
|
Emitter<VerifyOtpState> 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) {
|
||||||
|
emit(state.copyWith(status: RequestStatus.loaded));
|
||||||
|
add(VerifyOtpEvent.cancelTimer());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onResendVerifyPhoneRegister(
|
||||||
|
_ResendRegister event,
|
||||||
|
Emitter<VerifyOtpState> emit,
|
||||||
|
) async {
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.loading));
|
||||||
|
final response = await _phoneRegisterUseCase.call(
|
||||||
|
VerifyPhoneNumberParams(phoneNumber: event.phoneNUmber),
|
||||||
|
);
|
||||||
|
|
||||||
|
response.fold(
|
||||||
|
(l) {
|
||||||
|
showErrorToast(l.errorMessage);
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.error));
|
||||||
|
},
|
||||||
|
(r) {
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.loaded));
|
||||||
|
add(VerifyOtpEvent.ticked(120));
|
||||||
|
add(VerifyOtpEvent.started());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onResendVerifyPhoneForgot(
|
||||||
|
_ResendForgot event,
|
||||||
|
Emitter<VerifyOtpState> emit,
|
||||||
|
) async {
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.loading));
|
||||||
|
final response = await _phoneNumberLoginUseCase.call(
|
||||||
|
VerifyPhoneNumberParams(phoneNumber: event.phoneNUmber),
|
||||||
|
);
|
||||||
|
|
||||||
|
response.fold(
|
||||||
|
(l) {
|
||||||
|
showErrorToast(l.errorMessage);
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.error));
|
||||||
|
},
|
||||||
|
(r) {
|
||||||
|
emit(state.copyWith(resendStatus: RequestStatus.loaded));
|
||||||
|
add(VerifyOtpEvent.ticked(120));
|
||||||
|
add(VerifyOtpEvent.started());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
part of 'verify_otp_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class VerifyOtpEvent with _$VerifyOtpEvent {
|
||||||
|
const factory VerifyOtpEvent.started() = _Started;
|
||||||
|
const factory VerifyOtpEvent.cancelTimer() = _CancelTimer;
|
||||||
|
const factory VerifyOtpEvent.resendRegister(String phoneNUmber) =
|
||||||
|
_ResendRegister;
|
||||||
|
|
||||||
|
const factory VerifyOtpEvent.resendForgot(String phoneNUmber) = _ResendForgot;
|
||||||
|
|
||||||
|
const factory VerifyOtpEvent.ticked(int seconds) = _Ticked;
|
||||||
|
|
||||||
|
const factory VerifyOtpEvent.verifyOtpReset(VerifyOtpCodeParams params) =
|
||||||
|
_VerifyOtpReset;
|
||||||
|
|
||||||
|
const factory VerifyOtpEvent.verifyOtpRegister(VerifyOtpCodeParams params) =
|
||||||
|
_VerifyOtpRegister;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
part of 'verify_otp_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class VerifyOtpState with _$VerifyOtpState {
|
||||||
|
const factory VerifyOtpState({
|
||||||
|
@Default(RequestStatus.initial) RequestStatus status,
|
||||||
|
@Default(RequestStatus.initial) RequestStatus resendStatus,
|
||||||
|
@Default(120) int time,
|
||||||
|
}) = _VerifyOtpState;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_login_usecase.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_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 'verify_phone_event.dart';
|
||||||
|
|
||||||
|
part 'verify_phone_state.dart';
|
||||||
|
|
||||||
|
part 'verify_phone_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class VerifyPhoneBloc extends Bloc<VerifyPhoneEvent, VerifyPhoneState> {
|
||||||
|
final VerifyPhoneNumberLoginUseCase _loginUseCase;
|
||||||
|
final VerifyPhoneRegisterUseCase _registerUseCase;
|
||||||
|
|
||||||
|
VerifyPhoneBloc(this._loginUseCase, this._registerUseCase)
|
||||||
|
: super(const VerifyPhoneState()) {
|
||||||
|
on<_VerifyPhoneRegister>(_onVerifyPhoneNumberRegister);
|
||||||
|
on<_VerifyPhoneReset>(_onVerifyPhoneReset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onVerifyPhoneNumberRegister(
|
||||||
|
_VerifyPhoneRegister event,
|
||||||
|
Emitter<VerifyPhoneState> 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));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onVerifyPhoneReset(
|
||||||
|
_VerifyPhoneReset event,
|
||||||
|
Emitter<VerifyPhoneState> emit,
|
||||||
|
) async {
|
||||||
|
emit(state.copyWith(status: RequestStatus.loading));
|
||||||
|
final response = await _loginUseCase.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));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
part of 'verify_phone_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class VerifyPhoneEvent with _$VerifyPhoneEvent {
|
||||||
|
const factory VerifyPhoneEvent.started() = _Started;
|
||||||
|
|
||||||
|
const factory VerifyPhoneEvent.verifyPhoneRegister(
|
||||||
|
VerifyPhoneNumberParams params,
|
||||||
|
) = _VerifyPhoneRegister;
|
||||||
|
|
||||||
|
const factory VerifyPhoneEvent.verifyPhoneReset(
|
||||||
|
VerifyPhoneNumberParams params,
|
||||||
|
) = _VerifyPhoneReset;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
part of 'verify_phone_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class VerifyPhoneState with _$VerifyPhoneState {
|
||||||
|
const factory VerifyPhoneState({
|
||||||
|
@Default(RequestStatus.initial) RequestStatus status,
|
||||||
|
}) = _VerifyPhoneState;
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:food_delivery_client/core/helpers/formatters.dart';
|
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/domain/usecases/login_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/login_bloc/login_bloc.dart';
|
import '../../../blocs/login_bloc/login_bloc.dart';
|
||||||
@@ -110,7 +109,7 @@ class _WLoginBodyState extends State<WLoginBody> {
|
|||||||
alignment: AlignmentGeometry.centerRight,
|
alignment: AlignmentGeometry.centerRight,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// context.push(Routes.verifyPhoneNumber, extra: false);
|
context.push(Routes.verifyPhoneNumber, extra: false);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
context.loc.forgot_password,
|
context.loc.forgot_password,
|
||||||
@@ -154,7 +153,7 @@ class _WLoginBodyState extends State<WLoginBody> {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// context.push(Routes.verifyPhoneNumber, extra: true);
|
context.push(Routes.verifyPhoneNumber, extra: true);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
context.loc.sign_up,
|
context.loc.sign_up,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import 'package:food_delivery_client/feature/auth/presentation/pages/register_pa
|
|||||||
import '../../../../../food_delivery_client.dart';
|
import '../../../../../food_delivery_client.dart';
|
||||||
|
|
||||||
class RegisterPage extends StatelessWidget {
|
class RegisterPage extends StatelessWidget {
|
||||||
const RegisterPage({super.key});
|
const RegisterPage({super.key, required this.phoneNumber});
|
||||||
|
|
||||||
|
final String phoneNumber;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WLayout(
|
return WLayout(top: false, child: Scaffold(body: WRegisterBody()));
|
||||||
top: false,
|
|
||||||
child: Scaffold(body: WRegisterBody()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,10 @@ class _WRegisterBodyState extends State<WRegisterBody> {
|
|||||||
AppIcons.icArrowRightLight,
|
AppIcons.icArrowRightLight,
|
||||||
).paddingOnly(left: 8),
|
).paddingOnly(left: 8),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState?.validate() ?? false) {}
|
if (_formKey.currentState?.validate() ?? false) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
20.verticalSpace,
|
20.verticalSpace,
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import 'package:food_delivery_client/feature/auth/presentation/widgets/w_auth_ba
|
|||||||
import '../../../../../food_delivery_client.dart';
|
import '../../../../../food_delivery_client.dart';
|
||||||
|
|
||||||
class ResetPasswordPage extends StatelessWidget {
|
class ResetPasswordPage extends StatelessWidget {
|
||||||
const ResetPasswordPage({super.key});
|
const ResetPasswordPage({super.key, required this.phoneNumber});
|
||||||
|
final String phoneNumber;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WLayout(
|
return WLayout(
|
||||||
|
|||||||
@@ -1,17 +1,181 @@
|
|||||||
|
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/presentation/blocs/verify_otp_bloc/verify_otp_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 'package:pinput/pinput.dart';
|
||||||
|
|
||||||
import '../../../../../food_delivery_client.dart';
|
import '../../../../../food_delivery_client.dart';
|
||||||
|
|
||||||
class VerifyOtpCodePage extends StatelessWidget {
|
class VerifyOtpCodePage extends StatefulWidget {
|
||||||
const VerifyOtpCodePage({super.key, required this.isRegister});
|
const VerifyOtpCodePage({super.key, required this.params});
|
||||||
|
|
||||||
final bool isRegister;
|
final OtpCodePageParams params;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<VerifyOtpCodePage> createState() => _VerifyOtpCodePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _VerifyOtpCodePageState extends State<VerifyOtpCodePage> {
|
||||||
|
late TextEditingController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_controller = TextEditingController();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
final defaultPinTheme = PinTheme(
|
||||||
|
height: 56,
|
||||||
|
width: 56,
|
||||||
|
textStyle: AppTextStyles.size18Medium,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: AppUtils.kBorderRadius8,
|
||||||
|
border: Border.all(color: Color.fromRGBO(234, 239, 243, 1)),
|
||||||
|
color: Color.fromRGBO(234, 234, 243, 1),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WLayout(
|
return BlocProvider(
|
||||||
top: false,
|
create: (context) => sl<VerifyOtpBloc>()..add(VerifyOtpEvent.started()),
|
||||||
child: Scaffold(body: WAuthBackground(child: Column())),
|
child: BlocConsumer<VerifyOtpBloc, VerifyOtpState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state.status.isLoaded()) {
|
||||||
|
if (widget.params.isRegister) {
|
||||||
|
context.push(Routes.register, extra: widget.params.phoneNumber);
|
||||||
|
} else {
|
||||||
|
context.push(
|
||||||
|
Routes.resetPassword,
|
||||||
|
extra: widget.params.phoneNumber,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, state) {
|
||||||
|
return WLayout(
|
||||||
|
top: false,
|
||||||
|
child: Scaffold(
|
||||||
|
body: WAuthBackground(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
40.verticalSpace,
|
||||||
|
Text(
|
||||||
|
"Enter the 5-digit code sent to you at ${widget.params.phoneNumber}",
|
||||||
|
style: AppTextStyles.size20Medium,
|
||||||
|
),
|
||||||
|
20.verticalSpace,
|
||||||
|
Pinput(
|
||||||
|
length: 5,
|
||||||
|
enabled: true,
|
||||||
|
controller: _controller,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
autofocus: true,
|
||||||
|
showCursor: true,
|
||||||
|
defaultPinTheme: defaultPinTheme,
|
||||||
|
|
||||||
|
focusedPinTheme: defaultPinTheme.copyWith(
|
||||||
|
decoration: defaultPinTheme.decoration!.copyWith(
|
||||||
|
color: Color.fromRGBO(234, 239, 243, 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
submittedPinTheme: defaultPinTheme.copyWith(
|
||||||
|
decoration: defaultPinTheme.decoration!.copyWith(
|
||||||
|
color: Color.fromRGBO(234, 239, 243, 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value.length == 5 && state.time > 0) {}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
10.verticalSpace,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text("You can resend otp after"),
|
||||||
|
|
||||||
|
if (state.time != 0)
|
||||||
|
Text(TimeFormatters.formatMinutesToTime(state.time)),
|
||||||
|
|
||||||
|
if (state.time == 0)
|
||||||
|
state.resendStatus.isLoading()
|
||||||
|
? CircularProgressIndicator.adaptive()
|
||||||
|
: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (widget.params.isRegister) {
|
||||||
|
context.read<VerifyOtpBloc>().add(
|
||||||
|
VerifyOtpEvent.resendRegister(
|
||||||
|
widget.params.phoneNumber,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.read<VerifyOtpBloc>().add(
|
||||||
|
VerifyOtpEvent.resendForgot(
|
||||||
|
widget.params.phoneNumber,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text("Resend"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
20.verticalSpace,
|
||||||
|
AppButton(
|
||||||
|
name: context.loc.continue_str,
|
||||||
|
onPressed: () {
|
||||||
|
if (_controller.text.trim().length == 5 &&
|
||||||
|
state.time > 0) {
|
||||||
|
if (widget.params.isRegister) {
|
||||||
|
context.read<VerifyOtpBloc>().add(
|
||||||
|
VerifyOtpEvent.verifyOtpRegister(
|
||||||
|
VerifyOtpCodeParams(
|
||||||
|
phoneNumber: widget.params.phoneNumber,
|
||||||
|
otpCode: _controller.text.trim().substring(
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.read<VerifyOtpBloc>().add(
|
||||||
|
VerifyOtpEvent.verifyOtpReset(
|
||||||
|
VerifyOtpCodeParams(
|
||||||
|
phoneNumber: widget.params.phoneNumber,
|
||||||
|
otpCode: _controller.text.trim().substring(
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backgroundColor: AppColors.c34A853,
|
||||||
|
borderRadius: 15,
|
||||||
|
trailing: SvgPicture.asset(
|
||||||
|
AppIcons.icArrowRightLight,
|
||||||
|
).paddingOnly(left: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingSymmetric(horizontal: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import 'package:food_delivery_client/core/helpers/formatters.dart';
|
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/domain/usecases/verify_otp_code_login_usecase.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/domain/usecases/verify_phone_login_usecase.dart';
|
||||||
|
import 'package:food_delivery_client/feature/auth/presentation/blocs/verify_phone_bloc/verify_phone_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';
|
||||||
@@ -31,6 +34,22 @@ class _VerifyPhoneNumberPageState extends State<VerifyPhoneNumberPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => sl<VerifyPhoneBloc>(),
|
||||||
|
child: BlocConsumer<VerifyPhoneBloc, VerifyPhoneState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state.status.isLoaded()) {
|
||||||
|
context.push(
|
||||||
|
Routes.verifyOtpCode,
|
||||||
|
extra: OtpCodePageParams(
|
||||||
|
phoneNumber:
|
||||||
|
"+998${_phoneNumberController.text.trim().replaceAll(" ", "")}",
|
||||||
|
isRegister: widget.isRegister,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, state) {
|
||||||
return Form(
|
return Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: WLayout(
|
child: WLayout(
|
||||||
@@ -72,7 +91,29 @@ class _VerifyPhoneNumberPageState extends State<VerifyPhoneNumberPage> {
|
|||||||
25.verticalSpace,
|
25.verticalSpace,
|
||||||
AppButton(
|
AppButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState?.validate() ?? false) {}
|
if (_formKey.currentState?.validate() ?? false) {
|
||||||
|
|
||||||
|
|
||||||
|
if (widget.isRegister) {
|
||||||
|
context.read<VerifyPhoneBloc>().add(
|
||||||
|
VerifyPhoneEvent.verifyPhoneRegister(
|
||||||
|
VerifyPhoneNumberParams(
|
||||||
|
phoneNumber:
|
||||||
|
"+998${_phoneNumberController.text.trim().replaceAll(" ", "")}",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.read<VerifyPhoneBloc>().add(
|
||||||
|
VerifyPhoneEvent.verifyPhoneReset(
|
||||||
|
VerifyPhoneNumberParams(
|
||||||
|
phoneNumber:
|
||||||
|
"+998${_phoneNumberController.text.trim().replaceAll(" ", "")}",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
name: context.loc.continue_str,
|
name: context.loc.continue_str,
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
@@ -92,5 +133,8 @@ class _VerifyPhoneNumberPageState extends State<VerifyPhoneNumberPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@@ -653,6 +653,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.1"
|
version: "7.0.1"
|
||||||
|
pinput:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: pinput
|
||||||
|
sha256: c41f42ee301505ae2375ec32871c985d3717bf8aee845620465b286e0140aad2
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.2"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -954,6 +962,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.2"
|
||||||
|
universal_platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: universal_platform
|
||||||
|
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ dependencies:
|
|||||||
equatable: ^2.0.7
|
equatable: ^2.0.7
|
||||||
dartz: ^0.10.1
|
dartz: ^0.10.1
|
||||||
mask_text_input_formatter: ^2.9.0
|
mask_text_input_formatter: ^2.9.0
|
||||||
|
pinput: ^5.0.2
|
||||||
|
|
||||||
#for notify user about error or success
|
#for notify user about error or success
|
||||||
toastification: ^3.0.3
|
toastification: ^3.0.3
|
||||||
|
|||||||
Reference in New Issue
Block a user