Compare commits
19 Commits
onboarding
...
auth-recov
| Author | SHA1 | Date | |
|---|---|---|---|
| 4be6a30a33 | |||
| 69230c0dde | |||
| d7706bf639 | |||
| 8754884544 | |||
| 0e3fd8e6d5 | |||
| 4c46b2f498 | |||
| 0b2f1ff869 | |||
| 2c56d9fcb2 | |||
| efbdae81d4 | |||
| 0d8cb4bd37 | |||
| 6a9d68e945 | |||
| ea6a9741ee | |||
| f6e07192dc | |||
| ce062ec6e8 | |||
| 2e3681d36d | |||
| 098217f47a | |||
|
|
076951af24 | ||
| f8a3b038b6 | |||
|
|
0f30c7f422 |
31
.dart_tool/extension_discovery/README.md
Normal file
31
.dart_tool/extension_discovery/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Extension Discovery Cache
|
||||
=========================
|
||||
|
||||
This folder is used by `package:extension_discovery` to cache lists of
|
||||
packages that contains extensions for other packages.
|
||||
|
||||
DO NOT USE THIS FOLDER
|
||||
----------------------
|
||||
|
||||
* Do not read (or rely) the contents of this folder.
|
||||
* Do write to this folder.
|
||||
|
||||
If you're interested in the lists of extensions stored in this folder use the
|
||||
API offered by package `extension_discovery` to get this information.
|
||||
|
||||
If this package doesn't work for your use-case, then don't try to read the
|
||||
contents of this folder. It may change, and will not remain stable.
|
||||
|
||||
Use package `extension_discovery`
|
||||
---------------------------------
|
||||
|
||||
If you want to access information from this folder.
|
||||
|
||||
Feel free to delete this folder
|
||||
-------------------------------
|
||||
|
||||
Files in this folder act as a cache, and the cache is discarded if the files
|
||||
are older than the modification time of `.dart_tool/package_config.json`.
|
||||
|
||||
Hence, it should never be necessary to clear this cache manually, if you find a
|
||||
need to do please file a bug.
|
||||
1
.dart_tool/extension_discovery/vs_code.json
Normal file
1
.dart_tool/extension_discovery/vs_code.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version":2,"entries":[{"package":"sf_app_platform_mono_repo","rootUri":"../","packageUri":"lib/"}]}
|
||||
@@ -1 +1,2 @@
|
||||
API_BASE_URL=https://api-neki-b2b.neki.es/gateway/api/
|
||||
API_ORIGIN =https://neki-b2b.neki.es
|
||||
@@ -1,4 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<application
|
||||
android:label="sf_payments"
|
||||
android:name="${applicationName}"
|
||||
|
||||
1
apps/mobile_app/lib/config/env/env.dart
vendored
1
apps/mobile_app/lib/config/env/env.dart
vendored
@@ -2,6 +2,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
|
||||
class Env {
|
||||
static String get apiBaseUrl => dotenv.env['API_BASE_URL'] ?? '';
|
||||
static String get apiOrigin => dotenv.env['API_ORIGIN'] ?? '';
|
||||
|
||||
// static String get apiKey => dotenv.env['API_KEY'] ?? '';
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'env.dart';
|
||||
class QuestiaEnvConfig implements EnvConfig {
|
||||
@override
|
||||
String get apiBaseUrl => Env.apiBaseUrl;
|
||||
@override
|
||||
String get apiOrigin => Env.apiOrigin;
|
||||
|
||||
// @override
|
||||
// String get apiKey => Env.apiKey;
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:sf_app_platform/navigation/app_router.dart';
|
||||
import 'package:navigation/navigation_module.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
@@ -26,6 +27,8 @@ class PlatformApp extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
SizeUtils.init(context: context);
|
||||
|
||||
return MaterialApp.router(
|
||||
title: 'SaveFamily',
|
||||
theme: ThemeData(
|
||||
@@ -35,7 +38,8 @@ class PlatformApp extends ConsumerWidget {
|
||||
),
|
||||
routerConfig: appRouter,
|
||||
debugShowCheckedModeBanner: false,
|
||||
localizationsDelegates: const [
|
||||
localizationsDelegates: [
|
||||
// CountryLocalizations.getDelegate(enableLocalization: false),
|
||||
SFLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
|
||||
@@ -15,7 +15,7 @@ late final GoRouter appRouter;
|
||||
void configureAppRouter() {
|
||||
appRouter = GoRouter(
|
||||
navigatorKey: rootNavigatorKey,
|
||||
initialLocation: AppRoutes.linkPhone,
|
||||
initialLocation: AppRoutes.onboarding,
|
||||
debugLogDiagnostics: true,
|
||||
routes: [
|
||||
GoRoute(
|
||||
@@ -35,18 +35,18 @@ void configureAppRouter() {
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.linkPhone,
|
||||
name: 'link_phone',
|
||||
pageBuilder: LinkPhoneBuilder().buildPage,
|
||||
name: 'request_link_phone',
|
||||
pageBuilder: RequestLinkPhoneBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.phoneCode,
|
||||
name: 'phone_code',
|
||||
pageBuilder: PhoneCodeBuilder().buildPage,
|
||||
name: 'Verify_link_phone_code',
|
||||
pageBuilder: VerifyLinkPhoneCodeBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.recoverPassword,
|
||||
name: 'recover_password',
|
||||
pageBuilder: RecoverPasswordBuilder().buildPage,
|
||||
pageBuilder: RequestRecoveryBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.deviceSignup,
|
||||
|
||||
@@ -169,7 +169,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
country_code_picker:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: country_code_picker
|
||||
sha256: f0411f4833b6f98e8b7215f4fa3813bcc88e50f13925f70a170dbd36e3e447f5
|
||||
@@ -448,14 +448,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
intl_phone_field_v2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl_phone_field_v2
|
||||
sha256: b1e5077e31cc8705639a69b2e0410a8ecc858c3e518726d99b378b6c35adfefb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.5"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -480,6 +472,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
json_serializable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_serializable
|
||||
sha256: c5b2ee75210a0f263c6c7b9eeea80553dbae96ea1bf57f02484e806a3ffdffa3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.11.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -838,6 +838,14 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.2"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -59,6 +59,8 @@ dependencies:
|
||||
path: ../../packages/fonts
|
||||
sf_infrastructure:
|
||||
path: ../../packages/sf_infrastructure
|
||||
utils:
|
||||
path: ../../packages/utils
|
||||
|
||||
#dependencies go here
|
||||
cupertino_icons: ^1.0.8
|
||||
@@ -66,6 +68,7 @@ dependencies:
|
||||
go_router_builder: ^4.1.1
|
||||
build_runner: ^2.7.1
|
||||
flutter_dotenv: ^6.0.0
|
||||
country_code_picker: ^3.4.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export 'src/features/device_sign_up/link_watch/create_profile_screen.dart';
|
||||
export 'src/features/onboarding/onboarding_builder.dart';
|
||||
export 'src/features/link_phone/link_phone_builder.dart';
|
||||
export 'src/features/login/phone_code_builder.dart';
|
||||
export 'src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart';
|
||||
export 'src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart';
|
||||
export 'src/features/login/login_builder.dart';
|
||||
export 'src/features/recover_password/recover_password_builder.dart';
|
||||
export 'src/features/recover_password/presentation/request_recovery/request_recovery_builder.dart';
|
||||
export 'src/features/device_sign_up/device_signup_builder.dart';
|
||||
export 'src/features/sign_up/signup_builder.dart';
|
||||
export 'src/features/sign_up/sign_up_builder.dart';
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
|
||||
abstract class AuthRemoteDatasource {
|
||||
Future<void> requestPhoneCode({required String phone});
|
||||
|
||||
Future<void> verifyPhoneCode({required String phone, required String code});
|
||||
|
||||
Future<String> login({required String email, required String password});
|
||||
|
||||
Future<void> twoFALogin({required String token, required String code});
|
||||
Future<String> signUp({required SignUpRequestEntity request});
|
||||
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token});
|
||||
Future<void> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
});
|
||||
Future<String> requestPasswordReset({String? phone, String? email});
|
||||
|
||||
Future<void> recoverPassword({required newPassword, required token});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:auth/src/core/data/models/sign_up_request_model.dart';
|
||||
import 'package:auth/src/core/data/models/sign_up_response_model.dart';
|
||||
import 'package:auth/src/core/data/models/two_fa_secret_response_model.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
import 'auth_remote_datasource.dart';
|
||||
@@ -16,7 +24,10 @@ class AuthRemoteDatasourceImpl implements AuthRemoteDatasource {
|
||||
body: <String, dynamic>{'phone': phone},
|
||||
);
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error al solicitar el código');
|
||||
throw _mapDioError(
|
||||
error,
|
||||
defaultMessage: error.response?.data ?? 'Error to request phone code',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,23 +42,206 @@ class AuthRemoteDatasourceImpl implements AuthRemoteDatasource {
|
||||
body: <String, dynamic>{'phone': phone, 'code': code},
|
||||
);
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error al verificar el código');
|
||||
throw _mapDioError(error, defaultMessage: 'Error in verification code');
|
||||
}
|
||||
}
|
||||
|
||||
Exception _mapDioError(DioException error, {required String defaultMessage}) {
|
||||
final responseData = error.response?.data;
|
||||
String message = defaultMessage;
|
||||
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
final serverMessage = responseData['message'];
|
||||
if (serverMessage is String && serverMessage.isNotEmpty) {
|
||||
message = serverMessage;
|
||||
}
|
||||
} else if (error.message != null && error.message!.isNotEmpty) {
|
||||
message = error.message!;
|
||||
@override
|
||||
Future<String> login({
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _repository.post<Map<String, dynamic>>(
|
||||
'/auth/login',
|
||||
body: <String, dynamic>{'email': email, 'password': password},
|
||||
);
|
||||
final token = response.data!['token'];
|
||||
return token;
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(
|
||||
error,
|
||||
defaultMessage: error.message ?? 'Error in login',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Exception(message);
|
||||
@override
|
||||
Future<String> twoFALogin({
|
||||
required String token,
|
||||
required String code,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _repository.post<String>(
|
||||
'/auth/totp/login',
|
||||
body: <String, dynamic>{
|
||||
'token': token,
|
||||
'code': code,
|
||||
'rememberMe': true,
|
||||
},
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /auth/totp/login');
|
||||
}
|
||||
|
||||
return data;
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error in twoFALogin');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> signUp({required SignUpRequestEntity request}) async {
|
||||
try {
|
||||
final body = request.toModel().toJson();
|
||||
debugPrint(body.toString());
|
||||
debugPrint(const JsonEncoder.withIndent(' ').convert(body));
|
||||
|
||||
final response = await _repository.post<Map<String, dynamic>>(
|
||||
'/payment-profiles/signup',
|
||||
body: body,
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /payment-profiles/signup');
|
||||
}
|
||||
|
||||
final parsed = SignUpResponseModel.fromJson(data);
|
||||
|
||||
if (!parsed.isCreated) {
|
||||
throw Exception('Sign up failed: isCreated=false');
|
||||
}
|
||||
|
||||
final token = parsed.item.token.trim();
|
||||
if (token.isEmpty) {
|
||||
throw Exception('Sign up response has empty token');
|
||||
}
|
||||
|
||||
return token;
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error in signUp');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token}) async {
|
||||
try {
|
||||
final response = await _repository.post<Map<String, dynamic>>(
|
||||
'/auth/totp/secret',
|
||||
body: <String, dynamic>{'token': token},
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /auth/totp/secret');
|
||||
}
|
||||
|
||||
final model = TwoFASecretResponseModel.fromJson(data);
|
||||
return model.toEntity();
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error in twoFASignUp');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _repository.post<String>(
|
||||
'/auth/totp/code',
|
||||
body: <String, dynamic>{'token': token, 'code': code},
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /auth/totp/code');
|
||||
}
|
||||
|
||||
return data;
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error in twoFaCodeSignUp');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestPasswordReset({
|
||||
String? phone,
|
||||
String? email
|
||||
}) async {
|
||||
try {
|
||||
if (phone == null && email == null) {
|
||||
throw FormatException("No phone or email address given");
|
||||
}
|
||||
|
||||
// late final Map<String, dynamic> body;
|
||||
if (email != null) {
|
||||
// body = {'email': email};
|
||||
return 'ec14b7e7-58dd-4a59-9f41-0da86eaabf14';
|
||||
} else {
|
||||
// body = {'phone': phone!};
|
||||
return 'ec14b7e7-58dd-4a59-9f41-0da86eaabf14';
|
||||
// throw Exception("reset by phone is not currently implemented");
|
||||
}
|
||||
/*final response = await _repository.put<Map<String, dynamic>>(
|
||||
'/auth/reset-password',
|
||||
body: body,
|
||||
);
|
||||
final token = response.data!['token'];
|
||||
return token;*/
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error to request password reset');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({required newPassword, required token}) async {
|
||||
try {
|
||||
await _repository.put<void>(
|
||||
'/auth/recovery-password',
|
||||
body: <String, dynamic>{'newPassword': newPassword, 'token': token},
|
||||
);
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error to request password recovery');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exception _mapDioError(DioException error, {required String defaultMessage}) {
|
||||
final apiMsg = _extractApiMessage(error.response?.data);
|
||||
final msg = apiMsg ?? error.message ?? defaultMessage;
|
||||
return Exception(msg);
|
||||
}
|
||||
|
||||
String? _extractApiMessage(Object? data) {
|
||||
if (data == null) return null;
|
||||
|
||||
if (data is Map) {
|
||||
final errorObj = data['error'];
|
||||
if (errorObj is Map && errorObj['message'] is String) {
|
||||
return (errorObj['message'] as String).trim();
|
||||
}
|
||||
if (data['message'] is String) {
|
||||
return (data['message'] as String).trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data is String) {
|
||||
final raw = data.trim();
|
||||
if (raw.isEmpty) return null;
|
||||
|
||||
try {
|
||||
final decoded = jsonDecode(raw);
|
||||
return _extractApiMessage(decoded);
|
||||
} catch (_) {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
31
modules/auth/lib/src/core/data/models/address_model.dart
Normal file
31
modules/auth/lib/src/core/data/models/address_model.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/address_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'address_model.freezed.dart';
|
||||
part 'address_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class AddressModel with _$AddressModel {
|
||||
const factory AddressModel({
|
||||
required String street,
|
||||
required String city,
|
||||
required String province,
|
||||
required String state,
|
||||
required String country,
|
||||
required int postCode,
|
||||
}) = _AddressModel;
|
||||
|
||||
factory AddressModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$AddressModelFromJson(json);
|
||||
}
|
||||
|
||||
extension AddressModelMapper on AddressEntity {
|
||||
AddressModel toModel() => AddressModel(
|
||||
street: street,
|
||||
city: city,
|
||||
province: province,
|
||||
state: state,
|
||||
country: country,
|
||||
postCode: postCode,
|
||||
);
|
||||
}
|
||||
292
modules/auth/lib/src/core/data/models/address_model.freezed.dart
Normal file
292
modules/auth/lib/src/core/data/models/address_model.freezed.dart
Normal file
@@ -0,0 +1,292 @@
|
||||
// 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 'address_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AddressModel {
|
||||
|
||||
String get street; String get city; String get province; String get state; String get country; int get postCode;
|
||||
/// Create a copy of AddressModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AddressModelCopyWith<AddressModel> get copyWith => _$AddressModelCopyWithImpl<AddressModel>(this as AddressModel, _$identity);
|
||||
|
||||
/// Serializes this AddressModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AddressModel&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressModel(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AddressModelCopyWith<$Res> {
|
||||
factory $AddressModelCopyWith(AddressModel value, $Res Function(AddressModel) _then) = _$AddressModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AddressModelCopyWithImpl<$Res>
|
||||
implements $AddressModelCopyWith<$Res> {
|
||||
_$AddressModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AddressModel _self;
|
||||
final $Res Function(AddressModel) _then;
|
||||
|
||||
/// Create a copy of AddressModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: null == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AddressModel].
|
||||
extension AddressModelPatterns on AddressModel {
|
||||
/// 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( _AddressModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel() 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( _AddressModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel():
|
||||
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( _AddressModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel() 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( String street, String city, String province, String state, String country, int postCode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int postCode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel():
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int postCode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressModel() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _AddressModel implements AddressModel {
|
||||
const _AddressModel({required this.street, required this.city, required this.province, required this.state, required this.country, required this.postCode});
|
||||
factory _AddressModel.fromJson(Map<String, dynamic> json) => _$AddressModelFromJson(json);
|
||||
|
||||
@override final String street;
|
||||
@override final String city;
|
||||
@override final String province;
|
||||
@override final String state;
|
||||
@override final String country;
|
||||
@override final int postCode;
|
||||
|
||||
/// Create a copy of AddressModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AddressModelCopyWith<_AddressModel> get copyWith => __$AddressModelCopyWithImpl<_AddressModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$AddressModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AddressModel&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressModel(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AddressModelCopyWith<$Res> implements $AddressModelCopyWith<$Res> {
|
||||
factory _$AddressModelCopyWith(_AddressModel value, $Res Function(_AddressModel) _then) = __$AddressModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AddressModelCopyWithImpl<$Res>
|
||||
implements _$AddressModelCopyWith<$Res> {
|
||||
__$AddressModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AddressModel _self;
|
||||
final $Res Function(_AddressModel) _then;
|
||||
|
||||
/// Create a copy of AddressModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = null,}) {
|
||||
return _then(_AddressModel(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: null == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
27
modules/auth/lib/src/core/data/models/address_model.g.dart
Normal file
27
modules/auth/lib/src/core/data/models/address_model.g.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'address_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_AddressModel _$AddressModelFromJson(Map<String, dynamic> json) =>
|
||||
_AddressModel(
|
||||
street: json['street'] as String,
|
||||
city: json['city'] as String,
|
||||
province: json['province'] as String,
|
||||
state: json['state'] as String,
|
||||
country: json['country'] as String,
|
||||
postCode: (json['postCode'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AddressModelToJson(_AddressModel instance) =>
|
||||
<String, dynamic>{
|
||||
'street': instance.street,
|
||||
'city': instance.city,
|
||||
'province': instance.province,
|
||||
'state': instance.state,
|
||||
'country': instance.country,
|
||||
'postCode': instance.postCode,
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'address_model.dart';
|
||||
|
||||
part 'sign_up_request_model.freezed.dart';
|
||||
part 'sign_up_request_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class SignUpRequestModel with _$SignUpRequestModel {
|
||||
const factory SignUpRequestModel({
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required String email,
|
||||
required String phone,
|
||||
required String language,
|
||||
required String password,
|
||||
required List<AddressModel> taxResidences,
|
||||
required List<AddressModel> addresses,
|
||||
required int bornAt,
|
||||
required String userId,
|
||||
required String placeOfBirth,
|
||||
required String birthCountry,
|
||||
// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'document') required String documentNumber,
|
||||
required String documentType,
|
||||
// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'relationType') required String relationship,
|
||||
}) = _SignUpRequestModel;
|
||||
|
||||
factory SignUpRequestModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$SignUpRequestModelFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'document')
|
||||
String get documentNumber;
|
||||
@override
|
||||
@JsonKey(name: 'relationType')
|
||||
String get relationship;
|
||||
}
|
||||
|
||||
extension SignUpRequestModelMapper on SignUpRequestEntity {
|
||||
SignUpRequestModel toModel() => SignUpRequestModel(
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
email: email,
|
||||
phone: phone,
|
||||
language: language,
|
||||
password: password,
|
||||
taxResidences: taxResidences
|
||||
.map((e) => e.toModel())
|
||||
.toList(growable: false),
|
||||
addresses: addresses.map((e) => e.toModel()).toList(growable: false),
|
||||
bornAt: bornAt,
|
||||
userId: userId,
|
||||
placeOfBirth: placeOfBirth,
|
||||
birthCountry: birthCountry,
|
||||
documentNumber: documentNumber,
|
||||
documentType: documentType,
|
||||
relationship: relationship,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
// 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 'sign_up_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SignUpRequestModel {
|
||||
|
||||
String get firstName; String get lastName; String get email; String get phone; String get language; String get password; List<AddressModel> get taxResidences; List<AddressModel> get addresses; int get bornAt; String get userId; String get placeOfBirth; String get birthCountry;// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'document') String get documentNumber; String get documentType;// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'relationType') String get relationship;
|
||||
/// Create a copy of SignUpRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpRequestModelCopyWith<SignUpRequestModel> get copyWith => _$SignUpRequestModelCopyWithImpl<SignUpRequestModel>(this as SignUpRequestModel, _$identity);
|
||||
|
||||
/// Serializes this SignUpRequestModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SignUpRequestModel&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.language, language) || other.language == language)&&(identical(other.password, password) || other.password == password)&&const DeepCollectionEquality().equals(other.taxResidences, taxResidences)&&const DeepCollectionEquality().equals(other.addresses, addresses)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.relationship, relationship) || other.relationship == relationship));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(taxResidences),const DeepCollectionEquality().hash(addresses),bornAt,userId,placeOfBirth,birthCountry,documentNumber,documentType,relationship);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpRequestModel(firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, documentNumber: $documentNumber, documentType: $documentType, relationship: $relationship)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SignUpRequestModelCopyWith<$Res> {
|
||||
factory $SignUpRequestModelCopyWith(SignUpRequestModel value, $Res Function(SignUpRequestModel) _then) = _$SignUpRequestModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String firstName, String lastName, String email, String phone, String language, String password, List<AddressModel> taxResidences, List<AddressModel> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry,@JsonKey(name: 'document') String documentNumber, String documentType,@JsonKey(name: 'relationType') String relationship
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SignUpRequestModelCopyWithImpl<$Res>
|
||||
implements $SignUpRequestModelCopyWith<$Res> {
|
||||
_$SignUpRequestModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SignUpRequestModel _self;
|
||||
final $Res Function(SignUpRequestModel) _then;
|
||||
|
||||
/// Create a copy of SignUpRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? language = null,Object? password = null,Object? taxResidences = null,Object? addresses = null,Object? bornAt = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,Object? documentNumber = null,Object? documentType = null,Object? relationship = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,taxResidences: null == taxResidences ? _self.taxResidences : taxResidences // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressModel>,addresses: null == addresses ? _self.addresses : addresses // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressModel>,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SignUpRequestModel].
|
||||
extension SignUpRequestModelPatterns on SignUpRequestModel {
|
||||
/// 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( _SignUpRequestModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel() 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( _SignUpRequestModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel():
|
||||
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( _SignUpRequestModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel() 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( String firstName, String lastName, String email, String phone, String language, String password, List<AddressModel> taxResidences, List<AddressModel> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry, @JsonKey(name: 'document') String documentNumber, String documentType, @JsonKey(name: 'relationType') String relationship)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel() when $default != null:
|
||||
return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.documentNumber,_that.documentType,_that.relationship);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( String firstName, String lastName, String email, String phone, String language, String password, List<AddressModel> taxResidences, List<AddressModel> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry, @JsonKey(name: 'document') String documentNumber, String documentType, @JsonKey(name: 'relationType') String relationship) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel():
|
||||
return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.documentNumber,_that.documentType,_that.relationship);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( String firstName, String lastName, String email, String phone, String language, String password, List<AddressModel> taxResidences, List<AddressModel> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry, @JsonKey(name: 'document') String documentNumber, String documentType, @JsonKey(name: 'relationType') String relationship)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestModel() when $default != null:
|
||||
return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.documentNumber,_that.documentType,_that.relationship);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SignUpRequestModel implements SignUpRequestModel {
|
||||
const _SignUpRequestModel({required this.firstName, required this.lastName, required this.email, required this.phone, required this.language, required this.password, required final List<AddressModel> taxResidences, required final List<AddressModel> addresses, required this.bornAt, required this.userId, required this.placeOfBirth, required this.birthCountry, @JsonKey(name: 'document') required this.documentNumber, required this.documentType, @JsonKey(name: 'relationType') required this.relationship}): _taxResidences = taxResidences,_addresses = addresses;
|
||||
factory _SignUpRequestModel.fromJson(Map<String, dynamic> json) => _$SignUpRequestModelFromJson(json);
|
||||
|
||||
@override final String firstName;
|
||||
@override final String lastName;
|
||||
@override final String email;
|
||||
@override final String phone;
|
||||
@override final String language;
|
||||
@override final String password;
|
||||
final List<AddressModel> _taxResidences;
|
||||
@override List<AddressModel> get taxResidences {
|
||||
if (_taxResidences is EqualUnmodifiableListView) return _taxResidences;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_taxResidences);
|
||||
}
|
||||
|
||||
final List<AddressModel> _addresses;
|
||||
@override List<AddressModel> get addresses {
|
||||
if (_addresses is EqualUnmodifiableListView) return _addresses;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_addresses);
|
||||
}
|
||||
|
||||
@override final int bornAt;
|
||||
@override final String userId;
|
||||
@override final String placeOfBirth;
|
||||
@override final String birthCountry;
|
||||
// ignore: invalid_annotation_target
|
||||
@override@JsonKey(name: 'document') final String documentNumber;
|
||||
@override final String documentType;
|
||||
// ignore: invalid_annotation_target
|
||||
@override@JsonKey(name: 'relationType') final String relationship;
|
||||
|
||||
/// Create a copy of SignUpRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SignUpRequestModelCopyWith<_SignUpRequestModel> get copyWith => __$SignUpRequestModelCopyWithImpl<_SignUpRequestModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SignUpRequestModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SignUpRequestModel&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.language, language) || other.language == language)&&(identical(other.password, password) || other.password == password)&&const DeepCollectionEquality().equals(other._taxResidences, _taxResidences)&&const DeepCollectionEquality().equals(other._addresses, _addresses)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.relationship, relationship) || other.relationship == relationship));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(_taxResidences),const DeepCollectionEquality().hash(_addresses),bornAt,userId,placeOfBirth,birthCountry,documentNumber,documentType,relationship);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpRequestModel(firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, documentNumber: $documentNumber, documentType: $documentType, relationship: $relationship)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SignUpRequestModelCopyWith<$Res> implements $SignUpRequestModelCopyWith<$Res> {
|
||||
factory _$SignUpRequestModelCopyWith(_SignUpRequestModel value, $Res Function(_SignUpRequestModel) _then) = __$SignUpRequestModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String firstName, String lastName, String email, String phone, String language, String password, List<AddressModel> taxResidences, List<AddressModel> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry,@JsonKey(name: 'document') String documentNumber, String documentType,@JsonKey(name: 'relationType') String relationship
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SignUpRequestModelCopyWithImpl<$Res>
|
||||
implements _$SignUpRequestModelCopyWith<$Res> {
|
||||
__$SignUpRequestModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SignUpRequestModel _self;
|
||||
final $Res Function(_SignUpRequestModel) _then;
|
||||
|
||||
/// Create a copy of SignUpRequestModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? language = null,Object? password = null,Object? taxResidences = null,Object? addresses = null,Object? bornAt = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,Object? documentNumber = null,Object? documentType = null,Object? relationship = null,}) {
|
||||
return _then(_SignUpRequestModel(
|
||||
firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,taxResidences: null == taxResidences ? _self._taxResidences : taxResidences // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressModel>,addresses: null == addresses ? _self._addresses : addresses // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressModel>,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,49 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sign_up_request_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SignUpRequestModel _$SignUpRequestModelFromJson(Map<String, dynamic> json) =>
|
||||
_SignUpRequestModel(
|
||||
firstName: json['firstName'] as String,
|
||||
lastName: json['lastName'] as String,
|
||||
email: json['email'] as String,
|
||||
phone: json['phone'] as String,
|
||||
language: json['language'] as String,
|
||||
password: json['password'] as String,
|
||||
taxResidences: (json['taxResidences'] as List<dynamic>)
|
||||
.map((e) => AddressModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
addresses: (json['addresses'] as List<dynamic>)
|
||||
.map((e) => AddressModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
bornAt: (json['bornAt'] as num).toInt(),
|
||||
userId: json['userId'] as String,
|
||||
placeOfBirth: json['placeOfBirth'] as String,
|
||||
birthCountry: json['birthCountry'] as String,
|
||||
documentNumber: json['document'] as String,
|
||||
documentType: json['documentType'] as String,
|
||||
relationship: json['relationType'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SignUpRequestModelToJson(_SignUpRequestModel instance) =>
|
||||
<String, dynamic>{
|
||||
'firstName': instance.firstName,
|
||||
'lastName': instance.lastName,
|
||||
'email': instance.email,
|
||||
'phone': instance.phone,
|
||||
'language': instance.language,
|
||||
'password': instance.password,
|
||||
'taxResidences': instance.taxResidences,
|
||||
'addresses': instance.addresses,
|
||||
'bornAt': instance.bornAt,
|
||||
'userId': instance.userId,
|
||||
'placeOfBirth': instance.placeOfBirth,
|
||||
'birthCountry': instance.birthCountry,
|
||||
'document': instance.documentNumber,
|
||||
'documentType': instance.documentType,
|
||||
'relationType': instance.relationship,
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'sign_up_response_model.freezed.dart';
|
||||
part 'sign_up_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class SignUpResponseModel with _$SignUpResponseModel {
|
||||
const factory SignUpResponseModel({
|
||||
required bool isCreated,
|
||||
required SignUpResponseItemModel item,
|
||||
}) = _SignUpResponseModel;
|
||||
|
||||
factory SignUpResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$SignUpResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class SignUpResponseItemModel with _$SignUpResponseItemModel {
|
||||
const factory SignUpResponseItemModel({required String token}) =
|
||||
_SignUpResponseItemModel;
|
||||
|
||||
factory SignUpResponseItemModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$SignUpResponseItemModelFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,561 @@
|
||||
// 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 'sign_up_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SignUpResponseModel {
|
||||
|
||||
bool get isCreated; SignUpResponseItemModel get item;
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpResponseModelCopyWith<SignUpResponseModel> get copyWith => _$SignUpResponseModelCopyWithImpl<SignUpResponseModel>(this as SignUpResponseModel, _$identity);
|
||||
|
||||
/// Serializes this SignUpResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SignUpResponseModel&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpResponseModel(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SignUpResponseModelCopyWith<$Res> {
|
||||
factory $SignUpResponseModelCopyWith(SignUpResponseModel value, $Res Function(SignUpResponseModel) _then) = _$SignUpResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isCreated, SignUpResponseItemModel item
|
||||
});
|
||||
|
||||
|
||||
$SignUpResponseItemModelCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SignUpResponseModelCopyWithImpl<$Res>
|
||||
implements $SignUpResponseModelCopyWith<$Res> {
|
||||
_$SignUpResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SignUpResponseModel _self;
|
||||
final $Res Function(SignUpResponseModel) _then;
|
||||
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as SignUpResponseItemModel,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpResponseItemModelCopyWith<$Res> get item {
|
||||
|
||||
return $SignUpResponseItemModelCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SignUpResponseModel].
|
||||
extension SignUpResponseModelPatterns on SignUpResponseModel {
|
||||
/// 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( _SignUpResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel() 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( _SignUpResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel():
|
||||
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( _SignUpResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel() 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( bool isCreated, SignUpResponseItemModel item)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, SignUpResponseItemModel item) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel():
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, SignUpResponseItemModel item)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseModel() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SignUpResponseModel implements SignUpResponseModel {
|
||||
const _SignUpResponseModel({required this.isCreated, required this.item});
|
||||
factory _SignUpResponseModel.fromJson(Map<String, dynamic> json) => _$SignUpResponseModelFromJson(json);
|
||||
|
||||
@override final bool isCreated;
|
||||
@override final SignUpResponseItemModel item;
|
||||
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SignUpResponseModelCopyWith<_SignUpResponseModel> get copyWith => __$SignUpResponseModelCopyWithImpl<_SignUpResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SignUpResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SignUpResponseModel&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpResponseModel(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SignUpResponseModelCopyWith<$Res> implements $SignUpResponseModelCopyWith<$Res> {
|
||||
factory _$SignUpResponseModelCopyWith(_SignUpResponseModel value, $Res Function(_SignUpResponseModel) _then) = __$SignUpResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isCreated, SignUpResponseItemModel item
|
||||
});
|
||||
|
||||
|
||||
@override $SignUpResponseItemModelCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SignUpResponseModelCopyWithImpl<$Res>
|
||||
implements _$SignUpResponseModelCopyWith<$Res> {
|
||||
__$SignUpResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SignUpResponseModel _self;
|
||||
final $Res Function(_SignUpResponseModel) _then;
|
||||
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_SignUpResponseModel(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as SignUpResponseItemModel,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SignUpResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpResponseItemModelCopyWith<$Res> get item {
|
||||
|
||||
return $SignUpResponseItemModelCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SignUpResponseItemModel {
|
||||
|
||||
String get token;
|
||||
/// Create a copy of SignUpResponseItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpResponseItemModelCopyWith<SignUpResponseItemModel> get copyWith => _$SignUpResponseItemModelCopyWithImpl<SignUpResponseItemModel>(this as SignUpResponseItemModel, _$identity);
|
||||
|
||||
/// Serializes this SignUpResponseItemModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SignUpResponseItemModel&&(identical(other.token, token) || other.token == token));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,token);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpResponseItemModel(token: $token)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SignUpResponseItemModelCopyWith<$Res> {
|
||||
factory $SignUpResponseItemModelCopyWith(SignUpResponseItemModel value, $Res Function(SignUpResponseItemModel) _then) = _$SignUpResponseItemModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String token
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SignUpResponseItemModelCopyWithImpl<$Res>
|
||||
implements $SignUpResponseItemModelCopyWith<$Res> {
|
||||
_$SignUpResponseItemModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SignUpResponseItemModel _self;
|
||||
final $Res Function(SignUpResponseItemModel) _then;
|
||||
|
||||
/// Create a copy of SignUpResponseItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? token = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SignUpResponseItemModel].
|
||||
extension SignUpResponseItemModelPatterns on SignUpResponseItemModel {
|
||||
/// 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( _SignUpResponseItemModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel() 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( _SignUpResponseItemModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel():
|
||||
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( _SignUpResponseItemModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel() 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( String token)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel() when $default != null:
|
||||
return $default(_that.token);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( String token) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel():
|
||||
return $default(_that.token);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( String token)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpResponseItemModel() when $default != null:
|
||||
return $default(_that.token);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SignUpResponseItemModel implements SignUpResponseItemModel {
|
||||
const _SignUpResponseItemModel({required this.token});
|
||||
factory _SignUpResponseItemModel.fromJson(Map<String, dynamic> json) => _$SignUpResponseItemModelFromJson(json);
|
||||
|
||||
@override final String token;
|
||||
|
||||
/// Create a copy of SignUpResponseItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SignUpResponseItemModelCopyWith<_SignUpResponseItemModel> get copyWith => __$SignUpResponseItemModelCopyWithImpl<_SignUpResponseItemModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SignUpResponseItemModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SignUpResponseItemModel&&(identical(other.token, token) || other.token == token));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,token);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpResponseItemModel(token: $token)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SignUpResponseItemModelCopyWith<$Res> implements $SignUpResponseItemModelCopyWith<$Res> {
|
||||
factory _$SignUpResponseItemModelCopyWith(_SignUpResponseItemModel value, $Res Function(_SignUpResponseItemModel) _then) = __$SignUpResponseItemModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String token
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SignUpResponseItemModelCopyWithImpl<$Res>
|
||||
implements _$SignUpResponseItemModelCopyWith<$Res> {
|
||||
__$SignUpResponseItemModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SignUpResponseItemModel _self;
|
||||
final $Res Function(_SignUpResponseItemModel) _then;
|
||||
|
||||
/// Create a copy of SignUpResponseItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? token = null,}) {
|
||||
return _then(_SignUpResponseItemModel(
|
||||
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sign_up_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SignUpResponseModel _$SignUpResponseModelFromJson(Map<String, dynamic> json) =>
|
||||
_SignUpResponseModel(
|
||||
isCreated: json['isCreated'] as bool,
|
||||
item: SignUpResponseItemModel.fromJson(
|
||||
json['item'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SignUpResponseModelToJson(
|
||||
_SignUpResponseModel instance,
|
||||
) => <String, dynamic>{'isCreated': instance.isCreated, 'item': instance.item};
|
||||
|
||||
_SignUpResponseItemModel _$SignUpResponseItemModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _SignUpResponseItemModel(token: json['token'] as String);
|
||||
|
||||
Map<String, dynamic> _$SignUpResponseItemModelToJson(
|
||||
_SignUpResponseItemModel instance,
|
||||
) => <String, dynamic>{'token': instance.token};
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'two_fa_secret_response_model.freezed.dart';
|
||||
part 'two_fa_secret_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class TwoFASecretResponseModel with _$TwoFASecretResponseModel {
|
||||
const factory TwoFASecretResponseModel({
|
||||
required bool isCreated,
|
||||
required TwoFASecretItemResponseModel item,
|
||||
}) = _TwoFASecretResponseModel;
|
||||
|
||||
factory TwoFASecretResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$TwoFASecretResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class TwoFASecretItemResponseModel
|
||||
with _$TwoFASecretItemResponseModel {
|
||||
const factory TwoFASecretItemResponseModel({
|
||||
required String secret,
|
||||
required String qr,
|
||||
}) = _TwoFASecretItemResponseModel;
|
||||
|
||||
factory TwoFASecretItemResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$TwoFASecretItemResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
extension TwoFASecretResponseModelMapper on TwoFASecretResponseModel {
|
||||
TwoFASecretEntity toEntity() {
|
||||
return TwoFASecretEntity(
|
||||
isCreated: isCreated,
|
||||
item: TwoFASecretItemEntity(secret: item.secret, qr: item.qr),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
// 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 'two_fa_secret_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TwoFASecretResponseModel {
|
||||
|
||||
bool get isCreated; TwoFASecretItemResponseModel get item;
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretResponseModelCopyWith<TwoFASecretResponseModel> get copyWith => _$TwoFASecretResponseModelCopyWithImpl<TwoFASecretResponseModel>(this as TwoFASecretResponseModel, _$identity);
|
||||
|
||||
/// Serializes this TwoFASecretResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TwoFASecretResponseModel&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretResponseModel(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TwoFASecretResponseModelCopyWith<$Res> {
|
||||
factory $TwoFASecretResponseModelCopyWith(TwoFASecretResponseModel value, $Res Function(TwoFASecretResponseModel) _then) = _$TwoFASecretResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isCreated, TwoFASecretItemResponseModel item
|
||||
});
|
||||
|
||||
|
||||
$TwoFASecretItemResponseModelCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TwoFASecretResponseModelCopyWithImpl<$Res>
|
||||
implements $TwoFASecretResponseModelCopyWith<$Res> {
|
||||
_$TwoFASecretResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final TwoFASecretResponseModel _self;
|
||||
final $Res Function(TwoFASecretResponseModel) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretItemResponseModel,
|
||||
));
|
||||
}
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemResponseModelCopyWith<$Res> get item {
|
||||
|
||||
return $TwoFASecretItemResponseModelCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [TwoFASecretResponseModel].
|
||||
extension TwoFASecretResponseModelPatterns on TwoFASecretResponseModel {
|
||||
/// 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( _TwoFASecretResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel() 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( _TwoFASecretResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel():
|
||||
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( _TwoFASecretResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel() 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( bool isCreated, TwoFASecretItemResponseModel item)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, TwoFASecretItemResponseModel item) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel():
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, TwoFASecretItemResponseModel item)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretResponseModel() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _TwoFASecretResponseModel implements TwoFASecretResponseModel {
|
||||
const _TwoFASecretResponseModel({required this.isCreated, required this.item});
|
||||
factory _TwoFASecretResponseModel.fromJson(Map<String, dynamic> json) => _$TwoFASecretResponseModelFromJson(json);
|
||||
|
||||
@override final bool isCreated;
|
||||
@override final TwoFASecretItemResponseModel item;
|
||||
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$TwoFASecretResponseModelCopyWith<_TwoFASecretResponseModel> get copyWith => __$TwoFASecretResponseModelCopyWithImpl<_TwoFASecretResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$TwoFASecretResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TwoFASecretResponseModel&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretResponseModel(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$TwoFASecretResponseModelCopyWith<$Res> implements $TwoFASecretResponseModelCopyWith<$Res> {
|
||||
factory _$TwoFASecretResponseModelCopyWith(_TwoFASecretResponseModel value, $Res Function(_TwoFASecretResponseModel) _then) = __$TwoFASecretResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isCreated, TwoFASecretItemResponseModel item
|
||||
});
|
||||
|
||||
|
||||
@override $TwoFASecretItemResponseModelCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$TwoFASecretResponseModelCopyWithImpl<$Res>
|
||||
implements _$TwoFASecretResponseModelCopyWith<$Res> {
|
||||
__$TwoFASecretResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _TwoFASecretResponseModel _self;
|
||||
final $Res Function(_TwoFASecretResponseModel) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_TwoFASecretResponseModel(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretItemResponseModel,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of TwoFASecretResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemResponseModelCopyWith<$Res> get item {
|
||||
|
||||
return $TwoFASecretItemResponseModelCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TwoFASecretItemResponseModel {
|
||||
|
||||
String get secret; String get qr;
|
||||
/// Create a copy of TwoFASecretItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemResponseModelCopyWith<TwoFASecretItemResponseModel> get copyWith => _$TwoFASecretItemResponseModelCopyWithImpl<TwoFASecretItemResponseModel>(this as TwoFASecretItemResponseModel, _$identity);
|
||||
|
||||
/// Serializes this TwoFASecretItemResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TwoFASecretItemResponseModel&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.qr, qr) || other.qr == qr));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,secret,qr);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretItemResponseModel(secret: $secret, qr: $qr)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TwoFASecretItemResponseModelCopyWith<$Res> {
|
||||
factory $TwoFASecretItemResponseModelCopyWith(TwoFASecretItemResponseModel value, $Res Function(TwoFASecretItemResponseModel) _then) = _$TwoFASecretItemResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String secret, String qr
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TwoFASecretItemResponseModelCopyWithImpl<$Res>
|
||||
implements $TwoFASecretItemResponseModelCopyWith<$Res> {
|
||||
_$TwoFASecretItemResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final TwoFASecretItemResponseModel _self;
|
||||
final $Res Function(TwoFASecretItemResponseModel) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? secret = null,Object? qr = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String,qr: null == qr ? _self.qr : qr // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [TwoFASecretItemResponseModel].
|
||||
extension TwoFASecretItemResponseModelPatterns on TwoFASecretItemResponseModel {
|
||||
/// 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( _TwoFASecretItemResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel() 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( _TwoFASecretItemResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel():
|
||||
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( _TwoFASecretItemResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel() 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( String secret, String qr)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel() when $default != null:
|
||||
return $default(_that.secret,_that.qr);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( String secret, String qr) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel():
|
||||
return $default(_that.secret,_that.qr);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( String secret, String qr)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemResponseModel() when $default != null:
|
||||
return $default(_that.secret,_that.qr);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _TwoFASecretItemResponseModel implements TwoFASecretItemResponseModel {
|
||||
const _TwoFASecretItemResponseModel({required this.secret, required this.qr});
|
||||
factory _TwoFASecretItemResponseModel.fromJson(Map<String, dynamic> json) => _$TwoFASecretItemResponseModelFromJson(json);
|
||||
|
||||
@override final String secret;
|
||||
@override final String qr;
|
||||
|
||||
/// Create a copy of TwoFASecretItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$TwoFASecretItemResponseModelCopyWith<_TwoFASecretItemResponseModel> get copyWith => __$TwoFASecretItemResponseModelCopyWithImpl<_TwoFASecretItemResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$TwoFASecretItemResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TwoFASecretItemResponseModel&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.qr, qr) || other.qr == qr));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,secret,qr);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretItemResponseModel(secret: $secret, qr: $qr)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$TwoFASecretItemResponseModelCopyWith<$Res> implements $TwoFASecretItemResponseModelCopyWith<$Res> {
|
||||
factory _$TwoFASecretItemResponseModelCopyWith(_TwoFASecretItemResponseModel value, $Res Function(_TwoFASecretItemResponseModel) _then) = __$TwoFASecretItemResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String secret, String qr
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$TwoFASecretItemResponseModelCopyWithImpl<$Res>
|
||||
implements _$TwoFASecretItemResponseModelCopyWith<$Res> {
|
||||
__$TwoFASecretItemResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _TwoFASecretItemResponseModel _self;
|
||||
final $Res Function(_TwoFASecretItemResponseModel) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? secret = null,Object? qr = null,}) {
|
||||
return _then(_TwoFASecretItemResponseModel(
|
||||
secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String,qr: null == qr ? _self.qr : qr // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,31 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'two_fa_secret_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_TwoFASecretResponseModel _$TwoFASecretResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _TwoFASecretResponseModel(
|
||||
isCreated: json['isCreated'] as bool,
|
||||
item: TwoFASecretItemResponseModel.fromJson(
|
||||
json['item'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TwoFASecretResponseModelToJson(
|
||||
_TwoFASecretResponseModel instance,
|
||||
) => <String, dynamic>{'isCreated': instance.isCreated, 'item': instance.item};
|
||||
|
||||
_TwoFASecretItemResponseModel _$TwoFASecretItemResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _TwoFASecretItemResponseModel(
|
||||
secret: json['secret'] as String,
|
||||
qr: json['qr'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TwoFASecretItemResponseModelToJson(
|
||||
_TwoFASecretItemResponseModel instance,
|
||||
) => <String, dynamic>{'secret': instance.secret, 'qr': instance.qr};
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:auth/src/core/data/datasource/auth_remote_datasource.dart';
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
|
||||
class AuthRepositoryImpl implements AuthRepository {
|
||||
const AuthRepositoryImpl(this._remote);
|
||||
@@ -15,4 +17,45 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
Future<void> verifyPhoneCode({required String phone, required String code}) {
|
||||
return _remote.verifyPhoneCode(phone: phone, code: code);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> login({required String email, required String password}) {
|
||||
return _remote.login(email: email, password: password);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> twoFactor({required String token, required String code}) {
|
||||
return _remote.twoFALogin(token: token, code: code);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> signUp({required SignUpRequestEntity request}) {
|
||||
return _remote.signUp(request: request);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token}) {
|
||||
return _remote.generateTwoFASignUp(token: token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
}) {
|
||||
return _remote.verifyTwoFACodeSignUp(token: token, code: code);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestPasswordReset({String? phone, String? email}) {
|
||||
return _remote.requestPasswordReset(phone: phone, email: email);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({
|
||||
required String newPassword,
|
||||
required String token,
|
||||
}) {
|
||||
return _remote.recoverPassword(newPassword: newPassword, token: token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
|
||||
abstract class AuthRepository {
|
||||
Future<void> requestPhoneCode({required String phone});
|
||||
|
||||
Future<void> verifyPhoneCode({required String phone, required String code});
|
||||
|
||||
Future<String> login({required String email, required String password});
|
||||
Future<void> twoFactor({required String token, required String code});
|
||||
|
||||
Future<String> requestPasswordReset({String phone, String email});
|
||||
|
||||
Future<void> recoverPassword({
|
||||
required String newPassword,
|
||||
required String token,
|
||||
});
|
||||
|
||||
Future<String> signUp({required SignUpRequestEntity request});
|
||||
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token});
|
||||
Future<void> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:auth/auth.dart';
|
||||
import 'package:auth/src/features/device_sign_up/add_kid_screen.dart';
|
||||
import 'package:auth/src/features/device_sign_up/link_watch/link_watch_screen.dart';
|
||||
import 'package:auth/src/features/device_sign_up/link_watch/link_watch_previous_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/account_created_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/account_created_screen.dart';
|
||||
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -103,10 +103,7 @@ class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen> {
|
||||
nextStep: () => {},
|
||||
previousStep: () => {},
|
||||
),
|
||||
AccountCreatedScreen(
|
||||
navigationContract: navigationContract,
|
||||
kidAccount: true,
|
||||
),
|
||||
AccountCreatedScreen(navigationContract: navigationContract),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,14 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
Text(
|
||||
"Comienza con un peque; luego podrás agregar más",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, letterSpacing: 0),
|
||||
),
|
||||
CustomTextField(
|
||||
label: "Nombre",
|
||||
hint: "Nombre",
|
||||
),
|
||||
CustomTextField(
|
||||
label: "Apellidos",
|
||||
hint: "Apellidos",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
CustomTextField(label: "Nombre", hint: "Nombre"),
|
||||
CustomTextField(label: "Apellidos", hint: "Apellidos"),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
@@ -42,21 +40,21 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
keyboardType: TextInputType.number,
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
keyboardType: TextInputType.number,
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
keyboardType: TextInputType.number,
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
),
|
||||
@@ -77,7 +75,7 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
size: 18,
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ class LinkPhoneUseCaseImpl implements LinkPhoneUseCase {
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<void> requestCode({required String phone}) {
|
||||
return _repository.requestPhoneCode(phone: phone);
|
||||
Future<void> requestCode({required String phone}) async {
|
||||
// return _repository.requestPhoneCode(phone: phone);
|
||||
await Future<void>.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> verifyCode({required String phone, required String code}) {
|
||||
return _repository.verifyPhoneCode(phone: phone, code: code);
|
||||
Future<void> verifyCode({required String phone, required String code}) async {
|
||||
// return _repository.verifyPhoneCode(phone: phone, code: code);
|
||||
await Future<void>.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class RequestLinkPhoneBuilder {
|
||||
const RequestLinkPhoneBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RequestLinkPhoneScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import 'package:auth/src/features/link_phone/presentation/link_phone_view_model.dart';
|
||||
import 'package:design_system/src/dropdowns/country_prefix_picker.dart';
|
||||
import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_model.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class LinkPhoneScreen extends ConsumerWidget {
|
||||
class RequestLinkPhoneScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const LinkPhoneScreen({super.key, required this.navigationContract});
|
||||
const RequestLinkPhoneScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -28,19 +28,22 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
Text(
|
||||
context.translate(I18n.linkPhoneTitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 30,
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 28, xl: 26),
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22, xl: 20)),
|
||||
Text(
|
||||
context.translate(I18n.linkPhoneSubtitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 16, letterSpacing: 0),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
letterSpacing: 0
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 48),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 46, xl: 44)),
|
||||
|
||||
Column(
|
||||
spacing: 8,
|
||||
@@ -56,6 +59,7 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
spacing: 10,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
initialCountryCode: viewState.dialCode,
|
||||
onChanged: (country) {
|
||||
viewModel.updateDialCode(
|
||||
@@ -67,7 +71,7 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
child: CustomTextField(
|
||||
controller: viewModel.phoneNumberController,
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
numeric: true,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -89,7 +93,7 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
),
|
||||
],
|
||||
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 10)),
|
||||
|
||||
PrimaryButton(
|
||||
onPressed: () async {
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart';
|
||||
import 'package:auth/src/features/link_phone/presentation/link_phone_view_state.dart';
|
||||
import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_state.dart';
|
||||
|
||||
final linkPhoneViewModelProvider =
|
||||
NotifierProvider.autoDispose<LinkPhoneViewModel, LinkPhoneViewState>(
|
||||
@@ -13,6 +13,7 @@ final linkPhoneViewModelProvider =
|
||||
class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
late final LinkPhoneUseCase _linkPhoneUseCase;
|
||||
late final TextEditingController phoneNumberController;
|
||||
late final TextEditingController codeController;
|
||||
|
||||
@override
|
||||
LinkPhoneViewState build() {
|
||||
@@ -21,6 +22,8 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
phoneNumberController = TextEditingController();
|
||||
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||
|
||||
codeController = TextEditingController();
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return const LinkPhoneViewState();
|
||||
@@ -28,18 +31,34 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
|
||||
void _onPhoneNumberChanged() {
|
||||
final raw = phoneNumberController.text;
|
||||
state = state.copyWith(phoneNumber: raw, errorMessage: '');
|
||||
state = state.copyWith(
|
||||
phoneNumber: raw,
|
||||
errorMessage: '',
|
||||
codeVerified: false,
|
||||
);
|
||||
}
|
||||
|
||||
void updateDialCode(String dialCode) {
|
||||
state = state.copyWith(dialCode: dialCode, errorMessage: '');
|
||||
state = state.copyWith(
|
||||
dialCode: dialCode,
|
||||
errorMessage: '',
|
||||
codeVerified: false,
|
||||
);
|
||||
}
|
||||
|
||||
void updateCode(String code) {
|
||||
codeController.text = code;
|
||||
state = state.copyWith(errorMessage: '', codeVerified: false);
|
||||
}
|
||||
|
||||
Future<void> requestCode() async {
|
||||
final trimmedNumber = state.phoneNumber.trim();
|
||||
|
||||
if (trimmedNumber.isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'El teléfono no puede estar vacío');
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePhoneIsEmpty',
|
||||
codeVerified: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,6 +68,7 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
codeRequested: false,
|
||||
codeVerified: false,
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -67,6 +87,55 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
codeRequested: false,
|
||||
codeVerified: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyCode() async {
|
||||
final dialCode = state.dialCode;
|
||||
final phoneNumber = state.phoneNumber.trim();
|
||||
final code = codeController.text.trim();
|
||||
final fullPhone = '$dialCode$phoneNumber';
|
||||
|
||||
if (phoneNumber.isEmpty) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePhoneIsEmpty',
|
||||
codeVerified: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code.isEmpty) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessageCodeIsEmpty',
|
||||
codeVerified: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
codeVerified: false,
|
||||
);
|
||||
|
||||
try {
|
||||
await _linkPhoneUseCase.verifyCode(phone: fullPhone, code: code);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
codeVerified: true,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
codeVerified: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -74,5 +143,6 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
void disposeControllers() {
|
||||
phoneNumberController.removeListener(_onPhoneNumberChanged);
|
||||
phoneNumberController.dispose();
|
||||
codeController.dispose();
|
||||
}
|
||||
}
|
||||
@@ -10,5 +10,6 @@ abstract class LinkPhoneViewState with _$LinkPhoneViewState {
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool codeRequested,
|
||||
@Default(false) bool codeVerified,
|
||||
}) = _LinkPhoneViewState;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$LinkPhoneViewState {
|
||||
|
||||
String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested;
|
||||
String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested; bool get codeVerified;
|
||||
/// Create a copy of LinkPhoneViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $LinkPhoneViewStateCopyWith<LinkPhoneViewState> get copyWith => _$LinkPhoneViewS
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)&&(identical(other.codeVerified, codeVerified) || other.codeVerified == codeVerified));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested,codeVerified);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)';
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract mixin class $LinkPhoneViewStateCopyWith<$Res> {
|
||||
factory $LinkPhoneViewStateCopyWith(LinkPhoneViewState value, $Res Function(LinkPhoneViewState) _then) = _$LinkPhoneViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified
|
||||
});
|
||||
|
||||
|
||||
@@ -62,13 +62,14 @@ class _$LinkPhoneViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of LinkPhoneViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,Object? codeVerified = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,codeVerified: null == codeVerified ? _self.codeVerified : codeVerified // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
@@ -154,10 +155,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LinkPhoneViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -175,10 +176,10 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LinkPhoneViewState():
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -195,10 +196,10 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LinkPhoneViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -210,7 +211,7 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad
|
||||
|
||||
|
||||
class _LinkPhoneViewState implements LinkPhoneViewState {
|
||||
const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false});
|
||||
const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false, this.codeVerified = false});
|
||||
|
||||
|
||||
@override@JsonKey() final String phoneNumber;
|
||||
@@ -218,6 +219,7 @@ class _LinkPhoneViewState implements LinkPhoneViewState {
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool codeRequested;
|
||||
@override@JsonKey() final bool codeVerified;
|
||||
|
||||
/// Create a copy of LinkPhoneViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -229,16 +231,16 @@ _$LinkPhoneViewStateCopyWith<_LinkPhoneViewState> get copyWith => __$LinkPhoneVi
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)&&(identical(other.codeVerified, codeVerified) || other.codeVerified == codeVerified));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested,codeVerified);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)';
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +251,7 @@ abstract mixin class _$LinkPhoneViewStateCopyWith<$Res> implements $LinkPhoneVie
|
||||
factory _$LinkPhoneViewStateCopyWith(_LinkPhoneViewState value, $Res Function(_LinkPhoneViewState) _then) = __$LinkPhoneViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified
|
||||
});
|
||||
|
||||
|
||||
@@ -266,13 +268,14 @@ class __$LinkPhoneViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of LinkPhoneViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,Object? codeVerified = null,}) {
|
||||
return _then(_LinkPhoneViewState(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,codeVerified: null == codeVerified ? _self.codeVerified : codeVerified // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class VerifyLinkPhoneCodeBuilder {
|
||||
const VerifyLinkPhoneCodeBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: VerifyLinkPhoneCodeScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_model.dart';
|
||||
import 'package:auth/src/features/link_phone/presentation/widgets/link_phone_code_input.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class VerifyLinkPhoneCodeScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const VerifyLinkPhoneCodeScreen({
|
||||
super.key,
|
||||
required this.navigationContract,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(linkPhoneViewModelProvider.notifier);
|
||||
final viewState = ref.watch(linkPhoneViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 48,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.connect),
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: SizeUtils.getByScreen(small: 30, big: 28)),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: context.translate(I18n.verificationCodeSentTo),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 18, big: 15),
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '${viewState.dialCode}${viewState.phoneNumber}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 42, xl: 36)),
|
||||
Text(
|
||||
context.translate(I18n.enterCodeHere),
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 24, xl: 20)),
|
||||
|
||||
LinkPhoneCodeInput(
|
||||
length: 6,
|
||||
onCodeChanged: viewModel.updateCode,
|
||||
),
|
||||
|
||||
if (viewState.errorMessage.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
viewState.errorMessage,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
PrimaryButton(
|
||||
onPressed: () async {
|
||||
await viewModel.verifyCode();
|
||||
final updatedState = ref.read(linkPhoneViewModelProvider);
|
||||
|
||||
if (updatedState.codeVerified) {
|
||||
navigationContract.pushTo(AppRoutes.login);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.enter),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
size: SizeUtils.getByScreen(small: 18, big: 17, xl: 16),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
context.translate(I18n.didNotReceiveIt),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 18, big: 17, xl: 16),
|
||||
letterSpacing: 0,
|
||||
height: SizeUtils.getByScreen(small: 1.5, big: 0),
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 8, big: 0)),
|
||||
CustomTextButton(
|
||||
onPressed: () => navigationContract.goBack(),
|
||||
text: context.translate(I18n.tryAgain),
|
||||
size: SizeUtils.getByScreen(small: 18, big: 17, xl: 16),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class LinkPhoneCodeInput extends StatefulWidget {
|
||||
const LinkPhoneCodeInput({
|
||||
super.key,
|
||||
this.length = 6,
|
||||
required this.onCodeChanged,
|
||||
});
|
||||
|
||||
final int length;
|
||||
final ValueChanged<String> onCodeChanged;
|
||||
|
||||
@override
|
||||
State<LinkPhoneCodeInput> createState() => _LinkPhoneCodeInputState();
|
||||
}
|
||||
|
||||
class _LinkPhoneCodeInputState extends State<LinkPhoneCodeInput> {
|
||||
late final List<TextEditingController> _controllers;
|
||||
late final List<FocusNode> _focusNodes;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controllers = List<TextEditingController>.generate(
|
||||
widget.length,
|
||||
(_) => TextEditingController(),
|
||||
);
|
||||
_focusNodes = List<FocusNode>.generate(widget.length, (_) => FocusNode());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final controller in _controllers) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (final node in _focusNodes) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onDigitChanged(int index, String value) {
|
||||
if (value.length > 1) {
|
||||
final single = value.characters.last;
|
||||
_controllers[index].text = single;
|
||||
_controllers[index].selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: single.length),
|
||||
);
|
||||
}
|
||||
|
||||
if (value.isNotEmpty && index < widget.length - 1) {
|
||||
_focusNodes[index + 1].requestFocus();
|
||||
} else if (value.isEmpty && index > 0) {
|
||||
_focusNodes[index - 1].requestFocus();
|
||||
}
|
||||
|
||||
final code = _controllers.map((c) => c.text).join();
|
||||
widget.onCodeChanged(code);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: List<Widget>.generate(widget.length, (int i) {
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
controller: _controllers[i],
|
||||
focusNode: _focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
textAlign: TextAlign.center,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '0',
|
||||
counterText: '',
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(14))),
|
||||
),
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 20, big: 22, xl: 17)),
|
||||
maxLength: 1,
|
||||
onChanged: (value) => _onDigitChanged(i, value),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class LoginUseCase {
|
||||
Future<String> login({required String email, required String password});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/login/domain/login_use_case.dart';
|
||||
|
||||
class LoginUseCaseImpl implements LoginUseCase {
|
||||
LoginUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<String> login({required String email, required String password}) {
|
||||
return _repository.login(email: email, password: password);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class TwoFactorUseCase {
|
||||
Future<void> twoFactor({required String token, required String code});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/login/domain/two_factor_use_case.dart';
|
||||
|
||||
class TwoFactorUseCaseImpl implements TwoFactorUseCase {
|
||||
TwoFactorUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<void> twoFactor({required String token, required String code}) {
|
||||
return _repository.twoFactor(token: token, code: code);
|
||||
}
|
||||
}
|
||||
@@ -1,170 +1,128 @@
|
||||
import 'package:auth/src/features/login/presentation/loading_google_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/signup_screen.dart';
|
||||
import 'package:auth/src/features/login/presentation/state/login_view_model.dart';
|
||||
import 'package:auth/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class LoginScreen extends ConsumerStatefulWidget {
|
||||
class LoginScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const LoginScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
ConsumerState<ConsumerStatefulWidget> createState() => _LoginScreenState();
|
||||
}
|
||||
Future<void> _onLogIn(BuildContext context, WidgetRef ref) async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
bool passwordVisible = false;
|
||||
final vm = ref.read(loginViewModelProvider.notifier);
|
||||
|
||||
final String? token = await vm.login();
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (token == null || token.isEmpty) return;
|
||||
|
||||
vm.prepareTwoFactor();
|
||||
|
||||
final bool? verified = await showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
isDismissible: false,
|
||||
enableDrag: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context) {
|
||||
return Consumer(
|
||||
builder: (context, ref, _) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final vm = ref.read(loginViewModelProvider.notifier);
|
||||
|
||||
final otpErrorKey = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.otpError),
|
||||
);
|
||||
final isOtpLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isOtpLoading),
|
||||
);
|
||||
final otpCode = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.otpCode),
|
||||
);
|
||||
|
||||
final otpErrorText = otpErrorKey.isEmpty
|
||||
? ''
|
||||
: context.translate(otpErrorKey);
|
||||
|
||||
Future<void> onVerify() async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
final ok = await vm.twoFactor(token: token);
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (ok) Navigator.of(context).pop(true);
|
||||
}
|
||||
|
||||
return TwoFactorBottomSheetView(
|
||||
theme: theme,
|
||||
title: context.translate(I18n.twoFactorTitle),
|
||||
subtitle: context.translate(I18n.twoFactorSubtitle),
|
||||
verifyText: context.translate(I18n.twoFactorVerify),
|
||||
closeText: context.translate(I18n.close),
|
||||
isOtpLoading: isOtpLoading,
|
||||
otpCode: otpCode,
|
||||
otpErrorText: otpErrorText,
|
||||
onChanged: vm.setOtpCode,
|
||||
onVerify: onVerify,
|
||||
onClose: () => Navigator.of(context).pop(false),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (verified == true) {
|
||||
navigationContract.goTo(AppRoutes.dashboardHome);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
bool passwordVisible = true;
|
||||
|
||||
final content = [
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
size: 50,
|
||||
),
|
||||
Text(
|
||||
// context.translate(I18n.example)
|
||||
"¡Te damos la bienvenida!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
CustomTextField(
|
||||
hint: "Nombre de usuario",
|
||||
label: "Nombre de usuario",
|
||||
),
|
||||
Column(
|
||||
spacing: 12,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Contraseña",
|
||||
hint: "********",
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: CustomTextButton(
|
||||
text: "¿Has olvidado la contraseña?",
|
||||
onPressed: () => widget.navigationContract.pushTo(
|
||||
AppRoutes.recoverPassword,
|
||||
),
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () =>
|
||||
widget.navigationContract.goTo(AppRoutes.dashboardHome),
|
||||
text: "Iniciar sesión",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
Divider(endIndent: 74, indent: 74),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
child: Text("o continúa con"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(),
|
||||
SecondaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => LoadingGoogleScreen(),
|
||||
),
|
||||
),
|
||||
radius: 16,
|
||||
padding: 44,
|
||||
text: "Google",
|
||||
label: "Google",
|
||||
),
|
||||
SecondaryButton(
|
||||
onPressed: () => {},
|
||||
radius: 16,
|
||||
padding: 44,
|
||||
icon: Icons.apple,
|
||||
label: "Apple",
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
"¿No tienes cuenta?",
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
widget.navigationContract.goTo(AppRoutes.signup),
|
||||
child: Text(
|
||||
"Crear una ahora",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
final bool isLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isLoading),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: ListView.separated(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return content[index];
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(color: Colors.transparent, height: 48);
|
||||
},
|
||||
itemCount: content.length,
|
||||
body: SafeArea(
|
||||
child: AbsorbPointer(
|
||||
absorbing: isLoading,
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.symmetric(horizontal: SizeUtils.getByScreen(small: 24, big: 24)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 0, big: 30, xl: 44)),
|
||||
_Header(theme: theme),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 26, big: 30, xl: 40)),
|
||||
const _EmailSection(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 24, xl: 20)),
|
||||
_PasswordSection(onSubmitted: () => _onLogIn(context, ref)),
|
||||
_ForgotPassword(navigationContract: navigationContract),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 0, big: 24, xl: 22)),
|
||||
_SignInSection(
|
||||
theme: theme,
|
||||
onSignIn: () => _onLogIn(context, ref),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 30, big: 60, xl: 56)),
|
||||
_OrContinueWith(theme: theme),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 24, xl: 26)),
|
||||
_SocialButtons(theme: theme),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 36)),
|
||||
_Footer(navigationContract: navigationContract),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -172,3 +130,282 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Header extends StatelessWidget {
|
||||
const _Header({required this.theme});
|
||||
final ThemePort theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
size: SizeUtils.getByScreen(small: 54, big: 50, xl: 46),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.welcome),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 28, xl: 27),
|
||||
fontWeight: FontWeight.w500
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EmailSection extends ConsumerWidget {
|
||||
const _EmailSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final vm = ref.read(loginViewModelProvider.notifier);
|
||||
final String emailErrorKey = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.emailError),
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
CustomTextField(
|
||||
hint: context.translate(I18n.username),
|
||||
label: context.translate(I18n.username),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
controller: vm.emailController,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
_FieldErrorText.fromKey(errorKey: emailErrorKey),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordSection extends ConsumerWidget {
|
||||
const _PasswordSection({required this.onSubmitted});
|
||||
final Future<void> Function() onSubmitted;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final vm = ref.read(loginViewModelProvider.notifier);
|
||||
|
||||
final bool passwordVisible = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.passwordVisible),
|
||||
);
|
||||
final String passwordErrorKey = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.passwordError),
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: context.translate(I18n.password),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
hint: '********',
|
||||
controller: vm.passwordController,
|
||||
textInputAction: TextInputAction.done,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
),
|
||||
_FieldErrorText.fromKey(errorKey: passwordErrorKey),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ForgotPassword extends ConsumerWidget {
|
||||
const _ForgotPassword({required this.navigationContract});
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final bool isLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isLoading),
|
||||
);
|
||||
|
||||
return Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: CustomTextButton(
|
||||
text: context.translate(I18n.forgotPassword),
|
||||
onPressed: isLoading
|
||||
? () {}
|
||||
: () => navigationContract.pushTo(AppRoutes.recoverPassword),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 15, xl: 14),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SignInSection extends ConsumerWidget {
|
||||
const _SignInSection({required this.onSignIn, required this.theme});
|
||||
|
||||
final VoidCallback onSignIn;
|
||||
final ThemePort theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final bool isLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isLoading),
|
||||
);
|
||||
final String errorMessage = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.errorMessage),
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
PrimaryButton(
|
||||
onPressed: isLoading ? () {} : onSignIn,
|
||||
text: context.translate(I18n.signIn),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
leading: isLoading
|
||||
? const SizedBox(
|
||||
height: 18,
|
||||
width: 18,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
size: SizeUtils.getByScreen(small: 18, big: 17, xl: 16),
|
||||
),
|
||||
if (errorMessage.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Text(
|
||||
errorMessage,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: SizeUtils.getByScreen(small: 13, big: 12, xl: 11),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _OrContinueWith extends StatelessWidget {
|
||||
const _OrContinueWith({required this.theme});
|
||||
final ThemePort theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
const Divider(endIndent: 74, indent: 74),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
child: Text(context.translate(I18n.orContinueWith)),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SocialButtons extends ConsumerWidget {
|
||||
const _SocialButtons({required this.theme});
|
||||
final ThemePort theme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final bool isLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isLoading),
|
||||
);
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SecondaryButton(
|
||||
onPressed: isLoading
|
||||
? () {}
|
||||
: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const LoadingGoogleScreen(),
|
||||
),
|
||||
),
|
||||
radius: 16,
|
||||
padding: SizeUtils.getByScreen(small: 44, big: 40, xl: 36),
|
||||
text: context.translate(I18n.google),
|
||||
label: 'Google',
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
SecondaryButton(
|
||||
onPressed: isLoading ? () {} : () {},
|
||||
radius: 16,
|
||||
padding: SizeUtils.getByScreen(small: 44, big: 40, xl: 36),
|
||||
icon: Icons.apple,
|
||||
label: 'Apple',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Footer extends ConsumerWidget {
|
||||
const _Footer({required this.navigationContract});
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final bool isLoading = ref.watch(
|
||||
loginViewModelProvider.select((s) => s.isLoading),
|
||||
);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.dontHaveAccount),
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 17, xl: 16), letterSpacing: 0, height: 0),
|
||||
),
|
||||
CustomTextButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () => navigationContract.pushTo(AppRoutes.signup),
|
||||
text: context.translate(I18n.createOneNow),
|
||||
size: SizeUtils.getByScreen(small: 18, big: 17, xl: 16),
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FieldErrorText extends StatelessWidget {
|
||||
const _FieldErrorText._({required this.text});
|
||||
final String text;
|
||||
|
||||
factory _FieldErrorText.fromKey({required String errorKey}) {
|
||||
return _FieldErrorText._(text: errorKey);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (text.isEmpty) return const SizedBox.shrink();
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
context.translate(text),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class PhoneCodeScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
PhoneCodeScreen({super.key, required this.navigationContract});
|
||||
|
||||
final focusNodes = List<FocusNode>.generate(6, (int i) {
|
||||
return FocusNode();
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Text(
|
||||
"Conéctate",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Hemos enviado el código al ",
|
||||
children: [
|
||||
TextSpan(
|
||||
// text: widget.phone,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Introduce el código aquí"),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: List<Widget>.generate(6, (int i) {
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
focusNode: focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
hintText: "0",
|
||||
counterText: "",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
maxLength: 1,
|
||||
onChanged: (String value) => {
|
||||
value != ""
|
||||
? focusNodes[i + 1].requestFocus()
|
||||
: focusNodes[i - 1].requestFocus(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
PrimaryButton(
|
||||
onPressed: () => {
|
||||
navigationContract.pushTo(AppRoutes.login),
|
||||
},
|
||||
text: "Entrar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
"¿No lo has recibido?",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
letterSpacing: 0,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
CustomTextButton(
|
||||
onPressed: () => {},
|
||||
text: "Volver a intentarlo",
|
||||
size: 18,
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:auth/src/features/login/domain/login_use_case.dart';
|
||||
import 'package:auth/src/features/login/domain/login_use_case_impl.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final loginUseCaseProvider = Provider.autoDispose<LoginUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return LoginUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:auth/src/features/login/domain/two_factor_use_case.dart';
|
||||
import 'package:auth/src/features/login/domain/two_factor_use_case_impl.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final twoFactorUseCaseProvider = Provider.autoDispose<TwoFactorUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return TwoFactorUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,202 @@
|
||||
import 'package:auth/src/features/login/domain/login_use_case.dart';
|
||||
import 'package:auth/src/features/login/domain/two_factor_use_case.dart';
|
||||
import 'package:auth/src/features/login/presentation/providers/login_provider.dart';
|
||||
import 'package:auth/src/features/login/presentation/providers/two_factor_provider.dart';
|
||||
import 'package:auth/src/features/login/presentation/state/login_view_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
final loginViewModelProvider =
|
||||
NotifierProvider.autoDispose<LoginViewModel, LoginViewState>(
|
||||
LoginViewModel.new,
|
||||
);
|
||||
|
||||
class LoginViewModel extends Notifier<LoginViewState> {
|
||||
late final LoginUseCase _loginUseCase;
|
||||
late final TwoFactorUseCase _twoFactorUseCase;
|
||||
|
||||
late final TextEditingController emailController;
|
||||
late final TextEditingController passwordController;
|
||||
|
||||
late final TextEditingController otpController;
|
||||
|
||||
static final RegExp _emailRegex = RegExp(
|
||||
r'^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
@override
|
||||
LoginViewState build() {
|
||||
_loginUseCase = ref.read(loginUseCaseProvider);
|
||||
_twoFactorUseCase = ref.read(twoFactorUseCaseProvider);
|
||||
|
||||
emailController = TextEditingController();
|
||||
passwordController = TextEditingController();
|
||||
otpController = TextEditingController();
|
||||
|
||||
emailController.addListener(_onEmailChanged);
|
||||
passwordController.addListener(_onPasswordChanged);
|
||||
otpController.addListener(_onOtpChanged);
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return const LoginViewState();
|
||||
}
|
||||
|
||||
void _onEmailChanged() {
|
||||
final text = emailController.text;
|
||||
if (text == state.email) return;
|
||||
|
||||
state = state.copyWith(email: text, errorMessage: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(emailError: _emailErrorFor(text));
|
||||
}
|
||||
}
|
||||
|
||||
void _onPasswordChanged() {
|
||||
final text = passwordController.text;
|
||||
if (text == state.password) return;
|
||||
|
||||
state = state.copyWith(password: text, errorMessage: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(passwordError: _passwordErrorFor(text));
|
||||
}
|
||||
}
|
||||
|
||||
void togglePasswordVisible() {
|
||||
state = state.copyWith(passwordVisible: !state.passwordVisible);
|
||||
}
|
||||
|
||||
bool _isValidEmail(String email) => _emailRegex.hasMatch(email);
|
||||
|
||||
String _emailErrorFor(String value) {
|
||||
final email = value.trim();
|
||||
if (email.isEmpty) return I18n.errorEmailRequired;
|
||||
if (!_isValidEmail(email)) return I18n.errorEmailInvalid;
|
||||
return '';
|
||||
}
|
||||
|
||||
String _passwordErrorFor(String value) {
|
||||
final password = value.trim();
|
||||
if (password.isEmpty) return I18n.errorPasswordRequired;
|
||||
if (password.length < 6) return I18n.errorPasswordMinLength;
|
||||
return '';
|
||||
}
|
||||
|
||||
bool _validateForm() {
|
||||
final emailError = _emailErrorFor(state.email);
|
||||
final passwordError = _passwordErrorFor(state.password);
|
||||
|
||||
state = state.copyWith(
|
||||
showErrors: true,
|
||||
emailError: emailError,
|
||||
passwordError: passwordError,
|
||||
errorMessage: '',
|
||||
);
|
||||
|
||||
return emailError.isEmpty && passwordError.isEmpty;
|
||||
}
|
||||
|
||||
Future<String?> login() async {
|
||||
if (!_validateForm()) return null;
|
||||
|
||||
final email = state.email.trim();
|
||||
final password = state.password.trim();
|
||||
|
||||
state = state.copyWith(isLoading: true, errorMessage: '');
|
||||
|
||||
try {
|
||||
final String token = await _loginUseCase.login(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
|
||||
if (!ref.mounted) return null;
|
||||
|
||||
state = state.copyWith(isLoading: false);
|
||||
return token;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return null;
|
||||
|
||||
state = state.copyWith(isLoading: false, errorMessage: e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void prepareTwoFactor() {
|
||||
otpController.text = '';
|
||||
state = state.copyWith(otpCode: '', otpError: '', isOtpLoading: false);
|
||||
}
|
||||
|
||||
void _onOtpChanged() {
|
||||
final raw = otpController.text;
|
||||
if (raw == state.otpCode) return;
|
||||
|
||||
state = state.copyWith(otpCode: raw, otpError: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(otpError: _otpErrorFor(raw));
|
||||
}
|
||||
}
|
||||
|
||||
void setOtpCode(String code) {
|
||||
state = state.copyWith(otpCode: code, otpError: '');
|
||||
}
|
||||
|
||||
String _otpErrorFor(String value) {
|
||||
final code = value.trim();
|
||||
if (code.isEmpty) return I18n.errorTwoFactorCodeRequired;
|
||||
if (code.length != 6) return I18n.errorTwoFactorCodeInvalidLength;
|
||||
return '';
|
||||
}
|
||||
|
||||
bool _validateOtp() {
|
||||
final otpError = _otpErrorFor(state.otpCode);
|
||||
|
||||
state = state.copyWith(
|
||||
showErrors: true,
|
||||
otpError: otpError,
|
||||
errorMessage: '',
|
||||
);
|
||||
|
||||
return otpError.isEmpty;
|
||||
}
|
||||
|
||||
Future<bool> twoFactor({required String token}) async {
|
||||
if (!_validateOtp()) return false;
|
||||
|
||||
final code = state.otpCode.trim();
|
||||
|
||||
state = state.copyWith(isOtpLoading: true, otpError: '', errorMessage: '');
|
||||
|
||||
try {
|
||||
await _twoFactorUseCase.twoFactor(token: token, code: code);
|
||||
|
||||
if (!ref.mounted) return false;
|
||||
|
||||
state = state.copyWith(isOtpLoading: false);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
|
||||
state = state.copyWith(
|
||||
isOtpLoading: false,
|
||||
otpError: I18n.errorTwoFactorCodeInvalid,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
emailController.removeListener(_onEmailChanged);
|
||||
passwordController.removeListener(_onPasswordChanged);
|
||||
otpController.removeListener(_onOtpChanged);
|
||||
|
||||
emailController.dispose();
|
||||
passwordController.dispose();
|
||||
otpController.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'login_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class LoginViewState with _$LoginViewState {
|
||||
const factory LoginViewState({
|
||||
@Default('') String email,
|
||||
@Default('') String password,
|
||||
@Default(false) bool passwordVisible,
|
||||
@Default('') String emailError,
|
||||
@Default('') String passwordError,
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool showErrors,
|
||||
@Default(false) bool isLoading,
|
||||
@Default('') String token,
|
||||
@Default('') String otpCode,
|
||||
@Default('') String otpError,
|
||||
@Default(false) bool isOtpLoading,
|
||||
}) = _LoginViewState;
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
// 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 'login_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$LoginViewState {
|
||||
|
||||
String get email; String get password; bool get passwordVisible; String get emailError; String get passwordError; String get errorMessage; bool get showErrors; bool get isLoading; String get token; String get otpCode; String get otpError; bool get isOtpLoading;
|
||||
/// Create a copy of LoginViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$LoginViewStateCopyWith<LoginViewState> get copyWith => _$LoginViewStateCopyWithImpl<LoginViewState>(this as LoginViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is LoginViewState&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.emailError, emailError) || other.emailError == emailError)&&(identical(other.passwordError, passwordError) || other.passwordError == passwordError)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.showErrors, showErrors) || other.showErrors == showErrors)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.token, token) || other.token == token)&&(identical(other.otpCode, otpCode) || other.otpCode == otpCode)&&(identical(other.otpError, otpError) || other.otpError == otpError)&&(identical(other.isOtpLoading, isOtpLoading) || other.isOtpLoading == isOtpLoading));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,email,password,passwordVisible,emailError,passwordError,errorMessage,showErrors,isLoading,token,otpCode,otpError,isOtpLoading);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LoginViewState(email: $email, password: $password, passwordVisible: $passwordVisible, emailError: $emailError, passwordError: $passwordError, errorMessage: $errorMessage, showErrors: $showErrors, isLoading: $isLoading, token: $token, otpCode: $otpCode, otpError: $otpError, isOtpLoading: $isOtpLoading)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $LoginViewStateCopyWith<$Res> {
|
||||
factory $LoginViewStateCopyWith(LoginViewState value, $Res Function(LoginViewState) _then) = _$LoginViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, String token, String otpCode, String otpError, bool isOtpLoading
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$LoginViewStateCopyWithImpl<$Res>
|
||||
implements $LoginViewStateCopyWith<$Res> {
|
||||
_$LoginViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final LoginViewState _self;
|
||||
final $Res Function(LoginViewState) _then;
|
||||
|
||||
/// Create a copy of LoginViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? email = null,Object? password = null,Object? passwordVisible = null,Object? emailError = null,Object? passwordError = null,Object? errorMessage = null,Object? showErrors = null,Object? isLoading = null,Object? token = null,Object? otpCode = null,Object? otpError = null,Object? isOtpLoading = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordError: null == passwordError ? _self.passwordError : passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,showErrors: null == showErrors ? _self.showErrors : showErrors // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpCode: null == otpCode ? _self.otpCode : otpCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpError: null == otpError ? _self.otpError : otpError // ignore: cast_nullable_to_non_nullable
|
||||
as String,isOtpLoading: null == isOtpLoading ? _self.isOtpLoading : isOtpLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [LoginViewState].
|
||||
extension LoginViewStatePatterns on LoginViewState {
|
||||
/// 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( _LoginViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState() 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( _LoginViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState():
|
||||
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( _LoginViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState() 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( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, String token, String otpCode, String otpError, bool isOtpLoading)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState() when $default != null:
|
||||
return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.token,_that.otpCode,_that.otpError,_that.isOtpLoading);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( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, String token, String otpCode, String otpError, bool isOtpLoading) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState():
|
||||
return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.token,_that.otpCode,_that.otpError,_that.isOtpLoading);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( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, String token, String otpCode, String otpError, bool isOtpLoading)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LoginViewState() when $default != null:
|
||||
return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.token,_that.otpCode,_that.otpError,_that.isOtpLoading);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _LoginViewState implements LoginViewState {
|
||||
const _LoginViewState({this.email = '', this.password = '', this.passwordVisible = false, this.emailError = '', this.passwordError = '', this.errorMessage = '', this.showErrors = false, this.isLoading = false, this.token = '', this.otpCode = '', this.otpError = '', this.isOtpLoading = false});
|
||||
|
||||
|
||||
@override@JsonKey() final String email;
|
||||
@override@JsonKey() final String password;
|
||||
@override@JsonKey() final bool passwordVisible;
|
||||
@override@JsonKey() final String emailError;
|
||||
@override@JsonKey() final String passwordError;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool showErrors;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final String token;
|
||||
@override@JsonKey() final String otpCode;
|
||||
@override@JsonKey() final String otpError;
|
||||
@override@JsonKey() final bool isOtpLoading;
|
||||
|
||||
/// Create a copy of LoginViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$LoginViewStateCopyWith<_LoginViewState> get copyWith => __$LoginViewStateCopyWithImpl<_LoginViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LoginViewState&&(identical(other.email, email) || other.email == email)&&(identical(other.password, password) || other.password == password)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.emailError, emailError) || other.emailError == emailError)&&(identical(other.passwordError, passwordError) || other.passwordError == passwordError)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.showErrors, showErrors) || other.showErrors == showErrors)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.token, token) || other.token == token)&&(identical(other.otpCode, otpCode) || other.otpCode == otpCode)&&(identical(other.otpError, otpError) || other.otpError == otpError)&&(identical(other.isOtpLoading, isOtpLoading) || other.isOtpLoading == isOtpLoading));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,email,password,passwordVisible,emailError,passwordError,errorMessage,showErrors,isLoading,token,otpCode,otpError,isOtpLoading);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LoginViewState(email: $email, password: $password, passwordVisible: $passwordVisible, emailError: $emailError, passwordError: $passwordError, errorMessage: $errorMessage, showErrors: $showErrors, isLoading: $isLoading, token: $token, otpCode: $otpCode, otpError: $otpError, isOtpLoading: $isOtpLoading)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$LoginViewStateCopyWith<$Res> implements $LoginViewStateCopyWith<$Res> {
|
||||
factory _$LoginViewStateCopyWith(_LoginViewState value, $Res Function(_LoginViewState) _then) = __$LoginViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, String token, String otpCode, String otpError, bool isOtpLoading
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$LoginViewStateCopyWithImpl<$Res>
|
||||
implements _$LoginViewStateCopyWith<$Res> {
|
||||
__$LoginViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _LoginViewState _self;
|
||||
final $Res Function(_LoginViewState) _then;
|
||||
|
||||
/// Create a copy of LoginViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? email = null,Object? password = null,Object? passwordVisible = null,Object? emailError = null,Object? passwordError = null,Object? errorMessage = null,Object? showErrors = null,Object? isLoading = null,Object? token = null,Object? otpCode = null,Object? otpError = null,Object? isOtpLoading = null,}) {
|
||||
return _then(_LoginViewState(
|
||||
email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordError: null == passwordError ? _self.passwordError : passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,showErrors: null == showErrors ? _self.showErrors : showErrors // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpCode: null == otpCode ? _self.otpCode : otpCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpError: null == otpError ? _self.otpError : otpError // ignore: cast_nullable_to_non_nullable
|
||||
as String,isOtpLoading: null == isOtpLoading ? _self.isOtpLoading : isOtpLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,211 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class OtpCodeFields extends StatefulWidget {
|
||||
const OtpCodeFields({
|
||||
super.key,
|
||||
this.length = 6,
|
||||
this.autofocus = true,
|
||||
this.enabled = true,
|
||||
this.errorText,
|
||||
this.onChanged,
|
||||
this.onCompleted,
|
||||
this.boxSize = 48,
|
||||
this.gap = 10,
|
||||
});
|
||||
|
||||
final int length;
|
||||
final bool autofocus;
|
||||
final bool enabled;
|
||||
final String? errorText;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final ValueChanged<String>? onCompleted;
|
||||
final double boxSize;
|
||||
final double gap;
|
||||
|
||||
@override
|
||||
State<OtpCodeFields> createState() => _OtpCodeFieldsState();
|
||||
}
|
||||
|
||||
class _OtpCodeFieldsState extends State<OtpCodeFields> {
|
||||
late final List<TextEditingController> _controllers;
|
||||
late final List<FocusNode> _focusNodes;
|
||||
|
||||
String get _code => _controllers.map((c) => c.text.trim()).join();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controllers = List.generate(widget.length, (_) => TextEditingController());
|
||||
_focusNodes = List.generate(widget.length, (_) => FocusNode());
|
||||
|
||||
if (widget.autofocus) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) return;
|
||||
_focusNodes.first.requestFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final c in _controllers) {
|
||||
c.dispose();
|
||||
}
|
||||
for (final f in _focusNodes) {
|
||||
f.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _emit() {
|
||||
final code = _code;
|
||||
widget.onChanged?.call(code);
|
||||
if (code.length == widget.length &&
|
||||
!_controllers.any((c) => c.text.isEmpty)) {
|
||||
widget.onCompleted?.call(code);
|
||||
}
|
||||
}
|
||||
|
||||
void _setFromPaste(String value) {
|
||||
final digits = value.replaceAll(RegExp(r'\D'), '');
|
||||
if (digits.isEmpty) return;
|
||||
|
||||
final clipped = digits.length > widget.length
|
||||
? digits.substring(0, widget.length)
|
||||
: digits;
|
||||
|
||||
for (var i = 0; i < widget.length; i++) {
|
||||
_controllers[i].text = i < clipped.length ? clipped[i] : '';
|
||||
}
|
||||
|
||||
final nextIndex = clipped.length >= widget.length
|
||||
? widget.length - 1
|
||||
: clipped.length;
|
||||
|
||||
_focusNodes[nextIndex].requestFocus();
|
||||
_emit();
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _onChanged(int index, String value) {
|
||||
if (!mounted) return;
|
||||
|
||||
if (value.length > 1) {
|
||||
_setFromPaste(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.isNotEmpty && index < widget.length - 1) {
|
||||
_focusNodes[index + 1].requestFocus();
|
||||
}
|
||||
|
||||
_emit();
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
KeyEventResult _onKey(int index, KeyEvent event) {
|
||||
if (event is! KeyDownEvent) return KeyEventResult.ignored;
|
||||
|
||||
if (event.logicalKey == LogicalKeyboardKey.backspace) {
|
||||
final current = _controllers[index].text;
|
||||
|
||||
if (current.isEmpty && index > 0) {
|
||||
_controllers[index - 1].text = '';
|
||||
_focusNodes[index - 1].requestFocus();
|
||||
_emit();
|
||||
setState(() {});
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
}
|
||||
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final borderColor = widget.errorText == null || widget.errorText!.isEmpty
|
||||
? Theme.of(context).dividerColor
|
||||
: Theme.of(context).colorScheme.error;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: widget.gap,
|
||||
children: List.generate(widget.length, (i) {
|
||||
return SizedBox(
|
||||
width: widget.boxSize,
|
||||
height: widget.boxSize,
|
||||
child: Focus(
|
||||
onKeyEvent: (_, event) => _onKey(i, event),
|
||||
child: TextField(
|
||||
enabled: widget.enabled,
|
||||
controller: _controllers[i],
|
||||
focusNode: _focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: i == widget.length - 1
|
||||
? TextInputAction.done
|
||||
: TextInputAction.next,
|
||||
textAlign: TextAlign.center,
|
||||
maxLength: 1,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(1),
|
||||
],
|
||||
decoration: InputDecoration(
|
||||
counterText: '',
|
||||
contentPadding: EdgeInsets.zero,
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: BorderSide(color: borderColor),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
width: 1.6,
|
||||
),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
width: 1.2,
|
||||
),
|
||||
),
|
||||
focusedErrorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
width: 1.6,
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (v) => _onChanged(i, v),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
if (widget.errorText != null && widget.errorText!.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Text(
|
||||
widget.errorText!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:auth/src/features/login/presentation/widgets/otp_code_fields.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class TwoFactorBottomSheetView extends StatelessWidget {
|
||||
const TwoFactorBottomSheetView({
|
||||
super.key,
|
||||
required this.theme,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.verifyText,
|
||||
required this.closeText,
|
||||
required this.isOtpLoading,
|
||||
required this.otpCode,
|
||||
required this.otpErrorText,
|
||||
required this.onChanged,
|
||||
required this.onVerify,
|
||||
required this.onClose,
|
||||
});
|
||||
|
||||
final ThemePort theme;
|
||||
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String verifyText;
|
||||
final String closeText;
|
||||
|
||||
final bool isOtpLoading;
|
||||
final String otpCode;
|
||||
final String otpErrorText;
|
||||
|
||||
final ValueChanged<String> onChanged;
|
||||
final Future<void> Function() onVerify;
|
||||
final VoidCallback onClose;
|
||||
|
||||
bool get _isValidOtp => otpCode.trim().length == 6;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bottomInset = MediaQuery.of(context).viewInsets.bottom;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
padding: EdgeInsets.fromLTRB(24, 12, 24, 24 + bottomInset),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
height: 4,
|
||||
width: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.withValues(alpha: 0.35),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
subtitle,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
OtpCodeFields(
|
||||
length: 6,
|
||||
enabled: !isOtpLoading,
|
||||
errorText: otpErrorText.isEmpty ? null : otpErrorText,
|
||||
onChanged: onChanged,
|
||||
onCompleted: (_) {
|
||||
if (isOtpLoading || !_isValidOtp) return;
|
||||
unawaited(onVerify());
|
||||
},
|
||||
gap: SizeUtils.getByScreen(small: 10, big: 8, xl: 4),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 38)),
|
||||
|
||||
PrimaryButton(
|
||||
onPressed: (isOtpLoading || !_isValidOtp)
|
||||
? () {}
|
||||
: () => unawaited(onVerify()),
|
||||
text: verifyText,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
leading: isOtpLoading
|
||||
? const SizedBox(
|
||||
height: 18,
|
||||
width: 18,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 12, big: 9)),
|
||||
|
||||
TextButton(
|
||||
onPressed: isOtpLoading ? null : onClose,
|
||||
child: Text(closeText),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
abstract class RecoverPasswordUseCase {
|
||||
Future<String> requestEmail({required String email});
|
||||
|
||||
Future<String> requestSms({required String phone});
|
||||
|
||||
Future<void> recoverPassword({required String newPassword, required String token});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart';
|
||||
|
||||
class RecoverPasswordUseCaseImpl implements RecoverPasswordUseCase {
|
||||
RecoverPasswordUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<String> requestEmail({required String email}) async {
|
||||
return await _repository.requestPasswordReset(email: email);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestSms({required String phone}) async {
|
||||
return await _repository.requestPasswordReset(phone: phone);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({required String newPassword, required String token}) async {
|
||||
await _repository.recoverPassword(newPassword: newPassword, token: token);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
import 'package:auth/src/features/link_phone/presentation/link_phone_screen.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password/new_password_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class LinkPhoneBuilder {
|
||||
const LinkPhoneBuilder();
|
||||
class NewPasswordBuilder {
|
||||
const NewPasswordBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: LinkPhoneScreen(navigationContract: navigationContract),
|
||||
child: NewPasswordScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/state/recover_password_view_model.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class NewPasswordScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const NewPasswordScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordTitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 30, xl: 26),
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 42, big: 32)),
|
||||
CustomTextField(
|
||||
showPassword: viewState.passwordVisible,
|
||||
label: context.translate(I18n.newPassword),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
hint: '********',
|
||||
controller: viewModel.passwordController,
|
||||
// onVisibilityChanged: viewModel.togglePasswordVisible,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
CustomTextField(
|
||||
showPassword: viewState.passwordVisible,
|
||||
label: context.translate(I18n.repeatPassword),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
hint: '********',
|
||||
controller: viewModel.repeatedPasswordController,
|
||||
// onVisibilityChanged: viewModel.togglePasswordVisible,
|
||||
// color: viewState.equalPasswords ? const Color(0xFF4B4B4B) : const Color.fromRGBO(239, 17, 17, 1),
|
||||
),
|
||||
if (!viewState.equalPasswords) ...[
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 8, big: 8)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.info_outline_rounded,
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
size: 16,
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.errorMessageUnequalPasswords),
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
],
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
viewState.securityChecks['min']!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.passwordLength),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(
|
||||
small: 14,
|
||||
big: 14,
|
||||
xl: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 2, big: 4)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
viewState.securityChecks['capital']!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.passwordCapital),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(
|
||||
small: 14,
|
||||
big: 14,
|
||||
xl: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 2, big: 4)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
viewState.securityChecks['number']!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.passwordNumber),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(
|
||||
small: 14,
|
||||
big: 14,
|
||||
xl: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 2, big: 4)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
viewState.securityChecks['special']!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.passwordSpecial),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(
|
||||
small: 14,
|
||||
big: 14,
|
||||
xl: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: SizeUtils.getByScreen(small: 28, big: 32, xl: 24),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
context.translate(I18n.mobilePhone),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(
|
||||
small: 14,
|
||||
big: 14,
|
||||
xl: 12,
|
||||
),
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
width: 80,
|
||||
onChanged: (country) {
|
||||
viewModel.updateDialCode(
|
||||
country.dialCode ?? viewState.dialCode,
|
||||
);
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
keyboardType: TextInputType.number,
|
||||
controller: viewModel.newPhoneNumberController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (viewState.errorMessage.isNotEmpty) ...[
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
context.translate(viewState.errorMessage),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
SizedBox(height: 56),
|
||||
PrimaryButton(
|
||||
onPressed: () async {
|
||||
await viewModel.recoverPassword();
|
||||
final updatedState = ref.read(
|
||||
recoverPasswordViewModelProvider,
|
||||
);
|
||||
if (updatedState.passwordChanged) {
|
||||
navigationContract.goTo(AppRoutes.dashboardHome);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.accept),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class NewPasswordScreen extends ConsumerStatefulWidget {
|
||||
const NewPasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<NewPasswordScreen> createState() => NewPasswordScreenState();
|
||||
}
|
||||
|
||||
class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
|
||||
bool passwordVisible = false;
|
||||
bool equalPasswords = false;
|
||||
String password = '';
|
||||
|
||||
Map<String, bool> securityChecks = {
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
passwordVisible = false;
|
||||
equalPasswords = false;
|
||||
password = '';
|
||||
securityChecks = {
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
const Text(
|
||||
"Recuperar contraseña",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30, letterSpacing: 0),
|
||||
),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Nueva contraseña",
|
||||
hint: "********",
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
password = value;
|
||||
securityChecks = checkSecurity(value);
|
||||
}),
|
||||
},
|
||||
),
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Repetir contraseña",
|
||||
hint: "********",
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
equalPasswords = password == value;
|
||||
}),
|
||||
},
|
||||
),
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["min"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
const Text("Al menos 8 caracteres", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["capital"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
const Text("Una mayúscula", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["number"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
const Text("Un número", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["special"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
const Text("Un carácter especial", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: const Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
)
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
||||
onChanged: (value)=> {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
numeric: true
|
||||
))
|
||||
]
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: ()=>{navigationContract.goTo(AppRoutes.dashboardHome)},
|
||||
text: "Aceptar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: Extraer de la vista
|
||||
Map<String, bool> checkSecurity(String value) {
|
||||
return {
|
||||
'min': value.length >= 8,
|
||||
'capital': RegExp(r'[A-Z]').hasMatch(value),
|
||||
'number': RegExp(r'[0-9]').hasMatch(value),
|
||||
'special': RegExp(r'[^A-Za-z0-9]').hasMatch(value),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../domain/use_cases/recover_password_use_case.dart';
|
||||
import '../../domain/use_cases/recover_password_use_case_impl.dart';
|
||||
|
||||
final recoverPasswordUseCaseProvider = Provider.autoDispose<RecoverPasswordUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return RecoverPasswordUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class RequestRecoveryBuilder {
|
||||
const RequestRecoveryBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RequestRecoveryScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/sent/sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
import '../state/recover_password_view_model.dart';
|
||||
|
||||
class RequestRecoveryScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const RequestRecoveryScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: SizeUtils.getByScreen(small: 30, big: 30, xl: 20)),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordTitle),
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: SizeUtils.getByScreen(small: 29, big: 27, xl: 26)),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 32)),
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordSubtitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(letterSpacing: 0, fontSize: SizeUtils.getByScreen(small: 18, big: 18, xl: 16)),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 56, big: 52)),
|
||||
CustomTextField(
|
||||
label: context.translate(I18n.email),
|
||||
hint: context.translate(I18n.email),
|
||||
controller: viewModel.emailController,
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 36, big: 36, xl: 26)),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
context.translate(I18n.mobilePhone),
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
initialCountryCode: viewState.dialCode,
|
||||
onChanged: (country) {
|
||||
viewModel.updateDialCode(
|
||||
country.dialCode ?? viewState.dialCode,
|
||||
);
|
||||
},
|
||||
width: 80,
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6)),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
keyboardType: TextInputType.number,
|
||||
controller: viewModel.phoneNumberController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 40, big: 40, xl: 28)),
|
||||
if (viewState.errorMessage.isNotEmpty) ...[
|
||||
Text(
|
||||
context.translate(viewState.errorMessage),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40),
|
||||
],
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
text: context.translate(I18n.back),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 20, big: 20, xl: 10)),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () async {
|
||||
await viewModel.requestRecovery();
|
||||
final updatedState = ref.read(recoverPasswordViewModelProvider);
|
||||
if (updatedState.recoveryRequested) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SentScreen(navigationContract: navigationContract),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.send),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class RestorePasswordScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const RestorePasswordScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Text(
|
||||
"Recuperar contaseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text(
|
||||
"Introduce tu email para enviarte un enlace de recuperación",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 40,
|
||||
children: [
|
||||
CustomTextField(
|
||||
label: "Correo electrónico",
|
||||
hint: "Correo electrónico",
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
],
|
||||
onChanged: (value) => {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
numeric: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
text: "Volver",
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SentScreen(format: "email"),
|
||||
),
|
||||
),
|
||||
},
|
||||
text: "Enviar",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
import 'package:auth/src/features/login/presentation/phone_code_screen.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/sent/sent_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class PhoneCodeBuilder {
|
||||
const PhoneCodeBuilder();
|
||||
class SentBuilder {
|
||||
const SentBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: PhoneCodeScreen(navigationContract: navigationContract),
|
||||
child: SentScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password/new_password_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
import '../state/recover_password_view_model.dart';
|
||||
|
||||
class SentScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const SentScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordTitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 30, xl: 26),
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6)),
|
||||
Text(
|
||||
viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.emailSent)
|
||||
: context.translate(I18n.smsSent),
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 18, xl: 15), fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40)),
|
||||
Text(
|
||||
viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.checkEmail1)
|
||||
: context.translate(I18n.checkSms1),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 17, big: 17, xl: 14), letterSpacing: 0),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 16, big: 16, xl: 14)),
|
||||
Text(
|
||||
viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.checkEmail2)
|
||||
: context.translate(I18n.checkSms2),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12), letterSpacing: 0),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 48, xl: 38)),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () {
|
||||
if ( viewState.recoveryFormat == "email") {
|
||||
viewModel.requestEmail();
|
||||
} else {
|
||||
viewModel.requestSms();
|
||||
}
|
||||
},
|
||||
text: viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.resendEmail)
|
||||
: context.translate(I18n.resendSms),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => NewPasswordScreen(navigationContract: navigationContract)),
|
||||
),
|
||||
text: context.translate(I18n.continueKey),
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class SentScreen extends ConsumerWidget {
|
||||
final String format;
|
||||
|
||||
const SentScreen({super.key, required this.format});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 30,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Text(
|
||||
format == "email"
|
||||
? "Correo enviado correctamente"
|
||||
: "SMS enviado correctamente",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
format == "email"
|
||||
? "Revisa tu email y haz clic en el enlace para crear una nueva contraseña."
|
||||
: "Revisa tu móvil y sigue las instrucciones para crear una nueva contraseña.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||
),
|
||||
Text(
|
||||
format == "email"
|
||||
? "Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"."
|
||||
: "Si no recibes el SMS en unos minutos, asegúrate de tener cobertura o pulsa \"Reenviar SMS \".",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {},
|
||||
text: format == "email"
|
||||
? "Reenviar correo"
|
||||
: "Reenviar SMS",
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => NewPasswordScreen()),
|
||||
),
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
import 'package:auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/state/recover_password_view_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../providers/recover_password_provider.dart';
|
||||
|
||||
final recoverPasswordViewModelProvider =
|
||||
NotifierProvider.autoDispose<RecoverPasswordViewModel, RecoverPasswordViewState>(
|
||||
RecoverPasswordViewModel.new,
|
||||
);
|
||||
|
||||
class RecoverPasswordViewModel extends Notifier<RecoverPasswordViewState> {
|
||||
late final RecoverPasswordUseCase _recoverPasswordUseCase;
|
||||
late final TextEditingController phoneNumberController;
|
||||
late final TextEditingController emailController;
|
||||
late final TextEditingController passwordController;
|
||||
late final TextEditingController repeatedPasswordController;
|
||||
late final TextEditingController newPhoneNumberController;
|
||||
|
||||
@override
|
||||
RecoverPasswordViewState build() {
|
||||
_recoverPasswordUseCase = ref.read(recoverPasswordUseCaseProvider);
|
||||
|
||||
phoneNumberController = TextEditingController();
|
||||
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||
|
||||
emailController = TextEditingController();
|
||||
emailController.addListener(_onEmailChanged);
|
||||
|
||||
passwordController = TextEditingController();
|
||||
passwordController.addListener(_onPasswordChanged);
|
||||
|
||||
repeatedPasswordController = TextEditingController();
|
||||
repeatedPasswordController.addListener(_onRepeatedPasswordChanged);
|
||||
|
||||
newPhoneNumberController = TextEditingController();
|
||||
newPhoneNumberController.addListener(_onNewPhoneNumberChanged);
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return const RecoverPasswordViewState();
|
||||
}
|
||||
|
||||
void _onPhoneNumberChanged() {
|
||||
final String raw = phoneNumberController.text;
|
||||
state = state.copyWith(
|
||||
phoneNumber: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onNewPhoneNumberChanged() {
|
||||
final String raw = newPhoneNumberController.text;
|
||||
state = state.copyWith(
|
||||
newPhoneNumber: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onEmailChanged() {
|
||||
final String raw = emailController.text;
|
||||
state = state.copyWith(
|
||||
email: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onPasswordChanged() {
|
||||
final String raw = passwordController.text;
|
||||
final bool equalPasswords = raw == repeatedPasswordController.text;
|
||||
|
||||
final bool minCheck = raw.length >= 8;
|
||||
final bool capitalCheck = RegExp(r'[A-Z]').hasMatch(raw);
|
||||
final bool numberCheck = RegExp(r'[0-9]').hasMatch(raw);
|
||||
final bool specialCheck = RegExp(r'[^A-Za-z0-9]').hasMatch(raw);
|
||||
|
||||
final Map<String, bool> security = {
|
||||
'min': minCheck,
|
||||
'capital': capitalCheck,
|
||||
'number': numberCheck,
|
||||
'special': specialCheck,
|
||||
};
|
||||
|
||||
state = state.copyWith(
|
||||
password: raw,
|
||||
errorMessage: '',
|
||||
equalPasswords: equalPasswords,
|
||||
securityChecks: security,
|
||||
);
|
||||
}
|
||||
|
||||
void _onRepeatedPasswordChanged() {
|
||||
final String raw = repeatedPasswordController.text;
|
||||
final bool equalPasswords = raw == passwordController.text;
|
||||
state = state.copyWith(
|
||||
repeatedPassword: raw,
|
||||
errorMessage: '',
|
||||
equalPasswords: equalPasswords,
|
||||
);
|
||||
}
|
||||
|
||||
void updateDialCode(String dialCode) {
|
||||
state = state.copyWith(
|
||||
dialCode: dialCode,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void updateNewDialCode(String dialCode) {
|
||||
state = state.copyWith(
|
||||
newDialCode: dialCode,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void togglePasswordVisible(){
|
||||
state = state.copyWith(
|
||||
passwordVisible: !state.passwordVisible,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> requestRecovery() async {
|
||||
final trimmedNumber = state.phoneNumber.trim();
|
||||
final email = state.email.trim();
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
|
||||
if (email.isNotEmpty) {
|
||||
await requestEmail();
|
||||
} else if (trimmedNumber.isNotEmpty) {
|
||||
await requestSms();
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'errorMessageContactIsEmpty',
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestEmail() async {
|
||||
final email = state.email.trim();
|
||||
|
||||
try {
|
||||
final String token = await _recoverPasswordUseCase.requestEmail(email: email);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
recoveryRequested: true,
|
||||
token: token,
|
||||
recoveryFormat: 'email',
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
recoveryRequested: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestSms() async {
|
||||
final trimmedNumber = state.phoneNumber.trim();
|
||||
|
||||
final fullPhone = '${state.dialCode}$trimmedNumber';
|
||||
|
||||
try {
|
||||
final String token = await _recoverPasswordUseCase.requestSms(phone: fullPhone);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
recoveryRequested: true,
|
||||
token: token,
|
||||
recoveryFormat: 'sms'
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
recoveryRequested: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> recoverPassword() async {
|
||||
//final String fullPhone = state.newDialCode + state.newPhoneNumber;
|
||||
final String password = state.password;
|
||||
|
||||
if (!state.equalPasswords) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessageUnequalPasswords',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['min']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordTooShort',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['capital']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoCapitals',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['number']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoNumbers',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['special']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoSpecialChars',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
passwordChanged: false,
|
||||
);
|
||||
try {
|
||||
await _recoverPasswordUseCase.recoverPassword(
|
||||
newPassword: password, token: state.token);
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
passwordChanged: true,
|
||||
);
|
||||
} catch (error) {
|
||||
state = state.copyWith(
|
||||
errorMessage: error.toString(),
|
||||
isLoading: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
phoneNumberController.removeListener(_onPhoneNumberChanged);
|
||||
phoneNumberController.dispose();
|
||||
emailController.removeListener(_onPhoneNumberChanged);
|
||||
emailController.dispose();
|
||||
passwordController.removeListener(_onPasswordChanged);
|
||||
passwordController.dispose();
|
||||
repeatedPasswordController.removeListener(_onRepeatedPasswordChanged);
|
||||
repeatedPasswordController.dispose();
|
||||
newPhoneNumberController.removeListener(_onNewPhoneNumberChanged);
|
||||
newPhoneNumberController.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recover_password_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class RecoverPasswordViewState with _$RecoverPasswordViewState {
|
||||
const factory RecoverPasswordViewState({
|
||||
@Default('') String phoneNumber,
|
||||
@Default('+34') String dialCode,
|
||||
@Default('') String email,
|
||||
@Default('') String errorMessage,
|
||||
@Default('') String recoveryFormat,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool recoveryRequested,
|
||||
@Default(false) bool passwordChanged,
|
||||
@Default('') String token,
|
||||
@Default('') String password,
|
||||
@Default('') String repeatedPassword,
|
||||
@Default(false) bool passwordVisible,
|
||||
@Default(true) bool equalPasswords,
|
||||
@Default('+34') String newDialCode,
|
||||
@Default('') String newPhoneNumber,
|
||||
@Default({
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
}) Map<String, bool> securityChecks,
|
||||
}) = _RecoverPasswordViewState;
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
// 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 'recover_password_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$RecoverPasswordViewState {
|
||||
|
||||
String get phoneNumber; String get dialCode; String get email; String get errorMessage; String get recoveryFormat; bool get isLoading; bool get recoveryRequested; bool get passwordChanged; String get token; String get password; String get repeatedPassword; bool get passwordVisible; bool get equalPasswords; String get newDialCode; String get newPhoneNumber; Map<String, bool> get securityChecks;
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$RecoverPasswordViewStateCopyWith<RecoverPasswordViewState> get copyWith => _$RecoverPasswordViewStateCopyWithImpl<RecoverPasswordViewState>(this as RecoverPasswordViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is RecoverPasswordViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.email, email) || other.email == email)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.recoveryFormat, recoveryFormat) || other.recoveryFormat == recoveryFormat)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.recoveryRequested, recoveryRequested) || other.recoveryRequested == recoveryRequested)&&(identical(other.passwordChanged, passwordChanged) || other.passwordChanged == passwordChanged)&&(identical(other.token, token) || other.token == token)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatedPassword, repeatedPassword) || other.repeatedPassword == repeatedPassword)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.equalPasswords, equalPasswords) || other.equalPasswords == equalPasswords)&&(identical(other.newDialCode, newDialCode) || other.newDialCode == newDialCode)&&(identical(other.newPhoneNumber, newPhoneNumber) || other.newPhoneNumber == newPhoneNumber)&&const DeepCollectionEquality().equals(other.securityChecks, securityChecks));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,email,errorMessage,recoveryFormat,isLoading,recoveryRequested,passwordChanged,token,password,repeatedPassword,passwordVisible,equalPasswords,newDialCode,newPhoneNumber,const DeepCollectionEquality().hash(securityChecks));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecoverPasswordViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, email: $email, errorMessage: $errorMessage, recoveryFormat: $recoveryFormat, isLoading: $isLoading, recoveryRequested: $recoveryRequested, passwordChanged: $passwordChanged, token: $token, password: $password, repeatedPassword: $repeatedPassword, passwordVisible: $passwordVisible, equalPasswords: $equalPasswords, newDialCode: $newDialCode, newPhoneNumber: $newPhoneNumber, securityChecks: $securityChecks)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
factory $RecoverPasswordViewStateCopyWith(RecoverPasswordViewState value, $Res Function(RecoverPasswordViewState) _then) = _$RecoverPasswordViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$RecoverPasswordViewStateCopyWithImpl<$Res>
|
||||
implements $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
_$RecoverPasswordViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final RecoverPasswordViewState _self;
|
||||
final $Res Function(RecoverPasswordViewState) _then;
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? email = null,Object? errorMessage = null,Object? recoveryFormat = null,Object? isLoading = null,Object? recoveryRequested = null,Object? passwordChanged = null,Object? token = null,Object? password = null,Object? repeatedPassword = null,Object? passwordVisible = null,Object? equalPasswords = null,Object? newDialCode = null,Object? newPhoneNumber = null,Object? securityChecks = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,recoveryFormat: null == recoveryFormat ? _self.recoveryFormat : recoveryFormat // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,recoveryRequested: null == recoveryRequested ? _self.recoveryRequested : recoveryRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,passwordChanged: null == passwordChanged ? _self.passwordChanged : passwordChanged // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatedPassword: null == repeatedPassword ? _self.repeatedPassword : repeatedPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,equalPasswords: null == equalPasswords ? _self.equalPasswords : equalPasswords // ignore: cast_nullable_to_non_nullable
|
||||
as bool,newDialCode: null == newDialCode ? _self.newDialCode : newDialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPhoneNumber: null == newPhoneNumber ? _self.newPhoneNumber : newPhoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,securityChecks: null == securityChecks ? _self.securityChecks : securityChecks // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, bool>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [RecoverPasswordViewState].
|
||||
extension RecoverPasswordViewStatePatterns on RecoverPasswordViewState {
|
||||
/// 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( _RecoverPasswordViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() 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( _RecoverPasswordViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState():
|
||||
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( _RecoverPasswordViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() 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( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);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( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState():
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);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( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _RecoverPasswordViewState implements RecoverPasswordViewState {
|
||||
const _RecoverPasswordViewState({this.phoneNumber = '', this.dialCode = '+34', this.email = '', this.errorMessage = '', this.recoveryFormat = '', this.isLoading = false, this.recoveryRequested = false, this.passwordChanged = false, this.token = '', this.password = '', this.repeatedPassword = '', this.passwordVisible = false, this.equalPasswords = true, this.newDialCode = '+34', this.newPhoneNumber = '', final Map<String, bool> securityChecks = const {'min' : false, 'capital' : false, 'number' : false, 'special' : false}}): _securityChecks = securityChecks;
|
||||
|
||||
|
||||
@override@JsonKey() final String phoneNumber;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override@JsonKey() final String email;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final String recoveryFormat;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool recoveryRequested;
|
||||
@override@JsonKey() final bool passwordChanged;
|
||||
@override@JsonKey() final String token;
|
||||
@override@JsonKey() final String password;
|
||||
@override@JsonKey() final String repeatedPassword;
|
||||
@override@JsonKey() final bool passwordVisible;
|
||||
@override@JsonKey() final bool equalPasswords;
|
||||
@override@JsonKey() final String newDialCode;
|
||||
@override@JsonKey() final String newPhoneNumber;
|
||||
final Map<String, bool> _securityChecks;
|
||||
@override@JsonKey() Map<String, bool> get securityChecks {
|
||||
if (_securityChecks is EqualUnmodifiableMapView) return _securityChecks;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_securityChecks);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$RecoverPasswordViewStateCopyWith<_RecoverPasswordViewState> get copyWith => __$RecoverPasswordViewStateCopyWithImpl<_RecoverPasswordViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RecoverPasswordViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.email, email) || other.email == email)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.recoveryFormat, recoveryFormat) || other.recoveryFormat == recoveryFormat)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.recoveryRequested, recoveryRequested) || other.recoveryRequested == recoveryRequested)&&(identical(other.passwordChanged, passwordChanged) || other.passwordChanged == passwordChanged)&&(identical(other.token, token) || other.token == token)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatedPassword, repeatedPassword) || other.repeatedPassword == repeatedPassword)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.equalPasswords, equalPasswords) || other.equalPasswords == equalPasswords)&&(identical(other.newDialCode, newDialCode) || other.newDialCode == newDialCode)&&(identical(other.newPhoneNumber, newPhoneNumber) || other.newPhoneNumber == newPhoneNumber)&&const DeepCollectionEquality().equals(other._securityChecks, _securityChecks));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,email,errorMessage,recoveryFormat,isLoading,recoveryRequested,passwordChanged,token,password,repeatedPassword,passwordVisible,equalPasswords,newDialCode,newPhoneNumber,const DeepCollectionEquality().hash(_securityChecks));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecoverPasswordViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, email: $email, errorMessage: $errorMessage, recoveryFormat: $recoveryFormat, isLoading: $isLoading, recoveryRequested: $recoveryRequested, passwordChanged: $passwordChanged, token: $token, password: $password, repeatedPassword: $repeatedPassword, passwordVisible: $passwordVisible, equalPasswords: $equalPasswords, newDialCode: $newDialCode, newPhoneNumber: $newPhoneNumber, securityChecks: $securityChecks)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$RecoverPasswordViewStateCopyWith<$Res> implements $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
factory _$RecoverPasswordViewStateCopyWith(_RecoverPasswordViewState value, $Res Function(_RecoverPasswordViewState) _then) = __$RecoverPasswordViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$RecoverPasswordViewStateCopyWithImpl<$Res>
|
||||
implements _$RecoverPasswordViewStateCopyWith<$Res> {
|
||||
__$RecoverPasswordViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _RecoverPasswordViewState _self;
|
||||
final $Res Function(_RecoverPasswordViewState) _then;
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? email = null,Object? errorMessage = null,Object? recoveryFormat = null,Object? isLoading = null,Object? recoveryRequested = null,Object? passwordChanged = null,Object? token = null,Object? password = null,Object? repeatedPassword = null,Object? passwordVisible = null,Object? equalPasswords = null,Object? newDialCode = null,Object? newPhoneNumber = null,Object? securityChecks = null,}) {
|
||||
return _then(_RecoverPasswordViewState(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,recoveryFormat: null == recoveryFormat ? _self.recoveryFormat : recoveryFormat // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,recoveryRequested: null == recoveryRequested ? _self.recoveryRequested : recoveryRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,passwordChanged: null == passwordChanged ? _self.passwordChanged : passwordChanged // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatedPassword: null == repeatedPassword ? _self.repeatedPassword : repeatedPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,equalPasswords: null == equalPasswords ? _self.equalPasswords : equalPasswords // ignore: cast_nullable_to_non_nullable
|
||||
as bool,newDialCode: null == newDialCode ? _self.newDialCode : newDialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPhoneNumber: null == newPhoneNumber ? _self.newPhoneNumber : newPhoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,securityChecks: null == securityChecks ? _self._securityChecks : securityChecks // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, bool>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/restore_password_screen.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
@@ -12,7 +12,7 @@ class RecoverPasswordBuilder {
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RestorePasswordScreen(navigationContract: navigationContract),
|
||||
child: RequestRecoveryScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'address_entity.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class AddressEntity with _$AddressEntity {
|
||||
const factory AddressEntity({
|
||||
required String street,
|
||||
required String city,
|
||||
required String province,
|
||||
required String state,
|
||||
required String country,
|
||||
required int postCode,
|
||||
}) = _AddressEntity;
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
// 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 'address_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$AddressEntity {
|
||||
|
||||
String get street; String get city; String get province; String get state; String get country; int get postCode;
|
||||
/// Create a copy of AddressEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AddressEntityCopyWith<AddressEntity> get copyWith => _$AddressEntityCopyWithImpl<AddressEntity>(this as AddressEntity, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AddressEntity&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressEntity(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AddressEntityCopyWith<$Res> {
|
||||
factory $AddressEntityCopyWith(AddressEntity value, $Res Function(AddressEntity) _then) = _$AddressEntityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AddressEntityCopyWithImpl<$Res>
|
||||
implements $AddressEntityCopyWith<$Res> {
|
||||
_$AddressEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AddressEntity _self;
|
||||
final $Res Function(AddressEntity) _then;
|
||||
|
||||
/// Create a copy of AddressEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: null == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AddressEntity].
|
||||
extension AddressEntityPatterns on AddressEntity {
|
||||
/// 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( _AddressEntity value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity() 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( _AddressEntity value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity():
|
||||
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( _AddressEntity value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity() 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( String street, String city, String province, String state, String country, int postCode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int postCode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity():
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int postCode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressEntity() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _AddressEntity implements AddressEntity {
|
||||
const _AddressEntity({required this.street, required this.city, required this.province, required this.state, required this.country, required this.postCode});
|
||||
|
||||
|
||||
@override final String street;
|
||||
@override final String city;
|
||||
@override final String province;
|
||||
@override final String state;
|
||||
@override final String country;
|
||||
@override final int postCode;
|
||||
|
||||
/// Create a copy of AddressEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AddressEntityCopyWith<_AddressEntity> get copyWith => __$AddressEntityCopyWithImpl<_AddressEntity>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AddressEntity&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressEntity(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AddressEntityCopyWith<$Res> implements $AddressEntityCopyWith<$Res> {
|
||||
factory _$AddressEntityCopyWith(_AddressEntity value, $Res Function(_AddressEntity) _then) = __$AddressEntityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AddressEntityCopyWithImpl<$Res>
|
||||
implements _$AddressEntityCopyWith<$Res> {
|
||||
__$AddressEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AddressEntity _self;
|
||||
final $Res Function(_AddressEntity) _then;
|
||||
|
||||
/// Create a copy of AddressEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = null,}) {
|
||||
return _then(_AddressEntity(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: null == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'address_entity.dart';
|
||||
|
||||
part 'sign_up_request_entity.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class SignUpRequestEntity with _$SignUpRequestEntity {
|
||||
const factory SignUpRequestEntity({
|
||||
required String documentType,
|
||||
required String documentNumber,
|
||||
required String relationship,
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required String email,
|
||||
required String phone,
|
||||
required String language,
|
||||
required String password,
|
||||
required List<AddressEntity> taxResidences,
|
||||
required List<AddressEntity> addresses,
|
||||
required int bornAt,
|
||||
required String userId, // UUID
|
||||
required String placeOfBirth,
|
||||
required String birthCountry,
|
||||
}) = _SignUpRequestEntity;
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
// 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 'sign_up_request_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SignUpRequestEntity {
|
||||
|
||||
String get documentType; String get documentNumber; String get relationship; String get firstName; String get lastName; String get email; String get phone; String get language; String get password; List<AddressEntity> get taxResidences; List<AddressEntity> get addresses; int get bornAt; String get userId;// UUID
|
||||
String get placeOfBirth; String get birthCountry;
|
||||
/// Create a copy of SignUpRequestEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpRequestEntityCopyWith<SignUpRequestEntity> get copyWith => _$SignUpRequestEntityCopyWithImpl<SignUpRequestEntity>(this as SignUpRequestEntity, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SignUpRequestEntity&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.relationship, relationship) || other.relationship == relationship)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.language, language) || other.language == language)&&(identical(other.password, password) || other.password == password)&&const DeepCollectionEquality().equals(other.taxResidences, taxResidences)&&const DeepCollectionEquality().equals(other.addresses, addresses)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,documentType,documentNumber,relationship,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(taxResidences),const DeepCollectionEquality().hash(addresses),bornAt,userId,placeOfBirth,birthCountry);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpRequestEntity(documentType: $documentType, documentNumber: $documentNumber, relationship: $relationship, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SignUpRequestEntityCopyWith<$Res> {
|
||||
factory $SignUpRequestEntityCopyWith(SignUpRequestEntity value, $Res Function(SignUpRequestEntity) _then) = _$SignUpRequestEntityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String documentType, String documentNumber, String relationship, String firstName, String lastName, String email, String phone, String language, String password, List<AddressEntity> taxResidences, List<AddressEntity> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SignUpRequestEntityCopyWithImpl<$Res>
|
||||
implements $SignUpRequestEntityCopyWith<$Res> {
|
||||
_$SignUpRequestEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SignUpRequestEntity _self;
|
||||
final $Res Function(SignUpRequestEntity) _then;
|
||||
|
||||
/// Create a copy of SignUpRequestEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? documentType = null,Object? documentNumber = null,Object? relationship = null,Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? language = null,Object? password = null,Object? taxResidences = null,Object? addresses = null,Object? bornAt = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,taxResidences: null == taxResidences ? _self.taxResidences : taxResidences // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressEntity>,addresses: null == addresses ? _self.addresses : addresses // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressEntity>,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SignUpRequestEntity].
|
||||
extension SignUpRequestEntityPatterns on SignUpRequestEntity {
|
||||
/// 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( _SignUpRequestEntity value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity() 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( _SignUpRequestEntity value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity():
|
||||
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( _SignUpRequestEntity value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity() 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( String documentType, String documentNumber, String relationship, String firstName, String lastName, String email, String phone, String language, String password, List<AddressEntity> taxResidences, List<AddressEntity> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity() when $default != null:
|
||||
return $default(_that.documentType,_that.documentNumber,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry);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( String documentType, String documentNumber, String relationship, String firstName, String lastName, String email, String phone, String language, String password, List<AddressEntity> taxResidences, List<AddressEntity> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity():
|
||||
return $default(_that.documentType,_that.documentNumber,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry);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( String documentType, String documentNumber, String relationship, String firstName, String lastName, String email, String phone, String language, String password, List<AddressEntity> taxResidences, List<AddressEntity> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpRequestEntity() when $default != null:
|
||||
return $default(_that.documentType,_that.documentNumber,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.userId,_that.placeOfBirth,_that.birthCountry);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _SignUpRequestEntity implements SignUpRequestEntity {
|
||||
const _SignUpRequestEntity({required this.documentType, required this.documentNumber, required this.relationship, required this.firstName, required this.lastName, required this.email, required this.phone, required this.language, required this.password, required final List<AddressEntity> taxResidences, required final List<AddressEntity> addresses, required this.bornAt, required this.userId, required this.placeOfBirth, required this.birthCountry}): _taxResidences = taxResidences,_addresses = addresses;
|
||||
|
||||
|
||||
@override final String documentType;
|
||||
@override final String documentNumber;
|
||||
@override final String relationship;
|
||||
@override final String firstName;
|
||||
@override final String lastName;
|
||||
@override final String email;
|
||||
@override final String phone;
|
||||
@override final String language;
|
||||
@override final String password;
|
||||
final List<AddressEntity> _taxResidences;
|
||||
@override List<AddressEntity> get taxResidences {
|
||||
if (_taxResidences is EqualUnmodifiableListView) return _taxResidences;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_taxResidences);
|
||||
}
|
||||
|
||||
final List<AddressEntity> _addresses;
|
||||
@override List<AddressEntity> get addresses {
|
||||
if (_addresses is EqualUnmodifiableListView) return _addresses;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_addresses);
|
||||
}
|
||||
|
||||
@override final int bornAt;
|
||||
@override final String userId;
|
||||
// UUID
|
||||
@override final String placeOfBirth;
|
||||
@override final String birthCountry;
|
||||
|
||||
/// Create a copy of SignUpRequestEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SignUpRequestEntityCopyWith<_SignUpRequestEntity> get copyWith => __$SignUpRequestEntityCopyWithImpl<_SignUpRequestEntity>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SignUpRequestEntity&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.relationship, relationship) || other.relationship == relationship)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.language, language) || other.language == language)&&(identical(other.password, password) || other.password == password)&&const DeepCollectionEquality().equals(other._taxResidences, _taxResidences)&&const DeepCollectionEquality().equals(other._addresses, _addresses)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,documentType,documentNumber,relationship,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(_taxResidences),const DeepCollectionEquality().hash(_addresses),bornAt,userId,placeOfBirth,birthCountry);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpRequestEntity(documentType: $documentType, documentNumber: $documentNumber, relationship: $relationship, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SignUpRequestEntityCopyWith<$Res> implements $SignUpRequestEntityCopyWith<$Res> {
|
||||
factory _$SignUpRequestEntityCopyWith(_SignUpRequestEntity value, $Res Function(_SignUpRequestEntity) _then) = __$SignUpRequestEntityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String documentType, String documentNumber, String relationship, String firstName, String lastName, String email, String phone, String language, String password, List<AddressEntity> taxResidences, List<AddressEntity> addresses, int bornAt, String userId, String placeOfBirth, String birthCountry
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SignUpRequestEntityCopyWithImpl<$Res>
|
||||
implements _$SignUpRequestEntityCopyWith<$Res> {
|
||||
__$SignUpRequestEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SignUpRequestEntity _self;
|
||||
final $Res Function(_SignUpRequestEntity) _then;
|
||||
|
||||
/// Create a copy of SignUpRequestEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? documentType = null,Object? documentNumber = null,Object? relationship = null,Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? language = null,Object? password = null,Object? taxResidences = null,Object? addresses = null,Object? bornAt = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,}) {
|
||||
return _then(_SignUpRequestEntity(
|
||||
documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,taxResidences: null == taxResidences ? _self._taxResidences : taxResidences // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressEntity>,addresses: null == addresses ? _self._addresses : addresses // ignore: cast_nullable_to_non_nullable
|
||||
as List<AddressEntity>,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'two_fa_secret_entity.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class TwoFASecretEntity with _$TwoFASecretEntity {
|
||||
const factory TwoFASecretEntity({
|
||||
required bool isCreated,
|
||||
required TwoFASecretItemEntity item,
|
||||
}) = _TwoFASecretEntity;
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class TwoFASecretItemEntity with _$TwoFASecretItemEntity {
|
||||
const factory TwoFASecretItemEntity({
|
||||
required String secret,
|
||||
required String qr,
|
||||
}) = _TwoFASecretItemEntity;
|
||||
}
|
||||
@@ -0,0 +1,552 @@
|
||||
// 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 'two_fa_secret_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$TwoFASecretEntity {
|
||||
|
||||
bool get isCreated; TwoFASecretItemEntity get item;
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretEntityCopyWith<TwoFASecretEntity> get copyWith => _$TwoFASecretEntityCopyWithImpl<TwoFASecretEntity>(this as TwoFASecretEntity, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TwoFASecretEntity&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretEntity(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TwoFASecretEntityCopyWith<$Res> {
|
||||
factory $TwoFASecretEntityCopyWith(TwoFASecretEntity value, $Res Function(TwoFASecretEntity) _then) = _$TwoFASecretEntityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isCreated, TwoFASecretItemEntity item
|
||||
});
|
||||
|
||||
|
||||
$TwoFASecretItemEntityCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TwoFASecretEntityCopyWithImpl<$Res>
|
||||
implements $TwoFASecretEntityCopyWith<$Res> {
|
||||
_$TwoFASecretEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final TwoFASecretEntity _self;
|
||||
final $Res Function(TwoFASecretEntity) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretItemEntity,
|
||||
));
|
||||
}
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemEntityCopyWith<$Res> get item {
|
||||
|
||||
return $TwoFASecretItemEntityCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [TwoFASecretEntity].
|
||||
extension TwoFASecretEntityPatterns on TwoFASecretEntity {
|
||||
/// 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( _TwoFASecretEntity value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity() 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( _TwoFASecretEntity value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity():
|
||||
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( _TwoFASecretEntity value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity() 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( bool isCreated, TwoFASecretItemEntity item)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, TwoFASecretItemEntity item) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity():
|
||||
return $default(_that.isCreated,_that.item);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( bool isCreated, TwoFASecretItemEntity item)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretEntity() when $default != null:
|
||||
return $default(_that.isCreated,_that.item);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _TwoFASecretEntity implements TwoFASecretEntity {
|
||||
const _TwoFASecretEntity({required this.isCreated, required this.item});
|
||||
|
||||
|
||||
@override final bool isCreated;
|
||||
@override final TwoFASecretItemEntity item;
|
||||
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$TwoFASecretEntityCopyWith<_TwoFASecretEntity> get copyWith => __$TwoFASecretEntityCopyWithImpl<_TwoFASecretEntity>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TwoFASecretEntity&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.item, item) || other.item == item));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isCreated,item);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretEntity(isCreated: $isCreated, item: $item)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$TwoFASecretEntityCopyWith<$Res> implements $TwoFASecretEntityCopyWith<$Res> {
|
||||
factory _$TwoFASecretEntityCopyWith(_TwoFASecretEntity value, $Res Function(_TwoFASecretEntity) _then) = __$TwoFASecretEntityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isCreated, TwoFASecretItemEntity item
|
||||
});
|
||||
|
||||
|
||||
@override $TwoFASecretItemEntityCopyWith<$Res> get item;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$TwoFASecretEntityCopyWithImpl<$Res>
|
||||
implements _$TwoFASecretEntityCopyWith<$Res> {
|
||||
__$TwoFASecretEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _TwoFASecretEntity _self;
|
||||
final $Res Function(_TwoFASecretEntity) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isCreated = null,Object? item = null,}) {
|
||||
return _then(_TwoFASecretEntity(
|
||||
isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,item: null == item ? _self.item : item // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretItemEntity,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of TwoFASecretEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemEntityCopyWith<$Res> get item {
|
||||
|
||||
return $TwoFASecretItemEntityCopyWith<$Res>(_self.item, (value) {
|
||||
return _then(_self.copyWith(item: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TwoFASecretItemEntity {
|
||||
|
||||
String get secret; String get qr;
|
||||
/// Create a copy of TwoFASecretItemEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretItemEntityCopyWith<TwoFASecretItemEntity> get copyWith => _$TwoFASecretItemEntityCopyWithImpl<TwoFASecretItemEntity>(this as TwoFASecretItemEntity, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TwoFASecretItemEntity&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.qr, qr) || other.qr == qr));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,secret,qr);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretItemEntity(secret: $secret, qr: $qr)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TwoFASecretItemEntityCopyWith<$Res> {
|
||||
factory $TwoFASecretItemEntityCopyWith(TwoFASecretItemEntity value, $Res Function(TwoFASecretItemEntity) _then) = _$TwoFASecretItemEntityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String secret, String qr
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TwoFASecretItemEntityCopyWithImpl<$Res>
|
||||
implements $TwoFASecretItemEntityCopyWith<$Res> {
|
||||
_$TwoFASecretItemEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final TwoFASecretItemEntity _self;
|
||||
final $Res Function(TwoFASecretItemEntity) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretItemEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? secret = null,Object? qr = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String,qr: null == qr ? _self.qr : qr // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [TwoFASecretItemEntity].
|
||||
extension TwoFASecretItemEntityPatterns on TwoFASecretItemEntity {
|
||||
/// 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( _TwoFASecretItemEntity value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity() 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( _TwoFASecretItemEntity value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity():
|
||||
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( _TwoFASecretItemEntity value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity() 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( String secret, String qr)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity() when $default != null:
|
||||
return $default(_that.secret,_that.qr);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( String secret, String qr) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity():
|
||||
return $default(_that.secret,_that.qr);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( String secret, String qr)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TwoFASecretItemEntity() when $default != null:
|
||||
return $default(_that.secret,_that.qr);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _TwoFASecretItemEntity implements TwoFASecretItemEntity {
|
||||
const _TwoFASecretItemEntity({required this.secret, required this.qr});
|
||||
|
||||
|
||||
@override final String secret;
|
||||
@override final String qr;
|
||||
|
||||
/// Create a copy of TwoFASecretItemEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$TwoFASecretItemEntityCopyWith<_TwoFASecretItemEntity> get copyWith => __$TwoFASecretItemEntityCopyWithImpl<_TwoFASecretItemEntity>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TwoFASecretItemEntity&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.qr, qr) || other.qr == qr));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,secret,qr);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TwoFASecretItemEntity(secret: $secret, qr: $qr)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$TwoFASecretItemEntityCopyWith<$Res> implements $TwoFASecretItemEntityCopyWith<$Res> {
|
||||
factory _$TwoFASecretItemEntityCopyWith(_TwoFASecretItemEntity value, $Res Function(_TwoFASecretItemEntity) _then) = __$TwoFASecretItemEntityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String secret, String qr
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$TwoFASecretItemEntityCopyWithImpl<$Res>
|
||||
implements _$TwoFASecretItemEntityCopyWith<$Res> {
|
||||
__$TwoFASecretItemEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _TwoFASecretItemEntity _self;
|
||||
final $Res Function(_TwoFASecretItemEntity) _then;
|
||||
|
||||
/// Create a copy of TwoFASecretItemEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? secret = null,Object? qr = null,}) {
|
||||
return _then(_TwoFASecretItemEntity(
|
||||
secret: null == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String,qr: null == qr ? _self.qr : qr // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
|
||||
abstract class GenerateTwoFASignUpUseCase {
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart';
|
||||
|
||||
class GenerateTwoFASignUpUseCaseImpl implements GenerateTwoFASignUpUseCase {
|
||||
GenerateTwoFASignUpUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
@override
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token}) {
|
||||
return _repository.generateTwoFASignUp(token: token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
|
||||
abstract class SignUpUseCase {
|
||||
Future<String> signUp({required SignUpRequestEntity request});
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/sign_up_use_case.dart';
|
||||
|
||||
class SignUpUseCaseImpl implements SignUpUseCase {
|
||||
SignUpUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<String> signUp({required SignUpRequestEntity request}) {
|
||||
return _repository.signUp(request: request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
abstract class VerifyTwoFACodeSignUpUseCase {
|
||||
Future<void> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart';
|
||||
|
||||
class VerifyTwoFaCodeSignUpUseCaseImpl implements VerifyTwoFACodeSignUpUseCase {
|
||||
VerifyTwoFaCodeSignUpUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
@override
|
||||
Future<void> verifyTwoFACodeSignUp({
|
||||
required String token,
|
||||
required String code,
|
||||
}) {
|
||||
return _repository.verifyTwoFACodeSignUp(token: token, code: code);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
typedef SignUpBodyBuilder =
|
||||
Widget Function(BuildContext context, WidgetRef ref);
|
||||
|
||||
class SignUpStepConfig {
|
||||
final String supertitle;
|
||||
final String title;
|
||||
final String? subtitle;
|
||||
final SignUpBodyBuilder bodyBuilder;
|
||||
|
||||
const SignUpStepConfig({
|
||||
required this.supertitle,
|
||||
required this.title,
|
||||
this.subtitle,
|
||||
required this.bodyBuilder,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/address_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/address_view_state.dart';
|
||||
|
||||
extension AddressViewStateMapper on AddressViewState {
|
||||
bool get isValid =>
|
||||
street.trim().isNotEmpty &&
|
||||
city.trim().isNotEmpty &&
|
||||
province.trim().isNotEmpty &&
|
||||
state.trim().isNotEmpty &&
|
||||
country.trim().isNotEmpty &&
|
||||
(postCode != null);
|
||||
|
||||
AddressEntity toEntity() {
|
||||
return AddressEntity(
|
||||
street: street.trim(),
|
||||
city: city.trim(),
|
||||
province: province.trim(),
|
||||
state: state.trim(),
|
||||
country: country.trim(),
|
||||
postCode: postCode ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/address_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/mappers/address_view_state_mapper.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_state.dart';
|
||||
|
||||
extension SignUpViewStateMapper on SignUpViewState {
|
||||
bool get canSubmit =>
|
||||
documentNumber.trim().isNotEmpty &&
|
||||
documentType.trim().isNotEmpty &&
|
||||
relationship.trim().isNotEmpty &&
|
||||
firstName.trim().isNotEmpty &&
|
||||
lastName.trim().isNotEmpty &&
|
||||
email.trim().isNotEmpty &&
|
||||
phone.trim().isNotEmpty &&
|
||||
password.isNotEmpty &&
|
||||
bornAt != null &&
|
||||
userId.trim().isNotEmpty &&
|
||||
placeOfBirth.trim().isNotEmpty &&
|
||||
birthCountry.trim().isNotEmpty &&
|
||||
address.isValid;
|
||||
|
||||
SignUpRequestEntity toRequestEntity() {
|
||||
final birth = bornAt;
|
||||
if (birth == null) {
|
||||
throw Exception('bornAt is required');
|
||||
}
|
||||
|
||||
return SignUpRequestEntity(
|
||||
documentNumber: documentNumber.trim(),
|
||||
documentType: documentType.trim(),
|
||||
relationship: relationship.trim(),
|
||||
firstName: firstName.trim(),
|
||||
lastName: lastName.trim(),
|
||||
email: email.trim(),
|
||||
phone: phone.trim(),
|
||||
language: language.trim(),
|
||||
password: password,
|
||||
bornAt: birth.millisecondsSinceEpoch,
|
||||
userId: userId.trim(),
|
||||
placeOfBirth: placeOfBirth.trim(),
|
||||
birthCountry: birthCountry.trim(),
|
||||
addresses: <AddressEntity>[address.toEntity()],
|
||||
taxResidences: <AddressEntity>[address.toEntity()],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case_impl.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final generateTwoFASignUpUseCaseProvider =
|
||||
Provider.autoDispose<GenerateTwoFASignUpUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return GenerateTwoFASignUpUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/sign_up_use_case_impl.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final signUpUseCaseProvider = Provider.autoDispose<SignUpUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return SignUpUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case_impl.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final verifyTwoFACodeSignUpUseCaseProvider =
|
||||
Provider.autoDispose<VerifyTwoFACodeSignUpUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return VerifyTwoFaCodeSignUpUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -1,86 +1,88 @@
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_model.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
class AccountCreatedScreen extends ConsumerWidget {
|
||||
final bool kidAccount;
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const AccountCreatedScreen({
|
||||
super.key,
|
||||
required this.kidAccount,
|
||||
required this.navigationContract,
|
||||
});
|
||||
const AccountCreatedScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final email = "usuario@example.com";
|
||||
final fullName = "Carlos Pérez Cruz";
|
||||
final model = "SaveWatch Plus 2";
|
||||
final id = "1106652524";
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
|
||||
final String email = state.email;
|
||||
final String fullName = '${state.firstName} ${state.lastName}'.trim();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
margin: const EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(flex: 10),
|
||||
const Spacer(flex: 10),
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
size: 50,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
"Cuenta creada",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
context.translate(I18n.accountCreatedTitle),
|
||||
style: const TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
text: "Has creado la cuenta para:\n",
|
||||
text: '${context.translate(I18n.accountCreatedForLabel)}\n',
|
||||
children: [
|
||||
TextSpan(
|
||||
text: fullName,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!kidAccount) Text.rich(
|
||||
|
||||
const SizedBox(height: 16),
|
||||
Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
text: "Hemos enviado un email de verificación a:\n",
|
||||
text:
|
||||
'${context.translate(I18n.accountCreatedEmailVerificationSentLabel)}\n',
|
||||
children: [
|
||||
TextSpan(
|
||||
text: email,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (kidAccount) Text("Reloj: $model\nID del reloj: $id"),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
"Crea la cuenta de tu peque e ingresa su \nprimera paga para utilizarla con su reloj",
|
||||
context.translate(I18n.accountCreatedChildSetupHint),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
PrimaryButton(
|
||||
onPressed: () => {
|
||||
if (kidAccount){
|
||||
navigationContract.goTo(AppRoutes.dashboardHome)
|
||||
} else {
|
||||
navigationContract.pushTo(AppRoutes.deviceSignup)
|
||||
}
|
||||
},
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
onPressed: () => navigationContract.goTo(AppRoutes.login),
|
||||
text: context.translate(I18n.accountCreatedContinue),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Spacer(flex: 8),
|
||||
const Spacer(flex: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -0,0 +1,281 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:auth/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_model.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
class SecretCodeScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const SecretCodeScreen({super.key, required this.navigationContract});
|
||||
|
||||
Uint8List? _qrBytes(String? dataUri) {
|
||||
final value = (dataUri ?? '').trim();
|
||||
if (value.isEmpty) return null;
|
||||
|
||||
final idx = value.indexOf('base64,');
|
||||
final b64 = idx == -1 ? value : value.substring(idx + 7);
|
||||
|
||||
try {
|
||||
return base64Decode(b64);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool?> _openTwoFactorSignUpBottomSheet(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
) async {
|
||||
final token = ref.read(signUpViewModelProvider).token;
|
||||
if (token.trim().isEmpty) return false;
|
||||
|
||||
return showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
isDismissible: false,
|
||||
enableDrag: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context) {
|
||||
return Consumer(
|
||||
builder: (context, ref, _) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
|
||||
final otpErrorKey = ref.watch(
|
||||
signUpViewModelProvider.select((s) => s.otpError),
|
||||
);
|
||||
final isOtpLoading = ref.watch(
|
||||
signUpViewModelProvider.select((s) => s.isOtpLoading),
|
||||
);
|
||||
final otpCode = ref.watch(
|
||||
signUpViewModelProvider.select((s) => s.otpCode),
|
||||
);
|
||||
|
||||
final otpErrorText = otpErrorKey.isEmpty
|
||||
? ''
|
||||
: context.translate(otpErrorKey);
|
||||
|
||||
Future<void> onVerify() async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
final ok = await vm.verifyTwoFACodeSignUp(token: token);
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (ok) Navigator.of(context).pop(true);
|
||||
}
|
||||
|
||||
return TwoFactorBottomSheetView(
|
||||
theme: theme,
|
||||
title: context.translate(I18n.twoFactorTitle),
|
||||
subtitle: context.translate(I18n.twoFactorSubtitle),
|
||||
verifyText: context.translate(I18n.twoFactorVerify),
|
||||
closeText: context.translate(I18n.close),
|
||||
isOtpLoading: isOtpLoading,
|
||||
otpCode: otpCode,
|
||||
otpErrorText: otpErrorText,
|
||||
onChanged: vm.setOtpCode,
|
||||
onVerify: onVerify,
|
||||
onClose: () => Navigator.of(context).pop(false),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
|
||||
final secret = state.twoFASecret?.item.secret.trim() ?? '';
|
||||
final qrDataUri = state.twoFASecret?.item.qr;
|
||||
final qrBytes = _qrBytes(qrDataUri);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.fromLTRB(24, 8, 24, 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.secretCodeTitle),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
_StepBlock(
|
||||
theme: theme,
|
||||
number: '1.',
|
||||
title: context.translate(I18n.secretCodeStep1Title),
|
||||
body: context.translate(I18n.secretCodeStep1Body),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
|
||||
_StepBlock(
|
||||
theme: theme,
|
||||
number: '2.',
|
||||
title: context.translate(I18n.secretCodeStep2Title),
|
||||
body: context.translate(I18n.secretCodeStep2Body),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
Center(
|
||||
child: Container(
|
||||
width: 150,
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(width: 1, color: Colors.black),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
),
|
||||
child: qrBytes == null
|
||||
? const Center(child: Icon(Icons.qr_code_2, size: 60))
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Image.memory(qrBytes, fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 14,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
border: Border.all(width: 1, color: Colors.black),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
secret,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 1.1,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
icon: const Icon(Icons.copy, size: 18),
|
||||
onPressed: secret.isEmpty
|
||||
? null
|
||||
: () async {
|
||||
await Clipboard.setData(
|
||||
ClipboardData(text: secret),
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
context.translate(
|
||||
I18n.secretCodeKeyCopied,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 18),
|
||||
_StepBlock(
|
||||
theme: theme,
|
||||
number: '3.',
|
||||
title: context.translate(I18n.secretCodeStep3Title),
|
||||
body: context.translate(I18n.secretCodeStep3Body),
|
||||
),
|
||||
|
||||
const SizedBox(height: 26),
|
||||
PrimaryButton(
|
||||
onPressed: () async {
|
||||
final verified = await _openTwoFactorSignUpBottomSheet(
|
||||
context,
|
||||
ref,
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (verified == true) {
|
||||
vm.showAccountCreated();
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.secretCodeConfigure),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _StepBlock extends StatelessWidget {
|
||||
final ThemePort theme;
|
||||
final String number;
|
||||
final String title;
|
||||
final String body;
|
||||
|
||||
const _StepBlock({
|
||||
required this.theme,
|
||||
required this.number,
|
||||
required this.title,
|
||||
required this.body,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
height: 1.35,
|
||||
fontSize: 14,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '$number ',
|
||||
style: const TextStyle(fontWeight: FontWeight.w700),
|
||||
),
|
||||
TextSpan(
|
||||
text: '$title\n',
|
||||
style: const TextStyle(fontWeight: FontWeight.w700),
|
||||
),
|
||||
TextSpan(
|
||||
text: body,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class SignupAddressScreen extends StatelessWidget {
|
||||
const SignupAddressScreen({
|
||||
super.key,
|
||||
|
||||
required this.bornAtController,
|
||||
required this.onPickBornAt,
|
||||
required this.relationshipSelected,
|
||||
required this.onRelationshipChanged,
|
||||
required this.relationshipOptions,
|
||||
required this.relationshipHint,
|
||||
required this.relationshipLabel,
|
||||
|
||||
required this.placeOfBirthController,
|
||||
required this.birthCountryController,
|
||||
|
||||
required this.streetController,
|
||||
required this.cityController,
|
||||
required this.provinceController,
|
||||
required this.stateController,
|
||||
|
||||
required this.addressCountrySelected,
|
||||
required this.onAddressCountryChanged,
|
||||
required this.addressCountryController,
|
||||
required this.addressCountryLabel,
|
||||
|
||||
required this.postCodeController,
|
||||
|
||||
required this.birthDateLabel,
|
||||
required this.birthDateHint,
|
||||
|
||||
required this.placeOfBirthLabel,
|
||||
required this.placeOfBirthHint,
|
||||
|
||||
required this.birthCountryLabel,
|
||||
required this.birthCountryHint,
|
||||
required this.onBirthCountryChanged,
|
||||
|
||||
required this.streetLabel,
|
||||
required this.streetHint,
|
||||
|
||||
required this.cityLabel,
|
||||
required this.cityHint,
|
||||
|
||||
required this.provinceLabel,
|
||||
required this.provinceHint,
|
||||
|
||||
required this.stateLabel,
|
||||
required this.stateHint,
|
||||
|
||||
required this.postCodeLabel,
|
||||
required this.postCodeHint,
|
||||
});
|
||||
|
||||
final TextEditingController bornAtController;
|
||||
final VoidCallback onPickBornAt;
|
||||
|
||||
final String? relationshipSelected;
|
||||
final ValueChanged<String?> onRelationshipChanged;
|
||||
final List<String> relationshipOptions;
|
||||
final String relationshipHint;
|
||||
final String relationshipLabel;
|
||||
|
||||
final TextEditingController placeOfBirthController;
|
||||
final TextEditingController birthCountryController;
|
||||
|
||||
final TextEditingController streetController;
|
||||
final TextEditingController cityController;
|
||||
final TextEditingController provinceController;
|
||||
final TextEditingController stateController;
|
||||
|
||||
final String? addressCountrySelected;
|
||||
final ValueChanged<CountryCode> onAddressCountryChanged;
|
||||
final String addressCountryLabel;
|
||||
final TextEditingController addressCountryController;
|
||||
|
||||
final TextEditingController postCodeController;
|
||||
|
||||
final String birthDateLabel;
|
||||
final String birthDateHint;
|
||||
|
||||
final String placeOfBirthLabel;
|
||||
final String placeOfBirthHint;
|
||||
final ValueChanged<CountryCode> onBirthCountryChanged;
|
||||
|
||||
final String birthCountryLabel;
|
||||
final String birthCountryHint;
|
||||
|
||||
final String streetLabel;
|
||||
final String streetHint;
|
||||
|
||||
final String cityLabel;
|
||||
final String cityHint;
|
||||
|
||||
final String provinceLabel;
|
||||
final String provinceHint;
|
||||
|
||||
final String stateLabel;
|
||||
final String stateHint;
|
||||
|
||||
final String postCodeLabel;
|
||||
final String postCodeHint;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: onPickBornAt,
|
||||
child: AbsorbPointer(
|
||||
child: CustomTextField(
|
||||
label: birthDateLabel,
|
||||
hint: birthDateHint,
|
||||
controller: bornAtController,
|
||||
readOnly: true,
|
||||
keyboardType: TextInputType.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(relationshipLabel, style: const TextStyle(fontSize: 14)),
|
||||
),
|
||||
CustomDropdown(
|
||||
items: relationshipOptions.map(Text.new).toList(growable: false),
|
||||
values: relationshipOptions,
|
||||
value: relationshipSelected,
|
||||
hint: relationshipHint,
|
||||
onChanged: (v) => onRelationshipChanged(v as String?),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: placeOfBirthLabel,
|
||||
hint: placeOfBirthHint,
|
||||
controller: placeOfBirthController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(birthCountryLabel, style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
)),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
onChanged: onBirthCountryChanged,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
readOnly: true,
|
||||
controller: birthCountryController,
|
||||
hint: context.translate(I18n.birthCountryLabel),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: streetLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: streetHint,
|
||||
controller: streetController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: cityLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: cityHint,
|
||||
controller: cityController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: provinceLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: provinceHint,
|
||||
controller: provinceController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: stateLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: stateHint,
|
||||
controller: stateController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
addressCountryLabel,
|
||||
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
onChanged: onAddressCountryChanged,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
readOnly: true,
|
||||
controller: addressCountryController,
|
||||
hint: context.translate(I18n.addressCountryHint),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
CustomTextField(
|
||||
label: postCodeLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: postCodeHint,
|
||||
keyboardType: TextInputType.number,
|
||||
controller: postCodeController,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SignUpPasswordScreen extends StatelessWidget {
|
||||
final bool isPasswordVisible;
|
||||
final TextEditingController passwordTextFieldController;
|
||||
final TextEditingController repeatPasswordTextFieldController;
|
||||
const SignUpPasswordScreen({
|
||||
super.key,
|
||||
required this.isPasswordVisible,
|
||||
required this.passwordTextFieldController,
|
||||
required this.repeatPasswordTextFieldController,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: isPasswordVisible,
|
||||
label: "Contraseña",
|
||||
hint: "********",
|
||||
controller: passwordTextFieldController,
|
||||
),
|
||||
CustomTextField(
|
||||
showPassword: isPasswordVisible,
|
||||
label: "Repetir contraseña",
|
||||
hint: "*******",
|
||||
controller: repeatPasswordTextFieldController,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class SignupPersonalScreen extends StatelessWidget {
|
||||
final TextEditingController firstNameTextFieldController;
|
||||
final TextEditingController lastNameTextFieldController;
|
||||
final TextEditingController documentNumberTextFieldController;
|
||||
final TextEditingController phoneTextFieldController;
|
||||
final TextEditingController emailTextFieldController;
|
||||
|
||||
final String? documentTypeSelected;
|
||||
final ValueChanged<String?> onDocumentTypeChanged;
|
||||
|
||||
final String firstNameLabel;
|
||||
final String firstNameHint;
|
||||
|
||||
final String lastNameLabel;
|
||||
final String lastNameHint;
|
||||
|
||||
final List<String> documentTypeOptions;
|
||||
final String documentTypeHint;
|
||||
|
||||
final String documentNumberLabel;
|
||||
final String documentNumberHint;
|
||||
|
||||
final String phoneLabel;
|
||||
final String phoneHint;
|
||||
final ValueChanged<CountryCode> onDialCodeChanged;
|
||||
|
||||
final String emailLabel;
|
||||
final String emailHint;
|
||||
|
||||
final bool acceptTerms;
|
||||
final ValueChanged<bool?>? onAcceptTermsPressed;
|
||||
final String termsText;
|
||||
final ThemePort theme;
|
||||
|
||||
const SignupPersonalScreen({
|
||||
super.key,
|
||||
required this.firstNameTextFieldController,
|
||||
required this.lastNameTextFieldController,
|
||||
required this.documentNumberTextFieldController,
|
||||
required this.phoneTextFieldController,
|
||||
required this.emailTextFieldController,
|
||||
required this.documentTypeSelected,
|
||||
required this.onDocumentTypeChanged,
|
||||
required this.firstNameLabel,
|
||||
required this.firstNameHint,
|
||||
required this.lastNameLabel,
|
||||
required this.lastNameHint,
|
||||
required this.documentTypeOptions,
|
||||
required this.documentTypeHint,
|
||||
required this.documentNumberLabel,
|
||||
required this.documentNumberHint,
|
||||
required this.phoneLabel,
|
||||
required this.phoneHint,
|
||||
required this.onDialCodeChanged,
|
||||
required this.emailLabel,
|
||||
required this.emailHint,
|
||||
required this.acceptTerms,
|
||||
required this.onAcceptTermsPressed,
|
||||
required this.termsText,
|
||||
required this.theme,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
CustomTextField(
|
||||
label: firstNameLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: firstNameHint,
|
||||
controller: firstNameTextFieldController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CustomTextField(
|
||||
label: lastNameLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: lastNameHint,
|
||||
controller: lastNameTextFieldController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomDropdown(
|
||||
items: documentTypeOptions
|
||||
.map(Text.new)
|
||||
.toList(growable: false),
|
||||
values: documentTypeOptions,
|
||||
value: documentTypeSelected,
|
||||
hint: documentTypeHint,
|
||||
onChanged: (v) => onDocumentTypeChanged(v as String?),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
label: documentNumberLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: documentNumberHint,
|
||||
controller: documentNumberTextFieldController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(phoneLabel, style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12)
|
||||
)),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
onChanged: onDialCodeChanged,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
controller: phoneTextFieldController,
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CustomTextField(
|
||||
label: emailLabel,
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 13, xl: 12),
|
||||
hint: emailHint,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
controller: emailTextFieldController,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CheckboxListTile(
|
||||
value: acceptTerms,
|
||||
onChanged: onAcceptTermsPressed,
|
||||
title: Text(
|
||||
termsText,
|
||||
style: TextStyle(fontSize: 16, letterSpacing: 0),
|
||||
),
|
||||
checkboxScaleFactor: 1.5,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'package:auth/src/features/sign_up/presentation/sign_up_steps.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_model.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/account_created_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/secret_code_screen.dart';
|
||||
import 'package:auth/src/widgets/layouts/sign_up_layout.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class SignupScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const SignupScreen({super.key, required this.navigationContract});
|
||||
|
||||
Future<void> _onNextPressed(BuildContext context, WidgetRef ref) async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.read(signUpViewModelProvider);
|
||||
|
||||
final steps = signUpSteps(context);
|
||||
final isLastStep = state.currentIndex >= steps.length - 1;
|
||||
|
||||
if (!isLastStep) {
|
||||
vm.next();
|
||||
return;
|
||||
}
|
||||
|
||||
final ok = await vm.signUp();
|
||||
if (!context.mounted) return;
|
||||
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
|
||||
final steps = signUpSteps(context);
|
||||
final index = state.currentIndex.clamp(0, steps.length - 1);
|
||||
final step = steps[index];
|
||||
|
||||
if (state.showSecretCode) {
|
||||
return SecretCodeScreen(navigationContract: navigationContract);
|
||||
}
|
||||
|
||||
if (state.showAccountCreated) {
|
||||
return AccountCreatedScreen(navigationContract: navigationContract);
|
||||
}
|
||||
return SignUpLayout(
|
||||
theme: theme,
|
||||
supertitle: step.supertitle,
|
||||
title: step.title,
|
||||
subtitle: step.subtitle ?? '',
|
||||
currentStep: index + 1,
|
||||
numSteps: steps.length,
|
||||
body: step.bodyBuilder(context, ref),
|
||||
errorMessage: state.errorMessage,
|
||||
onBackPressed: state.currentIndex == 0
|
||||
? navigationContract.goBack
|
||||
: vm.back,
|
||||
onNextPressed: () => _onNextPressed(context, ref),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
import 'package:auth/src/features/sign_up/models/sign_up_step_config.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_model.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/sign_up_address_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/sign_up_password_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart';
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
const Map<String, String> documentType = <String, String>{
|
||||
'DNI': I18n.documentTypeDni,
|
||||
'NIE': I18n.documentTypeNie,
|
||||
'PASSPORT': I18n.documentTypePassport,
|
||||
};
|
||||
const Map<String, String> relationship = <String, String>{
|
||||
'FATHER': I18n.relationshipFather,
|
||||
'MOTHER': I18n.relationshipMother,
|
||||
'OTHER': I18n.relationshipTutor,
|
||||
};
|
||||
|
||||
List<SignUpStepConfig> signUpSteps(BuildContext context) => [
|
||||
SignUpStepConfig(
|
||||
supertitle: context.translate(I18n.stepUserContactSupertitle),
|
||||
title: context.translate(I18n.stepUserContactTitle),
|
||||
subtitle: context.translate(I18n.stepUserContactSubtitle),
|
||||
bodyBuilder: (context, ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
final documentLabel = <String, String>{
|
||||
for (final e in documentType.entries) e.key: context.translate(e.value),
|
||||
};
|
||||
|
||||
final documentKeys = <String, String>{
|
||||
for (final e in documentLabel.entries) e.value: e.key,
|
||||
};
|
||||
|
||||
final String? documentTypeSelected = state.documentType.trim().isEmpty
|
||||
? null
|
||||
: documentLabel[state.documentType];
|
||||
return SignupPersonalScreen(
|
||||
firstNameTextFieldController: vm.firstNameController,
|
||||
lastNameTextFieldController: vm.lastNameController,
|
||||
documentNumberTextFieldController: vm.documentNumberController,
|
||||
phoneTextFieldController: vm.phoneController,
|
||||
emailTextFieldController: vm.emailController,
|
||||
|
||||
documentTypeSelected: documentTypeSelected,
|
||||
|
||||
onDocumentTypeChanged: (label) {
|
||||
final documentKey = documentKeys[label ?? ''] ?? '';
|
||||
vm.setDocumentType(documentKey);
|
||||
},
|
||||
|
||||
acceptTerms: state.acceptTerms,
|
||||
onAcceptTermsPressed: (v) => vm.setAcceptTerms(v ?? false),
|
||||
termsText: context.translate(I18n.termsText),
|
||||
theme: theme,
|
||||
|
||||
firstNameLabel: context.translate(I18n.firstNameLabel),
|
||||
firstNameHint: context.translate(I18n.firstNameHint),
|
||||
lastNameLabel: context.translate(I18n.lastNameLabel),
|
||||
lastNameHint: context.translate(I18n.lastNameHint),
|
||||
|
||||
documentTypeOptions: documentLabel.values.toList(),
|
||||
documentTypeHint: context.translate(I18n.documentTypeHint),
|
||||
|
||||
documentNumberLabel: '',
|
||||
documentNumberHint: context.translate(I18n.documentNumberHint),
|
||||
phoneLabel: context.translate(I18n.phoneLabel),
|
||||
phoneHint: context.translate(I18n.phoneHint),
|
||||
emailLabel: context.translate(I18n.emailLabel),
|
||||
emailHint: context.translate(I18n.emailHint),
|
||||
|
||||
onDialCodeChanged: (CountryCode value) {
|
||||
vm.updateDialCode(value.dialCode ?? state.dialCode);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
SignUpStepConfig(
|
||||
supertitle: context.translate(I18n.stepPersonalDataSupertitle),
|
||||
title: context.translate(I18n.stepPersonalDataTitle),
|
||||
subtitle: context.translate(I18n.stepPersonalDataSubtitle),
|
||||
bodyBuilder: (context, ref) {
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
|
||||
final relationshipLabel = <String, String>{
|
||||
for (final e in relationship.entries) e.key: context.translate(e.value),
|
||||
};
|
||||
final relationshipKeys = <String, String>{
|
||||
for (final e in relationshipLabel.entries) e.value: e.key,
|
||||
};
|
||||
final String? relationshipSelected = state.relationship.trim().isEmpty
|
||||
? null
|
||||
: relationshipLabel[state.relationship];
|
||||
|
||||
return SignupAddressScreen(
|
||||
bornAtController: vm.bornAtController,
|
||||
onPickBornAt: () => vm.pickBornAt(context),
|
||||
|
||||
relationshipSelected: relationshipSelected,
|
||||
onRelationshipChanged: (label) {
|
||||
final key = relationshipKeys[label ?? ''] ?? '';
|
||||
vm.setRelationship(key);
|
||||
},
|
||||
relationshipOptions: relationshipLabel.values.toList(),
|
||||
relationshipHint: context.translate(I18n.relationshipHint),
|
||||
relationshipLabel: context.translate(I18n.relationshipLabel),
|
||||
|
||||
placeOfBirthController: vm.placeOfBirthController,
|
||||
birthCountryController: vm.birthCountryController,
|
||||
|
||||
streetController: vm.addressStreetController,
|
||||
cityController: vm.addressCityController,
|
||||
provinceController: vm.addressProvinceController,
|
||||
stateController: vm.addressStateController,
|
||||
|
||||
addressCountrySelected: state.address.country.trim().isEmpty
|
||||
? null
|
||||
: state.address.country,
|
||||
onAddressCountryChanged: (CountryCode value) {
|
||||
vm.setAddressCountry(name: value.name ?? '');
|
||||
},
|
||||
addressCountryLabel: context.translate(I18n.addressCountryLabel),
|
||||
addressCountryController: vm.addressCountryController,
|
||||
|
||||
postCodeController: vm.addressPostCodeController,
|
||||
|
||||
birthDateLabel: context.translate(I18n.birthDateLabel),
|
||||
birthDateHint: context.translate(I18n.birthDateHint),
|
||||
|
||||
placeOfBirthLabel: context.translate(I18n.placeOfBirthLabel),
|
||||
placeOfBirthHint: context.translate(I18n.placeOfBirthHint),
|
||||
|
||||
birthCountryLabel: context.translate(I18n.birthCountryLabel),
|
||||
birthCountryHint: context.translate(I18n.birthCountryHint),
|
||||
onBirthCountryChanged: (CountryCode value) {
|
||||
vm.setBirthCountryFromPicker(
|
||||
name: value.name ?? '',
|
||||
code: value.code ?? '',
|
||||
);
|
||||
},
|
||||
|
||||
streetLabel: context.translate(I18n.streetLabel),
|
||||
streetHint: context.translate(I18n.streetHint),
|
||||
|
||||
cityLabel: context.translate(I18n.cityLabel),
|
||||
cityHint: context.translate(I18n.cityHint),
|
||||
|
||||
provinceLabel: context.translate(I18n.provinceLabel),
|
||||
provinceHint: context.translate(I18n.provinceHint),
|
||||
|
||||
stateLabel: context.translate(I18n.stateLabel),
|
||||
stateHint: context.translate(I18n.stateHint),
|
||||
|
||||
postCodeLabel: context.translate(I18n.postCodeLabel),
|
||||
postCodeHint: context.translate(I18n.postCodeHint),
|
||||
);
|
||||
},
|
||||
),
|
||||
SignUpStepConfig(
|
||||
supertitle: context.translate(I18n.stepAddressSupertitle),
|
||||
title: context.translate(I18n.stepAddressTitle),
|
||||
subtitle: context.translate(I18n.passwordRulesSubtitle),
|
||||
bodyBuilder: (context, ref) {
|
||||
final vm = ref.read(signUpViewModelProvider.notifier);
|
||||
final state = ref.watch(signUpViewModelProvider);
|
||||
|
||||
return SignUpPasswordScreen(
|
||||
isPasswordVisible: state.isShowPassword,
|
||||
passwordTextFieldController: vm.passwordController,
|
||||
repeatPasswordTextFieldController: vm.repeatPasswordController,
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'address_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class AddressViewState with _$AddressViewState {
|
||||
const factory AddressViewState({
|
||||
@Default('') String street,
|
||||
@Default('') String city,
|
||||
@Default('') String province,
|
||||
@Default('') String state,
|
||||
@Default('España') String country,
|
||||
int? postCode,
|
||||
}) = _AddressViewState;
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
// 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 'address_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$AddressViewState {
|
||||
|
||||
String get street; String get city; String get province; String get state; String get country; int? get postCode;
|
||||
/// Create a copy of AddressViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AddressViewStateCopyWith<AddressViewState> get copyWith => _$AddressViewStateCopyWithImpl<AddressViewState>(this as AddressViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AddressViewState&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressViewState(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AddressViewStateCopyWith<$Res> {
|
||||
factory $AddressViewStateCopyWith(AddressViewState value, $Res Function(AddressViewState) _then) = _$AddressViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int? postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AddressViewStateCopyWithImpl<$Res>
|
||||
implements $AddressViewStateCopyWith<$Res> {
|
||||
_$AddressViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AddressViewState _self;
|
||||
final $Res Function(AddressViewState) _then;
|
||||
|
||||
/// Create a copy of AddressViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: freezed == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AddressViewState].
|
||||
extension AddressViewStatePatterns on AddressViewState {
|
||||
/// 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( _AddressViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState() 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( _AddressViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState():
|
||||
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( _AddressViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState() 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( String street, String city, String province, String state, String country, int? postCode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int? postCode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState():
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);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( String street, String city, String province, String state, String country, int? postCode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AddressViewState() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _AddressViewState implements AddressViewState {
|
||||
const _AddressViewState({this.street = '', this.city = '', this.province = '', this.state = '', this.country = 'España', this.postCode});
|
||||
|
||||
|
||||
@override@JsonKey() final String street;
|
||||
@override@JsonKey() final String city;
|
||||
@override@JsonKey() final String province;
|
||||
@override@JsonKey() final String state;
|
||||
@override@JsonKey() final String country;
|
||||
@override final int? postCode;
|
||||
|
||||
/// Create a copy of AddressViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AddressViewStateCopyWith<_AddressViewState> get copyWith => __$AddressViewStateCopyWithImpl<_AddressViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AddressViewState&&(identical(other.street, street) || other.street == street)&&(identical(other.city, city) || other.city == city)&&(identical(other.province, province) || other.province == province)&&(identical(other.state, state) || other.state == state)&&(identical(other.country, country) || other.country == country)&&(identical(other.postCode, postCode) || other.postCode == postCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,street,city,province,state,country,postCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AddressViewState(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AddressViewStateCopyWith<$Res> implements $AddressViewStateCopyWith<$Res> {
|
||||
factory _$AddressViewStateCopyWith(_AddressViewState value, $Res Function(_AddressViewState) _then) = __$AddressViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country, int? postCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AddressViewStateCopyWithImpl<$Res>
|
||||
implements _$AddressViewStateCopyWith<$Res> {
|
||||
__$AddressViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AddressViewState _self;
|
||||
final $Res Function(_AddressViewState) _then;
|
||||
|
||||
/// Create a copy of AddressViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,Object? postCode = freezed,}) {
|
||||
return _then(_AddressViewState(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,postCode: freezed == postCode ? _self.postCode : postCode // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,770 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:auth/src/features/sign_up/domain/entities/address_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/providers/generate_two_fa_sign_up_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/providers/sign_up_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/providers/verify_two_fa_code_sign_up_provider.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/address_view_state.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/state/sign_up_view_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
final signUpViewModelProvider =
|
||||
NotifierProvider.autoDispose<SignUpViewModel, SignUpViewState>(
|
||||
SignUpViewModel.new,
|
||||
);
|
||||
|
||||
class SignUpViewModel extends Notifier<SignUpViewState> {
|
||||
late final SignUpUseCase _signUpUseCase;
|
||||
late final GenerateTwoFASignUpUseCase _generateTwoFASignUpUseCase;
|
||||
late final VerifyTwoFACodeSignUpUseCase _verifyTwoFACodeSignUpUseCase;
|
||||
|
||||
late final TextEditingController firstNameController;
|
||||
late final TextEditingController lastNameController;
|
||||
late final TextEditingController documentNumberController;
|
||||
late final TextEditingController documentTypeController;
|
||||
late final TextEditingController phoneController;
|
||||
late final TextEditingController emailController;
|
||||
|
||||
late final TextEditingController relationshipController;
|
||||
late final TextEditingController bornAtController;
|
||||
late final TextEditingController placeOfBirthController;
|
||||
late final TextEditingController birthCountryController;
|
||||
|
||||
late final TextEditingController addressStreetController;
|
||||
late final TextEditingController addressCityController;
|
||||
late final TextEditingController addressProvinceController;
|
||||
late final TextEditingController addressStateController;
|
||||
late final TextEditingController addressCountryController;
|
||||
late final TextEditingController addressPostCodeController;
|
||||
|
||||
late final TextEditingController passwordController;
|
||||
late final TextEditingController repeatPasswordController;
|
||||
|
||||
static const int _lastIndex = 2;
|
||||
|
||||
static final RegExp _emailRegex = RegExp(
|
||||
r'^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
static final RegExp _phoneRegex = RegExp(r'^\+?\d{6,15}$');
|
||||
|
||||
@override
|
||||
SignUpViewState build() {
|
||||
_signUpUseCase = ref.read(signUpUseCaseProvider);
|
||||
_generateTwoFASignUpUseCase = ref.read(generateTwoFASignUpUseCaseProvider);
|
||||
_verifyTwoFACodeSignUpUseCase = ref.read(
|
||||
verifyTwoFACodeSignUpUseCaseProvider,
|
||||
);
|
||||
final initial = SignUpViewState(userId: const Uuid().v4());
|
||||
_initControllers(initial);
|
||||
_addListeners();
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return initial;
|
||||
}
|
||||
|
||||
void _initControllers(SignUpViewState s) {
|
||||
firstNameController = TextEditingController(text: s.firstName);
|
||||
lastNameController = TextEditingController(text: s.lastName);
|
||||
documentNumberController = TextEditingController(text: s.documentNumber);
|
||||
documentTypeController = TextEditingController(text: s.documentType);
|
||||
phoneController = TextEditingController(text: s.phone);
|
||||
emailController = TextEditingController(text: s.email);
|
||||
|
||||
relationshipController = TextEditingController(text: s.relationship);
|
||||
|
||||
bornAtController = TextEditingController(
|
||||
text: s.bornAt == null ? '' : _formatDate(s.bornAt!),
|
||||
);
|
||||
|
||||
placeOfBirthController = TextEditingController(text: s.placeOfBirth);
|
||||
birthCountryController = TextEditingController(text: s.birthCountry);
|
||||
|
||||
addressStreetController = TextEditingController(text: s.address.street);
|
||||
addressCityController = TextEditingController(text: s.address.city);
|
||||
addressProvinceController = TextEditingController(text: s.address.province);
|
||||
addressStateController = TextEditingController(text: s.address.state);
|
||||
addressCountryController = TextEditingController(text: s.address.country);
|
||||
addressPostCodeController = TextEditingController(
|
||||
text: s.address.postCode?.toString() ?? '',
|
||||
);
|
||||
|
||||
passwordController = TextEditingController(text: s.password);
|
||||
repeatPasswordController = TextEditingController(text: s.repeatPassword);
|
||||
}
|
||||
|
||||
void _addListeners() {
|
||||
firstNameController.addListener(_onFirstNameChanged);
|
||||
lastNameController.addListener(_onLastNameChanged);
|
||||
documentNumberController.addListener(_onDocumentNumberChanged);
|
||||
documentTypeController.addListener(_onDocumentTypeChanged);
|
||||
phoneController.addListener(_onPhoneChanged);
|
||||
emailController.addListener(_onEmailChanged);
|
||||
|
||||
relationshipController.addListener(_onRelationshipChanged);
|
||||
bornAtController.addListener(_onBornAtTextChanged);
|
||||
placeOfBirthController.addListener(_onPlaceOfBirthChanged);
|
||||
birthCountryController.addListener(_onBirthCountryChanged);
|
||||
|
||||
addressStreetController.addListener(_onAddressStreetChanged);
|
||||
addressCityController.addListener(_onAddressCityChanged);
|
||||
addressProvinceController.addListener(_onAddressProvinceChanged);
|
||||
addressStateController.addListener(_onAddressStateChanged);
|
||||
addressCountryController.addListener(_onAddressCountryChanged);
|
||||
addressPostCodeController.addListener(_onAddressPostCodeChanged);
|
||||
|
||||
passwordController.addListener(_onPasswordChanged);
|
||||
repeatPasswordController.addListener(_onRepeatPasswordChanged);
|
||||
}
|
||||
|
||||
void next() {
|
||||
if (state.isLoading) return;
|
||||
|
||||
final ok = switch (state.currentIndex) {
|
||||
0 => _validateStep0(),
|
||||
1 => _validateStep1(),
|
||||
2 => _validateStep2(),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if (!ok) return;
|
||||
|
||||
if (state.currentIndex >= _lastIndex) {
|
||||
unawaited(signUp());
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
currentIndex: (state.currentIndex + 1).clamp(0, _lastIndex),
|
||||
);
|
||||
}
|
||||
|
||||
void back() {
|
||||
if (state.isLoading) return;
|
||||
if (state.currentIndex <= 0) return;
|
||||
|
||||
state = state.copyWith(
|
||||
currentIndex: (state.currentIndex - 1).clamp(0, _lastIndex),
|
||||
);
|
||||
}
|
||||
|
||||
void updateDialCode(String dialCode) {
|
||||
state = state.copyWith(dialCode: dialCode);
|
||||
}
|
||||
|
||||
void setBirthCountryFromPicker({required String name, required String code}) {
|
||||
birthCountryController.text = name;
|
||||
state = state.copyWith(birthCountry: name, birthCountryCode: code);
|
||||
}
|
||||
|
||||
Future<void> pickBornAt(BuildContext context) async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
final now = DateTime.now();
|
||||
final initial = state.bornAt ?? DateTime(now.year - 18, now.month, now.day);
|
||||
|
||||
final safeInitial = initial.isAfter(now) ? now : initial;
|
||||
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: safeInitial,
|
||||
firstDate: DateTime(1900, 1, 1),
|
||||
lastDate: now,
|
||||
);
|
||||
|
||||
if (!ref.mounted) return;
|
||||
if (picked == null) return;
|
||||
|
||||
setBornAt(picked);
|
||||
}
|
||||
|
||||
void setDocumentType(String? value) {
|
||||
final v = value ?? '';
|
||||
if (documentTypeController.text == v) return;
|
||||
documentTypeController.text = v;
|
||||
}
|
||||
|
||||
void setRelationship(String? value) {
|
||||
final v = value ?? '';
|
||||
if (relationshipController.text == v) return;
|
||||
relationshipController.text = v;
|
||||
}
|
||||
|
||||
void setAddressCountry({required String name}) {
|
||||
addressCountryController.text = name;
|
||||
state = state.copyWith(address: state.address.copyWith(country: name));
|
||||
}
|
||||
|
||||
void setAcceptTerms(bool value) {
|
||||
if (value == state.acceptTerms) return;
|
||||
state = state.copyWith(acceptTerms: value, errorMessage: '');
|
||||
}
|
||||
|
||||
void toggleShowPassword() {
|
||||
state = state.copyWith(isShowPassword: !state.isShowPassword);
|
||||
}
|
||||
|
||||
void _onFirstNameChanged() {
|
||||
final text = firstNameController.text;
|
||||
if (text == state.firstName) return;
|
||||
state = state.copyWith(firstName: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onLastNameChanged() {
|
||||
final text = lastNameController.text;
|
||||
if (text == state.lastName) return;
|
||||
state = state.copyWith(lastName: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onDocumentNumberChanged() {
|
||||
final text = documentNumberController.text;
|
||||
if (text == state.documentNumber) return;
|
||||
state = state.copyWith(documentNumber: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onDocumentTypeChanged() {
|
||||
final text = documentTypeController.text;
|
||||
if (text == state.documentType) return;
|
||||
state = state.copyWith(documentType: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onRelationshipChanged() {
|
||||
final text = relationshipController.text;
|
||||
if (text == state.relationship) return;
|
||||
state = state.copyWith(relationship: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onPhoneChanged() {
|
||||
final text = phoneController.text;
|
||||
if (text == state.phone) return;
|
||||
|
||||
state = state.copyWith(phone: text);
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(phoneError: _phoneErrorFor(text));
|
||||
}
|
||||
}
|
||||
|
||||
void _onEmailChanged() {
|
||||
final text = emailController.text;
|
||||
if (text == state.email) return;
|
||||
|
||||
state = state.copyWith(email: text, errorMessage: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(emailError: _emailErrorFor(text));
|
||||
}
|
||||
}
|
||||
|
||||
void _onPasswordChanged() {
|
||||
final text = passwordController.text;
|
||||
if (text == state.password) return;
|
||||
|
||||
state = state.copyWith(password: text, errorMessage: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(
|
||||
passwordError: _passwordErrorFor(
|
||||
password: state.password,
|
||||
repeatPassword: state.repeatPassword,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _onRepeatPasswordChanged() {
|
||||
final text = repeatPasswordController.text;
|
||||
if (text == state.repeatPassword) return;
|
||||
|
||||
state = state.copyWith(repeatPassword: text, errorMessage: '');
|
||||
|
||||
if (state.showErrors) {
|
||||
state = state.copyWith(
|
||||
passwordError: _passwordErrorFor(
|
||||
password: state.password,
|
||||
repeatPassword: state.repeatPassword,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _onBornAtTextChanged() {
|
||||
final text = bornAtController.text;
|
||||
final parsed = _tryParseDate(text);
|
||||
|
||||
if (text.trim().isEmpty) {
|
||||
if (state.bornAt != null) {
|
||||
state = state.copyWith(bornAt: null, errorMessage: '');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed != null && parsed != state.bornAt) {
|
||||
state = state.copyWith(bornAt: parsed, errorMessage: '');
|
||||
}
|
||||
}
|
||||
|
||||
void _onPlaceOfBirthChanged() {
|
||||
final text = placeOfBirthController.text;
|
||||
if (text == state.placeOfBirth) return;
|
||||
state = state.copyWith(placeOfBirth: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onBirthCountryChanged() {
|
||||
final text = birthCountryController.text;
|
||||
if (text == state.birthCountry) return;
|
||||
state = state.copyWith(birthCountry: text, errorMessage: '');
|
||||
}
|
||||
|
||||
void _onAddressStreetChanged() {
|
||||
final text = addressStreetController.text;
|
||||
if (text == state.address.street) return;
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(street: text),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddressCityChanged() {
|
||||
final text = addressCityController.text;
|
||||
if (text == state.address.city) return;
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(city: text),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddressProvinceChanged() {
|
||||
final text = addressProvinceController.text;
|
||||
if (text == state.address.province) return;
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(province: text),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddressStateChanged() {
|
||||
final text = addressStateController.text;
|
||||
if (text == state.address.state) return;
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(state: text),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddressCountryChanged() {
|
||||
final text = addressCountryController.text;
|
||||
if (text == state.address.country) return;
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(country: text),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _onAddressPostCodeChanged() {
|
||||
final text = addressPostCodeController.text.trim();
|
||||
final parsed = int.tryParse(text);
|
||||
|
||||
if (text.isEmpty) {
|
||||
if (state.address.postCode != null) {
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(postCode: null),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed != null && parsed != state.address.postCode) {
|
||||
state = state.copyWith(
|
||||
address: state.address.copyWith(postCode: parsed),
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void setOtpCode(String code) {
|
||||
state = state.copyWith(otpCode: code, otpError: '');
|
||||
}
|
||||
|
||||
bool _validateStep0() {
|
||||
final emailError = _emailErrorFor(state.email);
|
||||
final phoneError = _phoneErrorFor(state.phone);
|
||||
state = state.copyWith(
|
||||
showErrors: true,
|
||||
emailError: emailError,
|
||||
phoneError: phoneError,
|
||||
errorMessage: '',
|
||||
);
|
||||
if (state.firstName.trim().isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'El nombre es obligatorio');
|
||||
return false;
|
||||
}
|
||||
if (state.lastName.trim().isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'El apellido es obligatorio');
|
||||
return false;
|
||||
}
|
||||
if (state.documentType.trim().isEmpty) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'El tipo de documento es obligatorio',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (state.documentNumber.trim().isEmpty) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'El número de documento es obligatorio',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (phoneError.isNotEmpty) {
|
||||
state = state.copyWith(errorMessage: phoneError);
|
||||
return false;
|
||||
}
|
||||
if (emailError.isNotEmpty) {
|
||||
state = state.copyWith(errorMessage: emailError);
|
||||
return false;
|
||||
}
|
||||
if (!state.acceptTerms) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'Debes aceptar los términos y condiciones',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _validateStep1() {
|
||||
if (!state.showErrors) {
|
||||
state = state.copyWith(showErrors: true, errorMessage: '');
|
||||
} else {
|
||||
state = state.copyWith(errorMessage: '');
|
||||
}
|
||||
if (state.bornAt == null) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'Selecciona una fecha de nacimiento válida (DD/MM/AAAA)',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (state.relationship.trim().isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'La relación es obligatoria');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.placeOfBirth.trim().isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'Falta el lugar de nacimiento');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.birthCountry.trim().isEmpty) {
|
||||
state = state.copyWith(errorMessage: 'Falta el país de nacimiento');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_isAddressValid(state.address)) {
|
||||
state = state.copyWith(errorMessage: 'Completa la dirección');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _validateStep2() {
|
||||
final passwordError = _passwordErrorFor(
|
||||
password: state.password,
|
||||
repeatPassword: state.repeatPassword,
|
||||
);
|
||||
|
||||
state = state.copyWith(
|
||||
showErrors: true,
|
||||
passwordError: passwordError,
|
||||
errorMessage: '',
|
||||
);
|
||||
|
||||
if (passwordError.isNotEmpty) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _validateForm() {
|
||||
return _validateStep0() && _validateStep1() && _validateStep2();
|
||||
}
|
||||
|
||||
bool _isValidEmail(String email) => _emailRegex.hasMatch(email);
|
||||
|
||||
String _emailErrorFor(String value) {
|
||||
final email = value.trim();
|
||||
if (email.isEmpty) return I18n.errorEmailRequired;
|
||||
if (!_isValidEmail(email)) return I18n.errorEmailInvalid;
|
||||
return '';
|
||||
}
|
||||
|
||||
String _passwordErrorFor({
|
||||
required String password,
|
||||
required String repeatPassword,
|
||||
}) {
|
||||
final p = password.trim();
|
||||
final rp = repeatPassword.trim();
|
||||
|
||||
if (p.isEmpty) return I18n.errorPasswordRequired;
|
||||
if (p.length < 6) return I18n.errorPasswordMinLength;
|
||||
|
||||
if (rp.isEmpty) return 'Repite la contraseña';
|
||||
if (p != rp) return 'Las contraseñas no coinciden';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
String _phoneErrorFor(String value) {
|
||||
final phone = value.trim();
|
||||
if (phone.isEmpty) return 'El teléfono es obligatorio';
|
||||
if (!_phoneRegex.hasMatch(phone)) {
|
||||
return 'El teléfono no tiene un formato válido';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
bool _isAddressValid(AddressViewState a) {
|
||||
return a.street.trim().isNotEmpty &&
|
||||
a.city.trim().isNotEmpty &&
|
||||
a.province.trim().isNotEmpty &&
|
||||
a.state.trim().isNotEmpty &&
|
||||
a.country.trim().isNotEmpty &&
|
||||
a.postCode != null;
|
||||
}
|
||||
|
||||
AddressEntity _toAddressEntity(AddressViewState a) {
|
||||
return AddressEntity(
|
||||
street: a.street.trim(),
|
||||
city: a.city.trim(),
|
||||
province: a.province.trim(),
|
||||
state: a.state.trim(),
|
||||
country: a.country.trim(),
|
||||
postCode: a.postCode ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
SignUpRequestEntity _toRequest() {
|
||||
final bornAt = state.bornAt;
|
||||
if (bornAt == null) throw Exception('bornAt is required');
|
||||
|
||||
return SignUpRequestEntity(
|
||||
documentType: state.documentType.trim(),
|
||||
documentNumber: state.documentNumber.trim(),
|
||||
relationship: state.relationship.trim(),
|
||||
firstName: state.firstName.trim(),
|
||||
lastName: state.lastName.trim(),
|
||||
email: state.email.trim(),
|
||||
phone: state.dialCode.trim() + state.phone.trim(),
|
||||
language: state.language.trim().isEmpty ? 'es' : state.language.trim(),
|
||||
password: state.password,
|
||||
bornAt: bornAt.millisecondsSinceEpoch,
|
||||
userId: state.userId.trim(),
|
||||
placeOfBirth: state.placeOfBirth.trim(),
|
||||
birthCountry: state.birthCountryCode.trim(),
|
||||
// birthCountry: 'spain',
|
||||
addresses: <AddressEntity>[_toAddressEntity(state.address)],
|
||||
taxResidences: <AddressEntity>[_toAddressEntity(state.address)],
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> signUp() async {
|
||||
if (state.isLoading) return false;
|
||||
if (!_validateForm()) return false;
|
||||
|
||||
_startLoadingForSignUp();
|
||||
|
||||
try {
|
||||
final request = _toRequest();
|
||||
|
||||
final token = await _signUp(request);
|
||||
if (!ref.mounted) return false;
|
||||
|
||||
final secretEntity = await _generateTwoFA(token);
|
||||
if (!ref.mounted) return false;
|
||||
|
||||
final validationError = _twoFAResponseError(secretEntity);
|
||||
if (validationError != null) {
|
||||
_finishWithError(token: token, message: validationError);
|
||||
return false;
|
||||
}
|
||||
state = state.copyWith(showSecretCode: true);
|
||||
_finishWithSuccess(token: token, twoFASecret: secretEntity);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
_finishWithError(message: e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void _startLoadingForSignUp() {
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
twoFASecret: null,
|
||||
showSecretCode: false,
|
||||
showAccountCreated: false,
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _signUp(SignUpRequestEntity request) async {
|
||||
return _signUpUseCase.signUp(request: request);
|
||||
}
|
||||
|
||||
Future<TwoFASecretEntity> _generateTwoFA(String token) async {
|
||||
return _generateTwoFASignUpUseCase.generateTwoFASignUp(token: token);
|
||||
}
|
||||
|
||||
Future<bool> verifyTwoFACodeSignUp({required String token}) async {
|
||||
if (state.isOtpLoading) return false;
|
||||
|
||||
final code = state.otpCode.trim();
|
||||
if (code.length != 6) {
|
||||
state = state.copyWith(otpError: 'error otp');
|
||||
return false;
|
||||
}
|
||||
|
||||
state = state.copyWith(isOtpLoading: true, otpError: '');
|
||||
|
||||
try {
|
||||
await _verifyTwoFACodeSignUpUseCase.verifyTwoFACodeSignUp(
|
||||
token: token,
|
||||
code: code,
|
||||
);
|
||||
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(isOtpLoading: false);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(isOtpLoading: false, otpError: e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String? _twoFAResponseError(TwoFASecretEntity entity) {
|
||||
if (!entity.isCreated) {
|
||||
return 'No se pudo generar el 2FA (isCreated=false)';
|
||||
}
|
||||
|
||||
final secret = entity.item.secret.trim();
|
||||
final qr = entity.item.qr.trim();
|
||||
|
||||
if (secret.isEmpty || qr.isEmpty) {
|
||||
return 'Respuesta inválida del 2FA (secret/qr vacío)';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void _finishWithSuccess({
|
||||
required String token,
|
||||
required TwoFASecretEntity twoFASecret,
|
||||
}) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
token: token,
|
||||
twoFASecret: twoFASecret,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void _finishWithError({String? token, required String message}) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
token: token ?? state.token,
|
||||
errorMessage: message,
|
||||
);
|
||||
}
|
||||
|
||||
void showAccountCreated() {
|
||||
state = state.copyWith(showAccountCreated: true, showSecretCode: false);
|
||||
}
|
||||
|
||||
DateTime? _tryParseDate(String value) {
|
||||
final v = value.trim();
|
||||
if (v.isEmpty) return null;
|
||||
|
||||
final parts = v.split('/');
|
||||
if (parts.length != 3) return null;
|
||||
|
||||
final d = int.tryParse(parts[0]);
|
||||
final m = int.tryParse(parts[1]);
|
||||
final y = int.tryParse(parts[2]);
|
||||
|
||||
if (d == null || m == null || y == null) return null;
|
||||
|
||||
final date = DateTime(y, m, d);
|
||||
if (date.year != y || date.month != m || date.day != d) return null;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
String _formatDate(DateTime date) {
|
||||
final dd = date.day.toString().padLeft(2, '0');
|
||||
final mm = date.month.toString().padLeft(2, '0');
|
||||
final yyyy = date.year.toString();
|
||||
return '$dd/$mm/$yyyy';
|
||||
}
|
||||
|
||||
void setBornAt(DateTime date) {
|
||||
bornAtController.text = _formatDate(date);
|
||||
state = state.copyWith(bornAt: date, errorMessage: '');
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
firstNameController.removeListener(_onFirstNameChanged);
|
||||
lastNameController.removeListener(_onLastNameChanged);
|
||||
documentNumberController.removeListener(_onDocumentNumberChanged);
|
||||
documentTypeController.removeListener(_onDocumentTypeChanged);
|
||||
phoneController.removeListener(_onPhoneChanged);
|
||||
emailController.removeListener(_onEmailChanged);
|
||||
|
||||
relationshipController.removeListener(_onRelationshipChanged);
|
||||
bornAtController.removeListener(_onBornAtTextChanged);
|
||||
placeOfBirthController.removeListener(_onPlaceOfBirthChanged);
|
||||
birthCountryController.removeListener(_onBirthCountryChanged);
|
||||
|
||||
addressStreetController.removeListener(_onAddressStreetChanged);
|
||||
addressCityController.removeListener(_onAddressCityChanged);
|
||||
addressProvinceController.removeListener(_onAddressProvinceChanged);
|
||||
addressStateController.removeListener(_onAddressStateChanged);
|
||||
addressCountryController.removeListener(_onAddressCountryChanged);
|
||||
addressPostCodeController.removeListener(_onAddressPostCodeChanged);
|
||||
|
||||
passwordController.removeListener(_onPasswordChanged);
|
||||
repeatPasswordController.removeListener(_onRepeatPasswordChanged);
|
||||
|
||||
firstNameController.dispose();
|
||||
lastNameController.dispose();
|
||||
documentNumberController.dispose();
|
||||
documentTypeController.dispose();
|
||||
phoneController.dispose();
|
||||
emailController.dispose();
|
||||
|
||||
relationshipController.dispose();
|
||||
bornAtController.dispose();
|
||||
placeOfBirthController.dispose();
|
||||
birthCountryController.dispose();
|
||||
|
||||
addressStreetController.dispose();
|
||||
addressCityController.dispose();
|
||||
addressProvinceController.dispose();
|
||||
addressStateController.dispose();
|
||||
addressCountryController.dispose();
|
||||
addressPostCodeController.dispose();
|
||||
|
||||
passwordController.dispose();
|
||||
repeatPasswordController.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import 'package:auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'address_view_state.dart';
|
||||
|
||||
part 'sign_up_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class SignUpViewState with _$SignUpViewState {
|
||||
const factory SignUpViewState({
|
||||
@Default(0) int currentIndex,
|
||||
|
||||
@Default('') String documentNumber,
|
||||
@Default('') String documentType,
|
||||
@Default(false) bool acceptTerms,
|
||||
@Default('') String relationship,
|
||||
|
||||
@Default('') String firstName,
|
||||
@Default('') String lastName,
|
||||
@Default('') String email,
|
||||
@Default('') String phone,
|
||||
@Default('+34') String dialCode,
|
||||
@Default('') String language,
|
||||
DateTime? bornAt,
|
||||
@Default('') String password,
|
||||
@Default('') String repeatPassword,
|
||||
@Default(false) bool isShowPassword,
|
||||
@Default('') String userId,
|
||||
@Default('') String placeOfBirth,
|
||||
@Default('España') String birthCountry,
|
||||
@Default('ES') String birthCountryCode,
|
||||
|
||||
@Default(AddressViewState()) AddressViewState address,
|
||||
|
||||
@Default('') String emailError,
|
||||
@Default('') String passwordError,
|
||||
@Default('') String phoneError,
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool showErrors,
|
||||
@Default('') String token,
|
||||
TwoFASecretEntity? twoFASecret,
|
||||
@Default('') String otpCode,
|
||||
@Default('') String otpError,
|
||||
@Default(false) bool isOtpLoading,
|
||||
@Default(false) bool showAccountCreated,
|
||||
@Default(false) bool showSecretCode,
|
||||
}) = _SignUpViewState;
|
||||
}
|
||||
@@ -0,0 +1,409 @@
|
||||
// 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 'sign_up_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SignUpViewState {
|
||||
|
||||
int get currentIndex; String get documentNumber; String get documentType; bool get acceptTerms; String get relationship; String get firstName; String get lastName; String get email; String get phone; String get dialCode; String get language; DateTime? get bornAt; String get password; String get repeatPassword; bool get isShowPassword; String get userId; String get placeOfBirth; String get birthCountry; String get birthCountryCode; AddressViewState get address; String get emailError; String get passwordError; String get phoneError; String get errorMessage; bool get isLoading; bool get showErrors; String get token; TwoFASecretEntity? get twoFASecret; String get otpCode; String get otpError; bool get isOtpLoading; bool get showAccountCreated; bool get showSecretCode;
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SignUpViewStateCopyWith<SignUpViewState> get copyWith => _$SignUpViewStateCopyWithImpl<SignUpViewState>(this as SignUpViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SignUpViewState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.acceptTerms, acceptTerms) || other.acceptTerms == acceptTerms)&&(identical(other.relationship, relationship) || other.relationship == relationship)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.language, language) || other.language == language)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatPassword, repeatPassword) || other.repeatPassword == repeatPassword)&&(identical(other.isShowPassword, isShowPassword) || other.isShowPassword == isShowPassword)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.birthCountryCode, birthCountryCode) || other.birthCountryCode == birthCountryCode)&&(identical(other.address, address) || other.address == address)&&(identical(other.emailError, emailError) || other.emailError == emailError)&&(identical(other.passwordError, passwordError) || other.passwordError == passwordError)&&(identical(other.phoneError, phoneError) || other.phoneError == phoneError)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.showErrors, showErrors) || other.showErrors == showErrors)&&(identical(other.token, token) || other.token == token)&&(identical(other.twoFASecret, twoFASecret) || other.twoFASecret == twoFASecret)&&(identical(other.otpCode, otpCode) || other.otpCode == otpCode)&&(identical(other.otpError, otpError) || other.otpError == otpError)&&(identical(other.isOtpLoading, isOtpLoading) || other.isOtpLoading == isOtpLoading)&&(identical(other.showAccountCreated, showAccountCreated) || other.showAccountCreated == showAccountCreated)&&(identical(other.showSecretCode, showSecretCode) || other.showSecretCode == showSecretCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,currentIndex,documentNumber,documentType,acceptTerms,relationship,firstName,lastName,email,phone,dialCode,language,bornAt,password,repeatPassword,isShowPassword,userId,placeOfBirth,birthCountry,birthCountryCode,address,emailError,passwordError,phoneError,errorMessage,isLoading,showErrors,token,twoFASecret,otpCode,otpError,isOtpLoading,showAccountCreated,showSecretCode]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpViewState(currentIndex: $currentIndex, documentNumber: $documentNumber, documentType: $documentType, acceptTerms: $acceptTerms, relationship: $relationship, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, dialCode: $dialCode, language: $language, bornAt: $bornAt, password: $password, repeatPassword: $repeatPassword, isShowPassword: $isShowPassword, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, birthCountryCode: $birthCountryCode, address: $address, emailError: $emailError, passwordError: $passwordError, phoneError: $phoneError, errorMessage: $errorMessage, isLoading: $isLoading, showErrors: $showErrors, token: $token, twoFASecret: $twoFASecret, otpCode: $otpCode, otpError: $otpError, isOtpLoading: $isOtpLoading, showAccountCreated: $showAccountCreated, showSecretCode: $showSecretCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SignUpViewStateCopyWith<$Res> {
|
||||
factory $SignUpViewStateCopyWith(SignUpViewState value, $Res Function(SignUpViewState) _then) = _$SignUpViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int currentIndex, String documentNumber, String documentType, bool acceptTerms, String relationship, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, String userId, String placeOfBirth, String birthCountry, String birthCountryCode, AddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, String token, TwoFASecretEntity? twoFASecret, String otpCode, String otpError, bool isOtpLoading, bool showAccountCreated, bool showSecretCode
|
||||
});
|
||||
|
||||
|
||||
$AddressViewStateCopyWith<$Res> get address;$TwoFASecretEntityCopyWith<$Res>? get twoFASecret;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SignUpViewStateCopyWithImpl<$Res>
|
||||
implements $SignUpViewStateCopyWith<$Res> {
|
||||
_$SignUpViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SignUpViewState _self;
|
||||
final $Res Function(SignUpViewState) _then;
|
||||
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,Object? documentNumber = null,Object? documentType = null,Object? acceptTerms = null,Object? relationship = null,Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? dialCode = null,Object? language = null,Object? bornAt = freezed,Object? password = null,Object? repeatPassword = null,Object? isShowPassword = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,Object? birthCountryCode = null,Object? address = null,Object? emailError = null,Object? passwordError = null,Object? phoneError = null,Object? errorMessage = null,Object? isLoading = null,Object? showErrors = null,Object? token = null,Object? twoFASecret = freezed,Object? otpCode = null,Object? otpError = null,Object? isOtpLoading = null,Object? showAccountCreated = null,Object? showSecretCode = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,acceptTerms: null == acceptTerms ? _self.acceptTerms : acceptTerms // ignore: cast_nullable_to_non_nullable
|
||||
as bool,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatPassword: null == repeatPassword ? _self.repeatPassword : repeatPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,isShowPassword: null == isShowPassword ? _self.isShowPassword : isShowPassword // ignore: cast_nullable_to_non_nullable
|
||||
as bool,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountryCode: null == birthCountryCode ? _self.birthCountryCode : birthCountryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as AddressViewState,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordError: null == passwordError ? _self.passwordError : passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as String,phoneError: null == phoneError ? _self.phoneError : phoneError // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showErrors: null == showErrors ? _self.showErrors : showErrors // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,twoFASecret: freezed == twoFASecret ? _self.twoFASecret : twoFASecret // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretEntity?,otpCode: null == otpCode ? _self.otpCode : otpCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpError: null == otpError ? _self.otpError : otpError // ignore: cast_nullable_to_non_nullable
|
||||
as String,isOtpLoading: null == isOtpLoading ? _self.isOtpLoading : isOtpLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showAccountCreated: null == showAccountCreated ? _self.showAccountCreated : showAccountCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showSecretCode: null == showSecretCode ? _self.showSecretCode : showSecretCode // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$AddressViewStateCopyWith<$Res> get address {
|
||||
|
||||
return $AddressViewStateCopyWith<$Res>(_self.address, (value) {
|
||||
return _then(_self.copyWith(address: value));
|
||||
});
|
||||
}/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretEntityCopyWith<$Res>? get twoFASecret {
|
||||
if (_self.twoFASecret == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $TwoFASecretEntityCopyWith<$Res>(_self.twoFASecret!, (value) {
|
||||
return _then(_self.copyWith(twoFASecret: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SignUpViewState].
|
||||
extension SignUpViewStatePatterns on SignUpViewState {
|
||||
/// 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( _SignUpViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState() 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( _SignUpViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState():
|
||||
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( _SignUpViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState() 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( int currentIndex, String documentNumber, String documentType, bool acceptTerms, String relationship, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, String userId, String placeOfBirth, String birthCountry, String birthCountryCode, AddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, String token, TwoFASecretEntity? twoFASecret, String otpCode, String otpError, bool isOtpLoading, bool showAccountCreated, bool showSecretCode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState() when $default != null:
|
||||
return $default(_that.currentIndex,_that.documentNumber,_that.documentType,_that.acceptTerms,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.token,_that.twoFASecret,_that.otpCode,_that.otpError,_that.isOtpLoading,_that.showAccountCreated,_that.showSecretCode);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( int currentIndex, String documentNumber, String documentType, bool acceptTerms, String relationship, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, String userId, String placeOfBirth, String birthCountry, String birthCountryCode, AddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, String token, TwoFASecretEntity? twoFASecret, String otpCode, String otpError, bool isOtpLoading, bool showAccountCreated, bool showSecretCode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState():
|
||||
return $default(_that.currentIndex,_that.documentNumber,_that.documentType,_that.acceptTerms,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.token,_that.twoFASecret,_that.otpCode,_that.otpError,_that.isOtpLoading,_that.showAccountCreated,_that.showSecretCode);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( int currentIndex, String documentNumber, String documentType, bool acceptTerms, String relationship, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, String userId, String placeOfBirth, String birthCountry, String birthCountryCode, AddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, String token, TwoFASecretEntity? twoFASecret, String otpCode, String otpError, bool isOtpLoading, bool showAccountCreated, bool showSecretCode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SignUpViewState() when $default != null:
|
||||
return $default(_that.currentIndex,_that.documentNumber,_that.documentType,_that.acceptTerms,_that.relationship,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.userId,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.token,_that.twoFASecret,_that.otpCode,_that.otpError,_that.isOtpLoading,_that.showAccountCreated,_that.showSecretCode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _SignUpViewState implements SignUpViewState {
|
||||
const _SignUpViewState({this.currentIndex = 0, this.documentNumber = '', this.documentType = '', this.acceptTerms = false, this.relationship = '', this.firstName = '', this.lastName = '', this.email = '', this.phone = '', this.dialCode = '+34', this.language = '', this.bornAt, this.password = '', this.repeatPassword = '', this.isShowPassword = false, this.userId = '', this.placeOfBirth = '', this.birthCountry = 'España', this.birthCountryCode = 'ES', this.address = const AddressViewState(), this.emailError = '', this.passwordError = '', this.phoneError = '', this.errorMessage = '', this.isLoading = false, this.showErrors = false, this.token = '', this.twoFASecret, this.otpCode = '', this.otpError = '', this.isOtpLoading = false, this.showAccountCreated = false, this.showSecretCode = false});
|
||||
|
||||
|
||||
@override@JsonKey() final int currentIndex;
|
||||
@override@JsonKey() final String documentNumber;
|
||||
@override@JsonKey() final String documentType;
|
||||
@override@JsonKey() final bool acceptTerms;
|
||||
@override@JsonKey() final String relationship;
|
||||
@override@JsonKey() final String firstName;
|
||||
@override@JsonKey() final String lastName;
|
||||
@override@JsonKey() final String email;
|
||||
@override@JsonKey() final String phone;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override@JsonKey() final String language;
|
||||
@override final DateTime? bornAt;
|
||||
@override@JsonKey() final String password;
|
||||
@override@JsonKey() final String repeatPassword;
|
||||
@override@JsonKey() final bool isShowPassword;
|
||||
@override@JsonKey() final String userId;
|
||||
@override@JsonKey() final String placeOfBirth;
|
||||
@override@JsonKey() final String birthCountry;
|
||||
@override@JsonKey() final String birthCountryCode;
|
||||
@override@JsonKey() final AddressViewState address;
|
||||
@override@JsonKey() final String emailError;
|
||||
@override@JsonKey() final String passwordError;
|
||||
@override@JsonKey() final String phoneError;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool showErrors;
|
||||
@override@JsonKey() final String token;
|
||||
@override final TwoFASecretEntity? twoFASecret;
|
||||
@override@JsonKey() final String otpCode;
|
||||
@override@JsonKey() final String otpError;
|
||||
@override@JsonKey() final bool isOtpLoading;
|
||||
@override@JsonKey() final bool showAccountCreated;
|
||||
@override@JsonKey() final bool showSecretCode;
|
||||
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SignUpViewStateCopyWith<_SignUpViewState> get copyWith => __$SignUpViewStateCopyWithImpl<_SignUpViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SignUpViewState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.documentNumber, documentNumber) || other.documentNumber == documentNumber)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.acceptTerms, acceptTerms) || other.acceptTerms == acceptTerms)&&(identical(other.relationship, relationship) || other.relationship == relationship)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.language, language) || other.language == language)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatPassword, repeatPassword) || other.repeatPassword == repeatPassword)&&(identical(other.isShowPassword, isShowPassword) || other.isShowPassword == isShowPassword)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.birthCountryCode, birthCountryCode) || other.birthCountryCode == birthCountryCode)&&(identical(other.address, address) || other.address == address)&&(identical(other.emailError, emailError) || other.emailError == emailError)&&(identical(other.passwordError, passwordError) || other.passwordError == passwordError)&&(identical(other.phoneError, phoneError) || other.phoneError == phoneError)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.showErrors, showErrors) || other.showErrors == showErrors)&&(identical(other.token, token) || other.token == token)&&(identical(other.twoFASecret, twoFASecret) || other.twoFASecret == twoFASecret)&&(identical(other.otpCode, otpCode) || other.otpCode == otpCode)&&(identical(other.otpError, otpError) || other.otpError == otpError)&&(identical(other.isOtpLoading, isOtpLoading) || other.isOtpLoading == isOtpLoading)&&(identical(other.showAccountCreated, showAccountCreated) || other.showAccountCreated == showAccountCreated)&&(identical(other.showSecretCode, showSecretCode) || other.showSecretCode == showSecretCode));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,currentIndex,documentNumber,documentType,acceptTerms,relationship,firstName,lastName,email,phone,dialCode,language,bornAt,password,repeatPassword,isShowPassword,userId,placeOfBirth,birthCountry,birthCountryCode,address,emailError,passwordError,phoneError,errorMessage,isLoading,showErrors,token,twoFASecret,otpCode,otpError,isOtpLoading,showAccountCreated,showSecretCode]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignUpViewState(currentIndex: $currentIndex, documentNumber: $documentNumber, documentType: $documentType, acceptTerms: $acceptTerms, relationship: $relationship, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, dialCode: $dialCode, language: $language, bornAt: $bornAt, password: $password, repeatPassword: $repeatPassword, isShowPassword: $isShowPassword, userId: $userId, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, birthCountryCode: $birthCountryCode, address: $address, emailError: $emailError, passwordError: $passwordError, phoneError: $phoneError, errorMessage: $errorMessage, isLoading: $isLoading, showErrors: $showErrors, token: $token, twoFASecret: $twoFASecret, otpCode: $otpCode, otpError: $otpError, isOtpLoading: $isOtpLoading, showAccountCreated: $showAccountCreated, showSecretCode: $showSecretCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SignUpViewStateCopyWith<$Res> implements $SignUpViewStateCopyWith<$Res> {
|
||||
factory _$SignUpViewStateCopyWith(_SignUpViewState value, $Res Function(_SignUpViewState) _then) = __$SignUpViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int currentIndex, String documentNumber, String documentType, bool acceptTerms, String relationship, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, String userId, String placeOfBirth, String birthCountry, String birthCountryCode, AddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, String token, TwoFASecretEntity? twoFASecret, String otpCode, String otpError, bool isOtpLoading, bool showAccountCreated, bool showSecretCode
|
||||
});
|
||||
|
||||
|
||||
@override $AddressViewStateCopyWith<$Res> get address;@override $TwoFASecretEntityCopyWith<$Res>? get twoFASecret;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SignUpViewStateCopyWithImpl<$Res>
|
||||
implements _$SignUpViewStateCopyWith<$Res> {
|
||||
__$SignUpViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SignUpViewState _self;
|
||||
final $Res Function(_SignUpViewState) _then;
|
||||
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? documentNumber = null,Object? documentType = null,Object? acceptTerms = null,Object? relationship = null,Object? firstName = null,Object? lastName = null,Object? email = null,Object? phone = null,Object? dialCode = null,Object? language = null,Object? bornAt = freezed,Object? password = null,Object? repeatPassword = null,Object? isShowPassword = null,Object? userId = null,Object? placeOfBirth = null,Object? birthCountry = null,Object? birthCountryCode = null,Object? address = null,Object? emailError = null,Object? passwordError = null,Object? phoneError = null,Object? errorMessage = null,Object? isLoading = null,Object? showErrors = null,Object? token = null,Object? twoFASecret = freezed,Object? otpCode = null,Object? otpError = null,Object? isOtpLoading = null,Object? showAccountCreated = null,Object? showSecretCode = null,}) {
|
||||
return _then(_SignUpViewState(
|
||||
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int,documentNumber: null == documentNumber ? _self.documentNumber : documentNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable
|
||||
as String,acceptTerms: null == acceptTerms ? _self.acceptTerms : acceptTerms // ignore: cast_nullable_to_non_nullable
|
||||
as bool,relationship: null == relationship ? _self.relationship : relationship // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||
as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatPassword: null == repeatPassword ? _self.repeatPassword : repeatPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,isShowPassword: null == isShowPassword ? _self.isShowPassword : isShowPassword // ignore: cast_nullable_to_non_nullable
|
||||
as bool,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
||||
as String,placeOfBirth: null == placeOfBirth ? _self.placeOfBirth : placeOfBirth // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountry: null == birthCountry ? _self.birthCountry : birthCountry // ignore: cast_nullable_to_non_nullable
|
||||
as String,birthCountryCode: null == birthCountryCode ? _self.birthCountryCode : birthCountryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as AddressViewState,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordError: null == passwordError ? _self.passwordError : passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as String,phoneError: null == phoneError ? _self.phoneError : phoneError // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showErrors: null == showErrors ? _self.showErrors : showErrors // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,twoFASecret: freezed == twoFASecret ? _self.twoFASecret : twoFASecret // ignore: cast_nullable_to_non_nullable
|
||||
as TwoFASecretEntity?,otpCode: null == otpCode ? _self.otpCode : otpCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,otpError: null == otpError ? _self.otpError : otpError // ignore: cast_nullable_to_non_nullable
|
||||
as String,isOtpLoading: null == isOtpLoading ? _self.isOtpLoading : isOtpLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showAccountCreated: null == showAccountCreated ? _self.showAccountCreated : showAccountCreated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showSecretCode: null == showSecretCode ? _self.showSecretCode : showSecretCode // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$AddressViewStateCopyWith<$Res> get address {
|
||||
|
||||
return $AddressViewStateCopyWith<$Res>(_self.address, (value) {
|
||||
return _then(_self.copyWith(address: value));
|
||||
});
|
||||
}/// Create a copy of SignUpViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TwoFASecretEntityCopyWith<$Res>? get twoFASecret {
|
||||
if (_self.twoFASecret == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $TwoFASecretEntityCopyWith<$Res>(_self.twoFASecret!, (value) {
|
||||
return _then(_self.copyWith(twoFASecret: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:auth/src/features/sign_up/signup_screen.dart';
|
||||
import 'package:auth/src/features/sign_up/presentation/sign_up_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
@@ -1,103 +0,0 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class SignupAddressScreen extends ConsumerStatefulWidget {
|
||||
const SignupAddressScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<SignupAddressScreen> createState() => SignupAddressScreenState();
|
||||
|
||||
}
|
||||
|
||||
class SignupAddressScreenState extends ConsumerState<SignupAddressScreen>{
|
||||
|
||||
late String country;
|
||||
late int relation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
relation = 0;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(alignment: Alignment.bottomLeft, child: Text(
|
||||
"Fecha de nacimiento",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(child: CustomTextField(
|
||||
//label: "Fecha de nacimiento",
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
numeric: true,
|
||||
)),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"¿Qué familiar eres?",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
CustomDropdown(
|
||||
items: [Text("Padre"), Text("Madre"), Text("Tutor")],
|
||||
hint: "¿Qué familiar eres?",
|
||||
onChanged: (value)=>setState(() {
|
||||
relation = value;
|
||||
})
|
||||
),
|
||||
],
|
||||
),
|
||||
CustomTextField(label: "Dirección completa", hint: "Calle Gran Vía 30 6º, 28013"),
|
||||
CustomTextField(label: "Ciudad", hint: "Ciudad"),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"País",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
CustomDropdown(
|
||||
items: [Text("España"), Text("Francia"), Text("Portugal")],
|
||||
hint: "País",
|
||||
onChanged: (value)=>setState(() {
|
||||
country = value;
|
||||
})
|
||||
),
|
||||
],
|
||||
),
|
||||
CustomTextField(label: "Nacionalidad", hint: "España"),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user