diff --git a/lib/application/auth/login_form/login_form_bloc.dart b/lib/application/auth/login_form/login_form_bloc.dart new file mode 100644 index 0000000..f14a8e1 --- /dev/null +++ b/lib/application/auth/login_form/login_form_bloc.dart @@ -0,0 +1,61 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/auth/auth.dart'; + +part 'login_form_event.dart'; +part 'login_form_state.dart'; +part 'login_form_bloc.freezed.dart'; + +@injectable +class LoginFormBloc extends Bloc { + final IAuthRepository _authRepository; + LoginFormBloc(this._authRepository) : super(LoginFormState.initial()) { + on(_onLoginFormEvent); + } + + Future _onLoginFormEvent( + LoginFormEvent event, + Emitter emit, + ) { + return event.map( + phoneNumberChanged: (e) async { + emit( + state.copyWith( + phoneNumber: e.phoneNumber, + failureOrLoginOption: none(), + ), + ); + }, + passwordChanged: (e) async { + emit( + state.copyWith(password: e.password, failureOrLoginOption: none()), + ); + }, + submitted: (e) async { + Either? failureOrLogin; + emit(state.copyWith(isSubmitting: true, failureOrLoginOption: none())); + + final phoneNumberValid = state.phoneNumber.isNotEmpty; + final passwordValid = state.password.isNotEmpty; + + if (phoneNumberValid && passwordValid) { + failureOrLogin = await _authRepository.login( + phoneNumber: state.phoneNumber, + password: state.password, + ); + + emit( + state.copyWith( + isSubmitting: false, + failureOrLoginOption: optionOf(failureOrLogin), + ), + ); + } + emit(state.copyWith(showErrorMessages: true, isSubmitting: false)); + }, + ); + } +} diff --git a/lib/application/auth/login_form/login_form_bloc.freezed.dart b/lib/application/auth/login_form/login_form_bloc.freezed.dart new file mode 100644 index 0000000..8387862 --- /dev/null +++ b/lib/application/auth/login_form/login_form_bloc.freezed.dart @@ -0,0 +1,740 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// 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 'login_form_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models', +); + +/// @nodoc +mixin _$LoginFormEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String phoneNumber) phoneNumberChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String phoneNumber)? phoneNumberChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String phoneNumber)? phoneNumberChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_PhoneNumberChanged value) phoneNumberChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoginFormEventCopyWith<$Res> { + factory $LoginFormEventCopyWith( + LoginFormEvent value, + $Res Function(LoginFormEvent) then, + ) = _$LoginFormEventCopyWithImpl<$Res, LoginFormEvent>; +} + +/// @nodoc +class _$LoginFormEventCopyWithImpl<$Res, $Val extends LoginFormEvent> + implements $LoginFormEventCopyWith<$Res> { + _$LoginFormEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$PhoneNumberChangedImplCopyWith<$Res> { + factory _$$PhoneNumberChangedImplCopyWith( + _$PhoneNumberChangedImpl value, + $Res Function(_$PhoneNumberChangedImpl) then, + ) = __$$PhoneNumberChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String phoneNumber}); +} + +/// @nodoc +class __$$PhoneNumberChangedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$PhoneNumberChangedImpl> + implements _$$PhoneNumberChangedImplCopyWith<$Res> { + __$$PhoneNumberChangedImplCopyWithImpl( + _$PhoneNumberChangedImpl _value, + $Res Function(_$PhoneNumberChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? phoneNumber = null}) { + return _then( + _$PhoneNumberChangedImpl( + null == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$PhoneNumberChangedImpl implements _PhoneNumberChanged { + const _$PhoneNumberChangedImpl(this.phoneNumber); + + @override + final String phoneNumber; + + @override + String toString() { + return 'LoginFormEvent.phoneNumberChanged(phoneNumber: $phoneNumber)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PhoneNumberChangedImpl && + (identical(other.phoneNumber, phoneNumber) || + other.phoneNumber == phoneNumber)); + } + + @override + int get hashCode => Object.hash(runtimeType, phoneNumber); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PhoneNumberChangedImplCopyWith<_$PhoneNumberChangedImpl> get copyWith => + __$$PhoneNumberChangedImplCopyWithImpl<_$PhoneNumberChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String phoneNumber) phoneNumberChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return phoneNumberChanged(phoneNumber); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String phoneNumber)? phoneNumberChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return phoneNumberChanged?.call(phoneNumber); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String phoneNumber)? phoneNumberChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (phoneNumberChanged != null) { + return phoneNumberChanged(phoneNumber); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_PhoneNumberChanged value) phoneNumberChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return phoneNumberChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return phoneNumberChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (phoneNumberChanged != null) { + return phoneNumberChanged(this); + } + return orElse(); + } +} + +abstract class _PhoneNumberChanged implements LoginFormEvent { + const factory _PhoneNumberChanged(final String phoneNumber) = + _$PhoneNumberChangedImpl; + + String get phoneNumber; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PhoneNumberChangedImplCopyWith<_$PhoneNumberChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$PasswordChangedImplCopyWith<$Res> { + factory _$$PasswordChangedImplCopyWith( + _$PasswordChangedImpl value, + $Res Function(_$PasswordChangedImpl) then, + ) = __$$PasswordChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String password}); +} + +/// @nodoc +class __$$PasswordChangedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$PasswordChangedImpl> + implements _$$PasswordChangedImplCopyWith<$Res> { + __$$PasswordChangedImplCopyWithImpl( + _$PasswordChangedImpl _value, + $Res Function(_$PasswordChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? password = null}) { + return _then( + _$PasswordChangedImpl( + null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$PasswordChangedImpl implements _PasswordChanged { + const _$PasswordChangedImpl(this.password); + + @override + final String password; + + @override + String toString() { + return 'LoginFormEvent.passwordChanged(password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PasswordChangedImpl && + (identical(other.password, password) || + other.password == password)); + } + + @override + int get hashCode => Object.hash(runtimeType, password); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith => + __$$PasswordChangedImplCopyWithImpl<_$PasswordChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String phoneNumber) phoneNumberChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return passwordChanged(password); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String phoneNumber)? phoneNumberChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return passwordChanged?.call(password); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String phoneNumber)? phoneNumberChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (passwordChanged != null) { + return passwordChanged(password); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_PhoneNumberChanged value) phoneNumberChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return passwordChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return passwordChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (passwordChanged != null) { + return passwordChanged(this); + } + return orElse(); + } +} + +abstract class _PasswordChanged implements LoginFormEvent { + const factory _PasswordChanged(final String password) = _$PasswordChangedImpl; + + String get password; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SubmittedImplCopyWith<$Res> { + factory _$$SubmittedImplCopyWith( + _$SubmittedImpl value, + $Res Function(_$SubmittedImpl) then, + ) = __$$SubmittedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SubmittedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$SubmittedImpl> + implements _$$SubmittedImplCopyWith<$Res> { + __$$SubmittedImplCopyWithImpl( + _$SubmittedImpl _value, + $Res Function(_$SubmittedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SubmittedImpl implements _Submitted { + const _$SubmittedImpl(); + + @override + String toString() { + return 'LoginFormEvent.submitted()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SubmittedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String phoneNumber) phoneNumberChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return submitted(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String phoneNumber)? phoneNumberChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return submitted?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String phoneNumber)? phoneNumberChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_PhoneNumberChanged value) phoneNumberChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return submitted(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return submitted?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_PhoneNumberChanged value)? phoneNumberChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(this); + } + return orElse(); + } +} + +abstract class _Submitted implements LoginFormEvent { + const factory _Submitted() = _$SubmittedImpl; +} + +/// @nodoc +mixin _$LoginFormState { + String get phoneNumber => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + Option> get failureOrLoginOption => + throw _privateConstructorUsedError; + bool get isSubmitting => throw _privateConstructorUsedError; + bool get showErrorMessages => throw _privateConstructorUsedError; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LoginFormStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoginFormStateCopyWith<$Res> { + factory $LoginFormStateCopyWith( + LoginFormState value, + $Res Function(LoginFormState) then, + ) = _$LoginFormStateCopyWithImpl<$Res, LoginFormState>; + @useResult + $Res call({ + String phoneNumber, + String password, + Option> failureOrLoginOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class _$LoginFormStateCopyWithImpl<$Res, $Val extends LoginFormState> + implements $LoginFormStateCopyWith<$Res> { + _$LoginFormStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? phoneNumber = null, + Object? password = null, + Object? failureOrLoginOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _value.copyWith( + phoneNumber: null == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + failureOrLoginOption: null == failureOrLoginOption + ? _value.failureOrLoginOption + : failureOrLoginOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$LoginFormStateImplCopyWith<$Res> + implements $LoginFormStateCopyWith<$Res> { + factory _$$LoginFormStateImplCopyWith( + _$LoginFormStateImpl value, + $Res Function(_$LoginFormStateImpl) then, + ) = __$$LoginFormStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String phoneNumber, + String password, + Option> failureOrLoginOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class __$$LoginFormStateImplCopyWithImpl<$Res> + extends _$LoginFormStateCopyWithImpl<$Res, _$LoginFormStateImpl> + implements _$$LoginFormStateImplCopyWith<$Res> { + __$$LoginFormStateImplCopyWithImpl( + _$LoginFormStateImpl _value, + $Res Function(_$LoginFormStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? phoneNumber = null, + Object? password = null, + Object? failureOrLoginOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _$LoginFormStateImpl( + phoneNumber: null == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + failureOrLoginOption: null == failureOrLoginOption + ? _value.failureOrLoginOption + : failureOrLoginOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$LoginFormStateImpl implements _LoginFormState { + const _$LoginFormStateImpl({ + required this.phoneNumber, + required this.password, + required this.failureOrLoginOption, + this.isSubmitting = false, + this.showErrorMessages = false, + }); + + @override + final String phoneNumber; + @override + final String password; + @override + final Option> failureOrLoginOption; + @override + @JsonKey() + final bool isSubmitting; + @override + @JsonKey() + final bool showErrorMessages; + + @override + String toString() { + return 'LoginFormState(phoneNumber: $phoneNumber, password: $password, failureOrLoginOption: $failureOrLoginOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LoginFormStateImpl && + (identical(other.phoneNumber, phoneNumber) || + other.phoneNumber == phoneNumber) && + (identical(other.password, password) || + other.password == password) && + (identical(other.failureOrLoginOption, failureOrLoginOption) || + other.failureOrLoginOption == failureOrLoginOption) && + (identical(other.isSubmitting, isSubmitting) || + other.isSubmitting == isSubmitting) && + (identical(other.showErrorMessages, showErrorMessages) || + other.showErrorMessages == showErrorMessages)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + phoneNumber, + password, + failureOrLoginOption, + isSubmitting, + showErrorMessages, + ); + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith => + __$$LoginFormStateImplCopyWithImpl<_$LoginFormStateImpl>( + this, + _$identity, + ); +} + +abstract class _LoginFormState implements LoginFormState { + const factory _LoginFormState({ + required final String phoneNumber, + required final String password, + required final Option> failureOrLoginOption, + final bool isSubmitting, + final bool showErrorMessages, + }) = _$LoginFormStateImpl; + + @override + String get phoneNumber; + @override + String get password; + @override + Option> get failureOrLoginOption; + @override + bool get isSubmitting; + @override + bool get showErrorMessages; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/auth/login_form/login_form_event.dart b/lib/application/auth/login_form/login_form_event.dart new file mode 100644 index 0000000..ca70b88 --- /dev/null +++ b/lib/application/auth/login_form/login_form_event.dart @@ -0,0 +1,10 @@ +part of 'login_form_bloc.dart'; + +@freezed +class LoginFormEvent with _$LoginFormEvent { + const factory LoginFormEvent.phoneNumberChanged(String phoneNumber) = + _PhoneNumberChanged; + const factory LoginFormEvent.passwordChanged(String password) = + _PasswordChanged; + const factory LoginFormEvent.submitted() = _Submitted; +} diff --git a/lib/application/auth/login_form/login_form_state.dart b/lib/application/auth/login_form/login_form_state.dart new file mode 100644 index 0000000..3f51301 --- /dev/null +++ b/lib/application/auth/login_form/login_form_state.dart @@ -0,0 +1,18 @@ +part of 'login_form_bloc.dart'; + +@freezed +class LoginFormState with _$LoginFormState { + const factory LoginFormState({ + required String phoneNumber, + required String password, + required Option> failureOrLoginOption, + @Default(false) bool isSubmitting, + @Default(false) bool showErrorMessages, + }) = _LoginFormState; + + factory LoginFormState.initial() => LoginFormState( + phoneNumber: '', + password: '', + failureOrLoginOption: none(), + ); +} diff --git a/lib/common/url/api_path.dart b/lib/common/url/api_path.dart index bc1ed58..d6d3a1c 100644 --- a/lib/common/url/api_path.dart +++ b/lib/common/url/api_path.dart @@ -3,4 +3,5 @@ class ApiPath { static String register = '/api/v1/customer-auth/register/start'; static String verify = '/api/v1/customer-auth/register/verify-otp'; static String setPassword = '/api/v1/customer-auth/register/set-password'; + static String login = '/api/v1/customer-auth/register/login'; } diff --git a/lib/domain/auth/repositories/i_auth_repository.dart b/lib/domain/auth/repositories/i_auth_repository.dart index 630add3..b6f62be 100644 --- a/lib/domain/auth/repositories/i_auth_repository.dart +++ b/lib/domain/auth/repositories/i_auth_repository.dart @@ -21,4 +21,9 @@ abstract class IAuthRepository { required String password, required String confirmPassword, }); + + Future> login({ + required String phoneNumber, + required String password, + }); } diff --git a/lib/infrastructure/auth/datasources/remote_data_provider.dart b/lib/infrastructure/auth/datasources/remote_data_provider.dart index a4af963..e65d2a8 100644 --- a/lib/infrastructure/auth/datasources/remote_data_provider.dart +++ b/lib/infrastructure/auth/datasources/remote_data_provider.dart @@ -183,4 +183,44 @@ class AuthRemoteDataProvider { return DC.error(AuthFailure.serverError(e)); } } + + Future> login({ + required String phoneNumber, + required String password, + }) async { + try { + final response = await _apiClient.post( + ApiPath.login, + data: {'phone_number': phoneNumber, 'password': password}, + ); + + if (response.data['success'] == false) { + if ((response.data['errors'] as List).isNotEmpty) { + if (response.data['errors'][0]['code'] == "900") { + return DC.error( + AuthFailure.dynamicErrorMessage('Kamu Belum Terdaftar'), + ); + } else { + return DC.error( + AuthFailure.dynamicErrorMessage( + 'Terjadi kesalahan coba lagi nanti', + ), + ); + } + } else { + return DC.error( + AuthFailure.dynamicErrorMessage( + 'Terjadi kesalahan coba lagi nanti', + ), + ); + } + } + + final dto = LoginDto.fromJson(response.data['data']); + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('login', name: _logName, error: e, stackTrace: s); + return DC.error(AuthFailure.serverError(e)); + } + } } diff --git a/lib/infrastructure/auth/repositories/auth_repository.dart b/lib/infrastructure/auth/repositories/auth_repository.dart index 33ddfcb..782b3b7 100644 --- a/lib/infrastructure/auth/repositories/auth_repository.dart +++ b/lib/infrastructure/auth/repositories/auth_repository.dart @@ -111,4 +111,28 @@ class AuthRepository implements IAuthRepository { return left(const AuthFailure.unexpectedError()); } } + + @override + Future> login({ + required String phoneNumber, + required String password, + }) async { + try { + final result = await _remoteDataProvider.login( + phoneNumber: phoneNumber, + password: password, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + return right(auth); + } catch (e, s) { + log('loginError', name: _logName, error: e, stackTrace: s); + return left(const AuthFailure.unexpectedError()); + } + } } diff --git a/lib/injection.config.dart b/lib/injection.config.dart index e984bfc..662589d 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -13,6 +13,8 @@ import 'package:connectivity_plus/connectivity_plus.dart' as _i895; import 'package:dio/dio.dart' as _i361; import 'package:enaklo/application/auth/check_phone_form/check_phone_form_bloc.dart' as _i869; +import 'package:enaklo/application/auth/login_form/login_form_bloc.dart' + as _i510; import 'package:enaklo/application/auth/register_form/register_form_bloc.dart' as _i260; import 'package:enaklo/application/auth/set_password/set_password_form_bloc.dart' @@ -71,6 +73,9 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i995.IAuthRepository>( () => _i879.AuthRepository(gh<_i818.AuthRemoteDataProvider>()), ); + gh.factory<_i510.LoginFormBloc>( + () => _i510.LoginFormBloc(gh<_i995.IAuthRepository>()), + ); gh.factory<_i869.CheckPhoneFormBloc>( () => _i869.CheckPhoneFormBloc(gh<_i995.IAuthRepository>()), );