diff --git a/.idea/modules.xml b/.idea/modules.xml index deb74bef..523fb975 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -15,6 +15,7 @@ + diff --git a/.idea/runConfigurations/melos_flutter_test_legacy_auth.xml b/.idea/runConfigurations/melos_flutter_test_legacy_auth.xml new file mode 100644 index 00000000..b90babc1 --- /dev/null +++ b/.idea/runConfigurations/melos_flutter_test_legacy_auth.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/apps/mobile_app/lib/navigation/app_router.dart b/apps/mobile_app/lib/navigation/app_router.dart index 79182af9..2ede078f 100644 --- a/apps/mobile_app/lib/navigation/app_router.dart +++ b/apps/mobile_app/lib/navigation/app_router.dart @@ -1,6 +1,7 @@ import 'package:account/account.dart'; import 'package:activity/activity.dart'; import 'package:auth/auth.dart'; +import 'package:legacy_auth/legacy_auth.dart'; import 'package:customer_service/customer_service.dart'; import 'package:dashboard_shell/dashboard_builder.dart'; import 'package:device_management/device_management.dart'; @@ -23,7 +24,7 @@ late final GoRouter appRouter; void configureAppRouter() { appRouter = GoRouter( navigatorKey: rootNavigatorKey, - initialLocation: AppRoutes.splash, + initialLocation: AppRoutes.legacyLogin, debugLogDiagnostics: true, routes: [ GoRoute( @@ -153,6 +154,41 @@ void configureAppRouter() { name: 'device_setup', pageBuilder: DeviceSetupBuilder().buildPage, ), + GoRoute( + path: AppRoutes.legacyLogin, + name: 'legacy_login', + pageBuilder: LegacyLoginBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacySignup, + name: 'legacy_signup', + pageBuilder: LegacySignupBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacyOnboarding, + name: 'legacy_onboarding', + pageBuilder: LegacyOnboardingBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacyLinkPhone, + name: 'legacy_request_link_phone', + pageBuilder: LegacyRequestLinkPhoneBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacyPhoneCode, + name: 'legacy_verify_link_phone_code', + pageBuilder: LegacyVerifyLinkPhoneCodeBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacyRecoverPassword, + name: 'legacy_recover_password', + pageBuilder: LegacyRequestRecoveryBuilder().buildPage, + ), + GoRoute( + path: AppRoutes.legacyDeviceSetup, + name: 'legacy_device_setup', + pageBuilder: LegacyDeviceSetupBuilder().buildPage, + ), GoRoute( path: AppRoutes.hipayWebView, name: 'hipay_webview', diff --git a/apps/mobile_app/pubspec.lock b/apps/mobile_app/pubspec.lock index 8511bff6..5a913152 100644 --- a/apps/mobile_app/pubspec.lock +++ b/apps/mobile_app/pubspec.lock @@ -690,6 +690,13 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + legacy_auth: + dependency: "direct main" + description: + path: "../../modules/legacy/modules/legacy_auth" + relative: true + source: path + version: "0.0.1" legacy_dashboard_shell: dependency: "direct main" description: diff --git a/apps/mobile_app/pubspec.yaml b/apps/mobile_app/pubspec.yaml index a97c1719..d8968f64 100644 --- a/apps/mobile_app/pubspec.yaml +++ b/apps/mobile_app/pubspec.yaml @@ -61,6 +61,8 @@ dependencies: path: ../../modules/legacy/modules/account device_management: path: ../../modules/legacy/modules/device_management + legacy_auth: + path: ../../modules/legacy/modules/legacy_auth #packages dependencies go here navigation: path: ../../packages/navigation diff --git a/apps/mobile_app/pubspec_overrides.yaml b/apps/mobile_app/pubspec_overrides.yaml index caf849a2..2a761c30 100644 --- a/apps/mobile_app/pubspec_overrides.yaml +++ b/apps/mobile_app/pubspec_overrides.yaml @@ -1,4 +1,4 @@ -# melos_managed_dependency_overrides: account,activity,auth,customer_service,dashboard_shell,design_system,flutter_treezor_entrust_sdk_bridge,fonts,home,legacy_dashboard_shell,legacy_shared,navigation,notifications,payments,profile,sca_treezor,sf_infrastructure,sf_localizations,sf_shared,splash,utils,control_panel,device_management +# melos_managed_dependency_overrides: account,activity,auth,customer_service,dashboard_shell,design_system,flutter_treezor_entrust_sdk_bridge,fonts,home,legacy_dashboard_shell,legacy_shared,navigation,notifications,payments,profile,sca_treezor,sf_infrastructure,sf_localizations,sf_shared,splash,utils,control_panel,device_management,legacy_auth dependency_overrides: account: path: ../../modules/legacy/modules/account @@ -22,6 +22,8 @@ dependency_overrides: path: ../../packages/fonts home: path: ../../modules/home + legacy_auth: + path: ../../modules/legacy/modules/legacy_auth legacy_dashboard_shell: path: ../../modules/legacy/modules/legacy_dashboard_shell legacy_shared: diff --git a/modules/legacy/modules/legacy_auth/.gitignore b/modules/legacy/modules/legacy_auth/.gitignore new file mode 100644 index 00000000..dd5eb989 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/modules/legacy/modules/legacy_auth/.metadata b/modules/legacy/modules/legacy_auth/.metadata new file mode 100644 index 00000000..d7469f07 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2" + channel: "stable" + +project_type: package diff --git a/modules/legacy/modules/legacy_auth/CHANGELOG.md b/modules/legacy/modules/legacy_auth/CHANGELOG.md new file mode 100644 index 00000000..41cc7d81 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/modules/legacy/modules/legacy_auth/LICENSE b/modules/legacy/modules/legacy_auth/LICENSE new file mode 100644 index 00000000..ba75c69f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/modules/legacy/modules/legacy_auth/README.md b/modules/legacy/modules/legacy_auth/README.md new file mode 100644 index 00000000..4a260d8d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/modules/legacy/modules/legacy_auth/analysis_options.yaml b/modules/legacy/modules/legacy_auth/analysis_options.yaml new file mode 100644 index 00000000..a5744c1c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/modules/legacy/modules/legacy_auth/lib/legacy_auth.dart b/modules/legacy/modules/legacy_auth/lib/legacy_auth.dart new file mode 100644 index 00000000..81bd4f3b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/legacy_auth.dart @@ -0,0 +1,10 @@ +export 'src/features/onboarding/onboarding_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/presentation/request_recovery/request_recovery_builder.dart'; +export 'src/features/device_setup/device_setup_builder.dart'; +export 'src/features/sign_up/sign_up_builder.dart'; +export 'src/core/data/datasource/session_local_datasource.dart'; +export 'src/core/providers/auth_repository_provider.dart'; +export 'src/core/data/datasource/session_local_datasource_impl.dart'; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource.dart new file mode 100644 index 00000000..3d7bb231 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource.dart @@ -0,0 +1,56 @@ +import 'package:legacy_auth/src/core/data/models/child_profile_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_request_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/login_response_model.dart'; + +abstract class LegacyAuthRemoteDatasource { + Future requestPhoneCode({required String phone}); + + Future verifyPhoneCode({required String phone, required String code}); + + Future login({ + required String email, + required String password, + }); + Future twoFARequestCode({ + required String token, + required String methodType, + }); + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }); + + // Future totpLogin({required String token, required String code}); + + Future signUp({required LegacySignUpRequestModel request}); + + Future generateTwoFASignUp({required String token}); + + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }); + + Future requestPasswordReset({required String email}); + + Future recoverPassword({required newPassword, required token}); + + Future logout(); + + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart new file mode 100644 index 00000000..b51da51a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart @@ -0,0 +1,343 @@ +import 'dart:convert'; + +import 'package:legacy_auth/src/core/data/models/child_profile_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_request_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; +import 'package:legacy_auth/src/core/data/models/login_response_model.dart'; + +import 'auth_remote_datasource.dart'; + +class LegacyAuthRemoteDatasourceImpl implements LegacyAuthRemoteDatasource { + LegacyAuthRemoteDatasourceImpl(this._repository); + + final QuestiaRepository _repository; + + @override + Future requestPhoneCode({required String phone}) async { + try { + await _repository.post( + '/auth/link-phone/request-code', + body: {'phone': phone}, + ); + } on DioException catch (error) { + throw _mapDioError( + error, + defaultMessage: error.response?.data ?? 'Error to request phone code', + ); + } + } + + @override + Future verifyPhoneCode({ + required String phone, + required String code, + }) async { + try { + await _repository.post( + '/auth/link-phone/verify-code', + body: {'phone': phone, 'code': code}, + ); + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in verification code'); + } + } + + @override + Future login({ + required String email, + required String password, + }) async { + try { + final response = await _repository.post>( + '/auth/login', + body: {'email': email, 'password': password}, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception('Empty response from /auth/login'); + } + + final parsed = LegacyLoginResponseModel.fromJson(data); + + return parsed; + } on DioException catch (error) { + throw _mapDioError( + error, + defaultMessage: error.message ?? 'Error in login', + ); + } + } + + @override + Future twoFARequestCode({ + //this gonna send a request to the backend to send email code to the user for default + required String token, + required String methodType, + }) async { + try { + await _repository.post( + '/auth/2fa/request-code', + body: {'token': token, 'methodType': methodType}, + ); + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in twoFARequestCode'); + } + } + + @override + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }) async { + try { + await _repository.post( + '/auth/twofa/login', + body: { + 'token': token, + 'code': code, + 'methodType': methodType, + 'rememberMe': true, + }, + ); + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in twoFASendCode'); + } + } + + // @override + // Future totpLogin({ + // required String token, + // required String code, + // }) async { + // try { + // final response = await _repository.post( + // '/auth/totp/login', + // body: { + // '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 totpLogin'); + // } + // } + + @override + Future signUp({ + required LegacySignUpRequestModel request, + }) async { + try { + final body = request.toJson(); + debugPrint(const JsonEncoder.withIndent(' ').convert(body)); + + final response = await _repository.post>( + '/auth/signup', + body: body, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception('Empty response from /auth/signup'); + } + + final parsed = LegacySignUpResponseModel.fromJson(data); + + if (!parsed.isCreated) { + throw Exception('Sign up failed: isCreated=false'); + } + + final userId = parsed.item.userId.trim(); + if (userId.isEmpty) { + throw Exception('Sign up response has empty userId'); + } + + return parsed; + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in signUp'); + } + } + + @override + Future generateTwoFASignUp({ + required String token, + }) async { + try { + final response = await _repository.post>( + '/auth/totp/secret', + body: {'token': token}, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception('Empty response from /auth/totp/secret'); + } + + final model = LegacyTwoFASecretResponseModel.fromJson(data); + return model; + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in twoFASignUp'); + } + } + + @override + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }) async { + try { + final response = await _repository.post( + '/auth/totp/code', + body: {'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 requestPasswordReset({required String email}) async { + try { + late final Map body; + body = {'email': email}; + + final response = await _repository.put( + '/auth/reset-password', + body: body, + ); + 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 to request password reset', + ); + } + } + + @override + Future recoverPassword({required newPassword, required token}) async { + try { + await _repository.put( + '/auth/recovery-password', + body: {'newPassword': newPassword, 'token': token}, + ); + } on DioException catch (error) { + throw _mapDioError( + error, + defaultMessage: 'Error to request password recovery', + ); + } + } + + @override + Future logout() async { + try { + await _repository.post('/auth/logout'); + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in logout'); + } + } + + @override + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }) async { + try { + final response = await _repository.post>( + '/child-profiles', + body: { + 'address': address, + 'bornAt': bornAt, + 'cardPublicKey': cardPublicKey, + 'deviceActivationCode': deviceActivationCode, + 'firstName': firstName, + 'genre': genrer, + 'id': id, + 'lastName': lastName, + 'parentId': parentId, + 'relationType': relationType, + 'scaProof': scaProof, + }, + ); + + final data = response.data; + if (data == null || data.isEmpty) { + throw Exception('Empty response from /auth/child-profiles'); + } + + return LegacyChildProfileResponseModel.fromJson(data); + } on DioException catch (error) { + throw _mapDioError(error, defaultMessage: 'Error in createChildProfile'); + } + } +} + +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; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource.dart new file mode 100644 index 00000000..9ee25bc0 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource.dart @@ -0,0 +1,6 @@ +abstract class LegacySessionLocalDatasource { + Future savePaymentProfileId(String id); + Future getPaymentProfileId(); + + Future clearSession(); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource_impl.dart new file mode 100644 index 00000000..8ebc9e2b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/datasource/session_local_datasource_impl.dart @@ -0,0 +1,25 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +import 'session_local_datasource.dart'; + +class LegacySessionLocalDatasourceImpl implements LegacySessionLocalDatasource { + static const _paymentProfileIdKey = 'session_payment_profile_id'; + + @override + Future savePaymentProfileId(String id) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_paymentProfileIdKey, id); + } + + @override + Future getPaymentProfileId() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString(_paymentProfileIdKey); + } + + @override + Future clearSession() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.remove(_paymentProfileIdKey); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.dart new file mode 100644 index 00000000..24588ffa --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.dart @@ -0,0 +1,31 @@ +import 'package:legacy_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 LegacyAddressModel with _$LegacyAddressModel { + const factory LegacyAddressModel({ + required String street, + required String city, + required String province, + required String state, + required String country, + required int postCode, + }) = _LegacyAddressModel; + + factory LegacyAddressModel.fromJson(Map json) => + _$LegacyAddressModelFromJson(json); +} + +extension LegacyAddressModelMapper on LegacyAddressEntity { + LegacyAddressModel toModel() => LegacyAddressModel( + street: street, + city: city, + province: province, + state: state, + country: country, + postCode: postCode, + ); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.freezed.dart new file mode 100644 index 00000000..77e224a2 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.freezed.dart @@ -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 value) => value; + +/// @nodoc +mixin _$LegacyAddressModel { + + String get street; String get city; String get province; String get state; String get country; int get postCode; +/// Create a copy of LegacyAddressModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyAddressModelCopyWith get copyWith => _$LegacyAddressModelCopyWithImpl(this as LegacyAddressModel, _$identity); + + /// Serializes this LegacyAddressModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyAddressModel&&(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 'LegacyAddressModel(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyAddressModelCopyWith<$Res> { + factory $LegacyAddressModelCopyWith(LegacyAddressModel value, $Res Function(LegacyAddressModel) _then) = _$LegacyAddressModelCopyWithImpl; +@useResult +$Res call({ + String street, String city, String province, String state, String country, int postCode +}); + + + + +} +/// @nodoc +class _$LegacyAddressModelCopyWithImpl<$Res> + implements $LegacyAddressModelCopyWith<$Res> { + _$LegacyAddressModelCopyWithImpl(this._self, this._then); + + final LegacyAddressModel _self; + final $Res Function(LegacyAddressModel) _then; + +/// Create a copy of LegacyAddressModel +/// 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 [LegacyAddressModel]. +extension LegacyAddressModelPatterns on LegacyAddressModel { +/// 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 Function( _LegacyAddressModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyAddressModel() 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 Function( _LegacyAddressModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressModel(): +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? Function( _LegacyAddressModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressModel() 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 Function( String street, String city, String province, String state, String country, int postCode)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyAddressModel() 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 Function( String street, String city, String province, String state, String country, int postCode) $default,) {final _that = this; +switch (_that) { +case _LegacyAddressModel(): +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? Function( String street, String city, String province, String state, String country, int postCode)? $default,) {final _that = this; +switch (_that) { +case _LegacyAddressModel() when $default != null: +return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyAddressModel implements LegacyAddressModel { + const _LegacyAddressModel({required this.street, required this.city, required this.province, required this.state, required this.country, required this.postCode}); + factory _LegacyAddressModel.fromJson(Map json) => _$LegacyAddressModelFromJson(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 LegacyAddressModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyAddressModelCopyWith<_LegacyAddressModel> get copyWith => __$LegacyAddressModelCopyWithImpl<_LegacyAddressModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyAddressModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyAddressModel&&(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 'LegacyAddressModel(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyAddressModelCopyWith<$Res> implements $LegacyAddressModelCopyWith<$Res> { + factory _$LegacyAddressModelCopyWith(_LegacyAddressModel value, $Res Function(_LegacyAddressModel) _then) = __$LegacyAddressModelCopyWithImpl; +@override @useResult +$Res call({ + String street, String city, String province, String state, String country, int postCode +}); + + + + +} +/// @nodoc +class __$LegacyAddressModelCopyWithImpl<$Res> + implements _$LegacyAddressModelCopyWith<$Res> { + __$LegacyAddressModelCopyWithImpl(this._self, this._then); + + final _LegacyAddressModel _self; + final $Res Function(_LegacyAddressModel) _then; + +/// Create a copy of LegacyAddressModel +/// 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(_LegacyAddressModel( +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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.g.dart new file mode 100644 index 00000000..6ccfa5ff --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/address_model.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'address_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacyAddressModel _$LegacyAddressModelFromJson(Map json) => + _LegacyAddressModel( + 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 _$LegacyAddressModelToJson(_LegacyAddressModel instance) => + { + 'street': instance.street, + 'city': instance.city, + 'province': instance.province, + 'state': instance.state, + 'country': instance.country, + 'postCode': instance.postCode, + }; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.dart new file mode 100644 index 00000000..ef82fe70 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.dart @@ -0,0 +1,56 @@ +import 'package:legacy_auth/src/features/device_setup/domain/entities/child_profile_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'child_profile_response_model.freezed.dart'; +part 'child_profile_response_model.g.dart'; + +@freezed +abstract class LegacyChildProfileResponseModel with _$LegacyChildProfileResponseModel { + const factory LegacyChildProfileResponseModel({ + required bool isCreated, + required LegacyChildProfileItemResponseModel item, + }) = _LegacyChildProfileResponseModel; + + factory LegacyChildProfileResponseModel.fromJson(Map json) => + _$LegacyChildProfileResponseModelFromJson(json); +} + +@freezed +abstract class LegacyChildProfileItemResponseModel + with _$LegacyChildProfileItemResponseModel { + const factory LegacyChildProfileItemResponseModel({ + required String id, + required String deviceIdentificator, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String address, + required int createdAt, + int? updatedAt, + String? profileImageId, + }) = _LegacyChildProfileItemResponseModel; + + factory LegacyChildProfileItemResponseModel.fromJson(Map json) => + _$LegacyChildProfileItemResponseModelFromJson(json); +} + +extension LegacyChildProfileResponseModelMapper on LegacyChildProfileResponseModel { + LegacyChildProfileEntity toEntity() { + return LegacyChildProfileEntity( + isCreated: isCreated, + item: LegacyChildProfileItemEntity( + id: item.id, + deviceIdentificator: item.deviceIdentificator, + parentId: item.parentId, + firstName: item.firstName, + lastName: item.lastName, + bornAt: item.bornAt, + address: item.address, + createdAt: item.createdAt, + updatedAt: item.updatedAt, + profileImageId: item.profileImageId, + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.freezed.dart new file mode 100644 index 00000000..7417d3d5 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.freezed.dart @@ -0,0 +1,588 @@ +// 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 'child_profile_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$LegacyChildProfileResponseModel { + + bool get isCreated; LegacyChildProfileItemResponseModel get item; +/// Create a copy of LegacyChildProfileResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyChildProfileResponseModelCopyWith get copyWith => _$LegacyChildProfileResponseModelCopyWithImpl(this as LegacyChildProfileResponseModel, _$identity); + + /// Serializes this LegacyChildProfileResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyChildProfileResponseModel&&(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 'LegacyChildProfileResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyChildProfileResponseModelCopyWith<$Res> { + factory $LegacyChildProfileResponseModelCopyWith(LegacyChildProfileResponseModel value, $Res Function(LegacyChildProfileResponseModel) _then) = _$LegacyChildProfileResponseModelCopyWithImpl; +@useResult +$Res call({ + bool isCreated, LegacyChildProfileItemResponseModel item +}); + + +$LegacyChildProfileItemResponseModelCopyWith<$Res> get item; + +} +/// @nodoc +class _$LegacyChildProfileResponseModelCopyWithImpl<$Res> + implements $LegacyChildProfileResponseModelCopyWith<$Res> { + _$LegacyChildProfileResponseModelCopyWithImpl(this._self, this._then); + + final LegacyChildProfileResponseModel _self; + final $Res Function(LegacyChildProfileResponseModel) _then; + +/// Create a copy of LegacyChildProfileResponseModel +/// 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 LegacyChildProfileItemResponseModel, + )); +} +/// Create a copy of LegacyChildProfileResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyChildProfileItemResponseModelCopyWith<$Res> get item { + + return $LegacyChildProfileItemResponseModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacyChildProfileResponseModel]. +extension LegacyChildProfileResponseModelPatterns on LegacyChildProfileResponseModel { +/// 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 Function( _LegacyChildProfileResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel() 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 Function( _LegacyChildProfileResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel(): +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? Function( _LegacyChildProfileResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel() 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 Function( bool isCreated, LegacyChildProfileItemResponseModel item)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel() 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 Function( bool isCreated, LegacyChildProfileItemResponseModel item) $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel(): +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? Function( bool isCreated, LegacyChildProfileItemResponseModel item)? $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileResponseModel() when $default != null: +return $default(_that.isCreated,_that.item);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyChildProfileResponseModel implements LegacyChildProfileResponseModel { + const _LegacyChildProfileResponseModel({required this.isCreated, required this.item}); + factory _LegacyChildProfileResponseModel.fromJson(Map json) => _$LegacyChildProfileResponseModelFromJson(json); + +@override final bool isCreated; +@override final LegacyChildProfileItemResponseModel item; + +/// Create a copy of LegacyChildProfileResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyChildProfileResponseModelCopyWith<_LegacyChildProfileResponseModel> get copyWith => __$LegacyChildProfileResponseModelCopyWithImpl<_LegacyChildProfileResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyChildProfileResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyChildProfileResponseModel&&(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 'LegacyChildProfileResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyChildProfileResponseModelCopyWith<$Res> implements $LegacyChildProfileResponseModelCopyWith<$Res> { + factory _$LegacyChildProfileResponseModelCopyWith(_LegacyChildProfileResponseModel value, $Res Function(_LegacyChildProfileResponseModel) _then) = __$LegacyChildProfileResponseModelCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, LegacyChildProfileItemResponseModel item +}); + + +@override $LegacyChildProfileItemResponseModelCopyWith<$Res> get item; + +} +/// @nodoc +class __$LegacyChildProfileResponseModelCopyWithImpl<$Res> + implements _$LegacyChildProfileResponseModelCopyWith<$Res> { + __$LegacyChildProfileResponseModelCopyWithImpl(this._self, this._then); + + final _LegacyChildProfileResponseModel _self; + final $Res Function(_LegacyChildProfileResponseModel) _then; + +/// Create a copy of LegacyChildProfileResponseModel +/// 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(_LegacyChildProfileResponseModel( +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 LegacyChildProfileItemResponseModel, + )); +} + +/// Create a copy of LegacyChildProfileResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyChildProfileItemResponseModelCopyWith<$Res> get item { + + return $LegacyChildProfileItemResponseModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// @nodoc +mixin _$LegacyChildProfileItemResponseModel { + + String get id; String get deviceIdentificator; String get parentId; String get firstName; String get lastName; int get bornAt; String get address; int get createdAt; int? get updatedAt; String? get profileImageId; +/// Create a copy of LegacyChildProfileItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyChildProfileItemResponseModelCopyWith get copyWith => _$LegacyChildProfileItemResponseModelCopyWithImpl(this as LegacyChildProfileItemResponseModel, _$identity); + + /// Serializes this LegacyChildProfileItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyChildProfileItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.profileImageId, profileImageId) || other.profileImageId == profileImageId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,parentId,firstName,lastName,bornAt,address,createdAt,updatedAt,profileImageId); + +@override +String toString() { + return 'LegacyChildProfileItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, createdAt: $createdAt, updatedAt: $updatedAt, profileImageId: $profileImageId)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyChildProfileItemResponseModelCopyWith<$Res> { + factory $LegacyChildProfileItemResponseModelCopyWith(LegacyChildProfileItemResponseModel value, $Res Function(LegacyChildProfileItemResponseModel) _then) = _$LegacyChildProfileItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId +}); + + + + +} +/// @nodoc +class _$LegacyChildProfileItemResponseModelCopyWithImpl<$Res> + implements $LegacyChildProfileItemResponseModelCopyWith<$Res> { + _$LegacyChildProfileItemResponseModelCopyWithImpl(this._self, this._then); + + final LegacyChildProfileItemResponseModel _self; + final $Res Function(LegacyChildProfileItemResponseModel) _then; + +/// Create a copy of LegacyChildProfileItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = null,Object? address = null,Object? createdAt = null,Object? updatedAt = freezed,Object? profileImageId = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?,profileImageId: freezed == profileImageId ? _self.profileImageId : profileImageId // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyChildProfileItemResponseModel]. +extension LegacyChildProfileItemResponseModelPatterns on LegacyChildProfileItemResponseModel { +/// 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 Function( _LegacyChildProfileItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel() 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 Function( _LegacyChildProfileItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel(): +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? Function( _LegacyChildProfileItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel() 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 Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);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 Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId) $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel(): +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);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? Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId)? $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemResponseModel() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyChildProfileItemResponseModel implements LegacyChildProfileItemResponseModel { + const _LegacyChildProfileItemResponseModel({required this.id, required this.deviceIdentificator, required this.parentId, required this.firstName, required this.lastName, required this.bornAt, required this.address, required this.createdAt, this.updatedAt, this.profileImageId}); + factory _LegacyChildProfileItemResponseModel.fromJson(Map json) => _$LegacyChildProfileItemResponseModelFromJson(json); + +@override final String id; +@override final String deviceIdentificator; +@override final String parentId; +@override final String firstName; +@override final String lastName; +@override final int bornAt; +@override final String address; +@override final int createdAt; +@override final int? updatedAt; +@override final String? profileImageId; + +/// Create a copy of LegacyChildProfileItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyChildProfileItemResponseModelCopyWith<_LegacyChildProfileItemResponseModel> get copyWith => __$LegacyChildProfileItemResponseModelCopyWithImpl<_LegacyChildProfileItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyChildProfileItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyChildProfileItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.profileImageId, profileImageId) || other.profileImageId == profileImageId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,parentId,firstName,lastName,bornAt,address,createdAt,updatedAt,profileImageId); + +@override +String toString() { + return 'LegacyChildProfileItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, createdAt: $createdAt, updatedAt: $updatedAt, profileImageId: $profileImageId)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyChildProfileItemResponseModelCopyWith<$Res> implements $LegacyChildProfileItemResponseModelCopyWith<$Res> { + factory _$LegacyChildProfileItemResponseModelCopyWith(_LegacyChildProfileItemResponseModel value, $Res Function(_LegacyChildProfileItemResponseModel) _then) = __$LegacyChildProfileItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId +}); + + + + +} +/// @nodoc +class __$LegacyChildProfileItemResponseModelCopyWithImpl<$Res> + implements _$LegacyChildProfileItemResponseModelCopyWith<$Res> { + __$LegacyChildProfileItemResponseModelCopyWithImpl(this._self, this._then); + + final _LegacyChildProfileItemResponseModel _self; + final $Res Function(_LegacyChildProfileItemResponseModel) _then; + +/// Create a copy of LegacyChildProfileItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = null,Object? address = null,Object? createdAt = null,Object? updatedAt = freezed,Object? profileImageId = freezed,}) { + return _then(_LegacyChildProfileItemResponseModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?,profileImageId: freezed == profileImageId ? _self.profileImageId : profileImageId // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.g.dart new file mode 100644 index 00000000..719be6cb --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/child_profile_response_model.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'child_profile_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacyChildProfileResponseModel _$LegacyChildProfileResponseModelFromJson( + Map json, +) => _LegacyChildProfileResponseModel( + isCreated: json['isCreated'] as bool, + item: LegacyChildProfileItemResponseModel.fromJson( + json['item'] as Map, + ), +); + +Map _$LegacyChildProfileResponseModelToJson( + _LegacyChildProfileResponseModel instance, +) => {'isCreated': instance.isCreated, 'item': instance.item}; + +_LegacyChildProfileItemResponseModel +_$LegacyChildProfileItemResponseModelFromJson(Map json) => + _LegacyChildProfileItemResponseModel( + id: json['id'] as String, + deviceIdentificator: json['deviceIdentificator'] as String, + parentId: json['parentId'] as String, + firstName: json['firstName'] as String, + lastName: json['lastName'] as String, + bornAt: (json['bornAt'] as num).toInt(), + address: json['address'] as String, + createdAt: (json['createdAt'] as num).toInt(), + updatedAt: (json['updatedAt'] as num?)?.toInt(), + profileImageId: json['profileImageId'] as String?, + ); + +Map _$LegacyChildProfileItemResponseModelToJson( + _LegacyChildProfileItemResponseModel instance, +) => { + 'id': instance.id, + 'deviceIdentificator': instance.deviceIdentificator, + 'parentId': instance.parentId, + 'firstName': instance.firstName, + 'lastName': instance.lastName, + 'bornAt': instance.bornAt, + 'address': instance.address, + 'createdAt': instance.createdAt, + 'updatedAt': instance.updatedAt, + 'profileImageId': instance.profileImageId, +}; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.dart new file mode 100644 index 00000000..4eadd125 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.dart @@ -0,0 +1,52 @@ +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'login_response_model.freezed.dart'; +part 'login_response_model.g.dart'; + +@freezed +abstract class LegacyLoginResponseModel with _$LegacyLoginResponseModel { + const factory LegacyLoginResponseModel({ + required String token, + @Default([]) + List availableMethods, + }) = _LegacyLoginResponseModel; + + factory LegacyLoginResponseModel.fromJson(Map json) => + _$LegacyLoginResponseModelFromJson(json); +} + +@freezed +abstract class LegacyAvailableMethodModel with _$LegacyAvailableMethodModel { + const factory LegacyAvailableMethodModel({ + required String id, + required String userId, + required String methodType, + required String status, + required bool isDefault, + required int createdAt, + }) = _LegacyAvailableMethodModel; + + factory LegacyAvailableMethodModel.fromJson(Map json) => + _$LegacyAvailableMethodModelFromJson(json); +} + +extension LegacyLoginResponseModelMapper on LegacyLoginResponseModel { + LegacyLoginResponseEntity toEntity() { + return LegacyLoginResponseEntity( + token: token, + availableMethods: availableMethods + .map( + (m) => LegacyAvailableMethodEntity( + id: m.id, + userId: m.userId, + methodType: m.methodType, + status: m.status, + isDefault: m.isDefault, + createdAt: m.createdAt, + ), + ) + .toList(), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.freezed.dart new file mode 100644 index 00000000..4a406b7c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.freezed.dart @@ -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 'login_response_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$LegacyLoginResponseModel { + + String get token; List get availableMethods; +/// Create a copy of LegacyLoginResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyLoginResponseModelCopyWith get copyWith => _$LegacyLoginResponseModelCopyWithImpl(this as LegacyLoginResponseModel, _$identity); + + /// Serializes this LegacyLoginResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyLoginResponseModel&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other.availableMethods, availableMethods)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(availableMethods)); + +@override +String toString() { + return 'LegacyLoginResponseModel(token: $token, availableMethods: $availableMethods)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyLoginResponseModelCopyWith<$Res> { + factory $LegacyLoginResponseModelCopyWith(LegacyLoginResponseModel value, $Res Function(LegacyLoginResponseModel) _then) = _$LegacyLoginResponseModelCopyWithImpl; +@useResult +$Res call({ + String token, List availableMethods +}); + + + + +} +/// @nodoc +class _$LegacyLoginResponseModelCopyWithImpl<$Res> + implements $LegacyLoginResponseModelCopyWith<$Res> { + _$LegacyLoginResponseModelCopyWithImpl(this._self, this._then); + + final LegacyLoginResponseModel _self; + final $Res Function(LegacyLoginResponseModel) _then; + +/// Create a copy of LegacyLoginResponseModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? token = null,Object? availableMethods = null,}) { + return _then(_self.copyWith( +token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,availableMethods: null == availableMethods ? _self.availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyLoginResponseModel]. +extension LegacyLoginResponseModelPatterns on LegacyLoginResponseModel { +/// 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 Function( _LegacyLoginResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseModel() 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 Function( _LegacyLoginResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseModel(): +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? Function( _LegacyLoginResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseModel() 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 Function( String token, List availableMethods)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyLoginResponseModel() when $default != null: +return $default(_that.token,_that.availableMethods);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 Function( String token, List availableMethods) $default,) {final _that = this; +switch (_that) { +case _LegacyLoginResponseModel(): +return $default(_that.token,_that.availableMethods);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? Function( String token, List availableMethods)? $default,) {final _that = this; +switch (_that) { +case _LegacyLoginResponseModel() when $default != null: +return $default(_that.token,_that.availableMethods);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyLoginResponseModel implements LegacyLoginResponseModel { + const _LegacyLoginResponseModel({required this.token, final List availableMethods = const []}): _availableMethods = availableMethods; + factory _LegacyLoginResponseModel.fromJson(Map json) => _$LegacyLoginResponseModelFromJson(json); + +@override final String token; + final List _availableMethods; +@override@JsonKey() List get availableMethods { + if (_availableMethods is EqualUnmodifiableListView) return _availableMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_availableMethods); +} + + +/// Create a copy of LegacyLoginResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyLoginResponseModelCopyWith<_LegacyLoginResponseModel> get copyWith => __$LegacyLoginResponseModelCopyWithImpl<_LegacyLoginResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyLoginResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyLoginResponseModel&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other._availableMethods, _availableMethods)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(_availableMethods)); + +@override +String toString() { + return 'LegacyLoginResponseModel(token: $token, availableMethods: $availableMethods)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyLoginResponseModelCopyWith<$Res> implements $LegacyLoginResponseModelCopyWith<$Res> { + factory _$LegacyLoginResponseModelCopyWith(_LegacyLoginResponseModel value, $Res Function(_LegacyLoginResponseModel) _then) = __$LegacyLoginResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String token, List availableMethods +}); + + + + +} +/// @nodoc +class __$LegacyLoginResponseModelCopyWithImpl<$Res> + implements _$LegacyLoginResponseModelCopyWith<$Res> { + __$LegacyLoginResponseModelCopyWithImpl(this._self, this._then); + + final _LegacyLoginResponseModel _self; + final $Res Function(_LegacyLoginResponseModel) _then; + +/// Create a copy of LegacyLoginResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? token = null,Object? availableMethods = null,}) { + return _then(_LegacyLoginResponseModel( +token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,availableMethods: null == availableMethods ? _self._availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List, + )); +} + + +} + + +/// @nodoc +mixin _$LegacyAvailableMethodModel { + + String get id; String get userId; String get methodType; String get status; bool get isDefault; int get createdAt; +/// Create a copy of LegacyAvailableMethodModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyAvailableMethodModelCopyWith get copyWith => _$LegacyAvailableMethodModelCopyWithImpl(this as LegacyAvailableMethodModel, _$identity); + + /// Serializes this LegacyAvailableMethodModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyAvailableMethodModel&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.methodType, methodType) || other.methodType == methodType)&&(identical(other.status, status) || other.status == status)&&(identical(other.isDefault, isDefault) || other.isDefault == isDefault)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,userId,methodType,status,isDefault,createdAt); + +@override +String toString() { + return 'LegacyAvailableMethodModel(id: $id, userId: $userId, methodType: $methodType, status: $status, isDefault: $isDefault, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyAvailableMethodModelCopyWith<$Res> { + factory $LegacyAvailableMethodModelCopyWith(LegacyAvailableMethodModel value, $Res Function(LegacyAvailableMethodModel) _then) = _$LegacyAvailableMethodModelCopyWithImpl; +@useResult +$Res call({ + String id, String userId, String methodType, String status, bool isDefault, int createdAt +}); + + + + +} +/// @nodoc +class _$LegacyAvailableMethodModelCopyWithImpl<$Res> + implements $LegacyAvailableMethodModelCopyWith<$Res> { + _$LegacyAvailableMethodModelCopyWithImpl(this._self, this._then); + + final LegacyAvailableMethodModel _self; + final $Res Function(LegacyAvailableMethodModel) _then; + +/// Create a copy of LegacyAvailableMethodModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? userId = null,Object? methodType = null,Object? status = null,Object? isDefault = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,methodType: null == methodType ? _self.methodType : methodType // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as String,isDefault: null == isDefault ? _self.isDefault : isDefault // ignore: cast_nullable_to_non_nullable +as bool,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyAvailableMethodModel]. +extension LegacyAvailableMethodModelPatterns on LegacyAvailableMethodModel { +/// 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 Function( _LegacyAvailableMethodModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel() 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 Function( _LegacyAvailableMethodModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel(): +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? Function( _LegacyAvailableMethodModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel() 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 Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel() when $default != null: +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);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 Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt) $default,) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel(): +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);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? Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodModel() when $default != null: +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyAvailableMethodModel implements LegacyAvailableMethodModel { + const _LegacyAvailableMethodModel({required this.id, required this.userId, required this.methodType, required this.status, required this.isDefault, required this.createdAt}); + factory _LegacyAvailableMethodModel.fromJson(Map json) => _$LegacyAvailableMethodModelFromJson(json); + +@override final String id; +@override final String userId; +@override final String methodType; +@override final String status; +@override final bool isDefault; +@override final int createdAt; + +/// Create a copy of LegacyAvailableMethodModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyAvailableMethodModelCopyWith<_LegacyAvailableMethodModel> get copyWith => __$LegacyAvailableMethodModelCopyWithImpl<_LegacyAvailableMethodModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyAvailableMethodModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyAvailableMethodModel&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.methodType, methodType) || other.methodType == methodType)&&(identical(other.status, status) || other.status == status)&&(identical(other.isDefault, isDefault) || other.isDefault == isDefault)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,userId,methodType,status,isDefault,createdAt); + +@override +String toString() { + return 'LegacyAvailableMethodModel(id: $id, userId: $userId, methodType: $methodType, status: $status, isDefault: $isDefault, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyAvailableMethodModelCopyWith<$Res> implements $LegacyAvailableMethodModelCopyWith<$Res> { + factory _$LegacyAvailableMethodModelCopyWith(_LegacyAvailableMethodModel value, $Res Function(_LegacyAvailableMethodModel) _then) = __$LegacyAvailableMethodModelCopyWithImpl; +@override @useResult +$Res call({ + String id, String userId, String methodType, String status, bool isDefault, int createdAt +}); + + + + +} +/// @nodoc +class __$LegacyAvailableMethodModelCopyWithImpl<$Res> + implements _$LegacyAvailableMethodModelCopyWith<$Res> { + __$LegacyAvailableMethodModelCopyWithImpl(this._self, this._then); + + final _LegacyAvailableMethodModel _self; + final $Res Function(_LegacyAvailableMethodModel) _then; + +/// Create a copy of LegacyAvailableMethodModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? userId = null,Object? methodType = null,Object? status = null,Object? isDefault = null,Object? createdAt = null,}) { + return _then(_LegacyAvailableMethodModel( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,methodType: null == methodType ? _self.methodType : methodType // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as String,isDefault: null == isDefault ? _self.isDefault : isDefault // ignore: cast_nullable_to_non_nullable +as bool,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.g.dart new file mode 100644 index 00000000..f82ac2e9 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/login_response_model.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'login_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacyLoginResponseModel _$LegacyLoginResponseModelFromJson( + Map json, +) => _LegacyLoginResponseModel( + token: json['token'] as String, + availableMethods: + (json['availableMethods'] as List?) + ?.map( + (e) => + LegacyAvailableMethodModel.fromJson(e as Map), + ) + .toList() ?? + const [], +); + +Map _$LegacyLoginResponseModelToJson( + _LegacyLoginResponseModel instance, +) => { + 'token': instance.token, + 'availableMethods': instance.availableMethods, +}; + +_LegacyAvailableMethodModel _$LegacyAvailableMethodModelFromJson( + Map json, +) => _LegacyAvailableMethodModel( + id: json['id'] as String, + userId: json['userId'] as String, + methodType: json['methodType'] as String, + status: json['status'] as String, + isDefault: json['isDefault'] as bool, + createdAt: (json['createdAt'] as num).toInt(), +); + +Map _$LegacyAvailableMethodModelToJson( + _LegacyAvailableMethodModel instance, +) => { + 'id': instance.id, + 'userId': instance.userId, + 'methodType': instance.methodType, + 'status': instance.status, + 'isDefault': instance.isDefault, + 'createdAt': instance.createdAt, +}; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.dart new file mode 100644 index 00000000..c6104d8b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.dart @@ -0,0 +1,50 @@ +import 'package:legacy_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 LegacySignUpRequestModel with _$LegacySignUpRequestModel { + const factory LegacySignUpRequestModel({ + required String firstName, + required String lastName, + required String email, + required String phone, + required String language, + required String password, + required List taxResidences, + required List addresses, + required int bornAt, + required String placeOfBirth, + required String birthCountry, + required String document, + required String documentType, + required String relationType, + }) = _LegacySignUpRequestModel; + + factory LegacySignUpRequestModel.fromJson(Map json) => + _$LegacySignUpRequestModelFromJson(json); +} + +extension LegacySignUpRequestModelMapper on LegacySignUpRequestEntity { + LegacySignUpRequestModel toModel() => LegacySignUpRequestModel( + 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, + placeOfBirth: placeOfBirth, + birthCountry: birthCountry, + document: document, + documentType: documentType, + relationType: relationType, + ); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.freezed.dart new file mode 100644 index 00000000..da67d618 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.freezed.dart @@ -0,0 +1,328 @@ +// 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 value) => value; + +/// @nodoc +mixin _$LegacySignUpRequestModel { + + String get firstName; String get lastName; String get email; String get phone; String get language; String get password; List get taxResidences; List get addresses; int get bornAt; String get placeOfBirth; String get birthCountry; String get document; String get documentType; String get relationType; +/// Create a copy of LegacySignUpRequestModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpRequestModelCopyWith get copyWith => _$LegacySignUpRequestModelCopyWithImpl(this as LegacySignUpRequestModel, _$identity); + + /// Serializes this LegacySignUpRequestModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpRequestModel&&(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.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.document, document) || other.document == document)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.relationType, relationType) || other.relationType == relationType)); +} + +@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,placeOfBirth,birthCountry,document,documentType,relationType); + +@override +String toString() { + return 'LegacySignUpRequestModel(firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, document: $document, documentType: $documentType, relationType: $relationType)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpRequestModelCopyWith<$Res> { + factory $LegacySignUpRequestModelCopyWith(LegacySignUpRequestModel value, $Res Function(LegacySignUpRequestModel) _then) = _$LegacySignUpRequestModelCopyWithImpl; +@useResult +$Res call({ + String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry, String document, String documentType, String relationType +}); + + + + +} +/// @nodoc +class _$LegacySignUpRequestModelCopyWithImpl<$Res> + implements $LegacySignUpRequestModelCopyWith<$Res> { + _$LegacySignUpRequestModelCopyWithImpl(this._self, this._then); + + final LegacySignUpRequestModel _self; + final $Res Function(LegacySignUpRequestModel) _then; + +/// Create a copy of LegacySignUpRequestModel +/// 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? placeOfBirth = null,Object? birthCountry = null,Object? document = null,Object? documentType = null,Object? relationType = 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,addresses: null == addresses ? _self.addresses : addresses // ignore: cast_nullable_to_non_nullable +as List,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,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,document: null == document ? _self.document : document // ignore: cast_nullable_to_non_nullable +as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacySignUpRequestModel]. +extension LegacySignUpRequestModelPatterns on LegacySignUpRequestModel { +/// 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 Function( _LegacySignUpRequestModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestModel() 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 Function( _LegacySignUpRequestModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestModel(): +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? Function( _LegacySignUpRequestModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestModel() 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 Function( String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry, String document, String documentType, String relationType)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpRequestModel() when $default != null: +return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.placeOfBirth,_that.birthCountry,_that.document,_that.documentType,_that.relationType);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 Function( String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry, String document, String documentType, String relationType) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpRequestModel(): +return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.placeOfBirth,_that.birthCountry,_that.document,_that.documentType,_that.relationType);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? Function( String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry, String document, String documentType, String relationType)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpRequestModel() when $default != null: +return $default(_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.placeOfBirth,_that.birthCountry,_that.document,_that.documentType,_that.relationType);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacySignUpRequestModel implements LegacySignUpRequestModel { + const _LegacySignUpRequestModel({required this.firstName, required this.lastName, required this.email, required this.phone, required this.language, required this.password, required final List taxResidences, required final List addresses, required this.bornAt, required this.placeOfBirth, required this.birthCountry, required this.document, required this.documentType, required this.relationType}): _taxResidences = taxResidences,_addresses = addresses; + factory _LegacySignUpRequestModel.fromJson(Map json) => _$LegacySignUpRequestModelFromJson(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 _taxResidences; +@override List get taxResidences { + if (_taxResidences is EqualUnmodifiableListView) return _taxResidences; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_taxResidences); +} + + final List _addresses; +@override List get addresses { + if (_addresses is EqualUnmodifiableListView) return _addresses; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_addresses); +} + +@override final int bornAt; +@override final String placeOfBirth; +@override final String birthCountry; +@override final String document; +@override final String documentType; +@override final String relationType; + +/// Create a copy of LegacySignUpRequestModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpRequestModelCopyWith<_LegacySignUpRequestModel> get copyWith => __$LegacySignUpRequestModelCopyWithImpl<_LegacySignUpRequestModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacySignUpRequestModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpRequestModel&&(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.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)&&(identical(other.document, document) || other.document == document)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.relationType, relationType) || other.relationType == relationType)); +} + +@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,placeOfBirth,birthCountry,document,documentType,relationType); + +@override +String toString() { + return 'LegacySignUpRequestModel(firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, document: $document, documentType: $documentType, relationType: $relationType)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpRequestModelCopyWith<$Res> implements $LegacySignUpRequestModelCopyWith<$Res> { + factory _$LegacySignUpRequestModelCopyWith(_LegacySignUpRequestModel value, $Res Function(_LegacySignUpRequestModel) _then) = __$LegacySignUpRequestModelCopyWithImpl; +@override @useResult +$Res call({ + String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry, String document, String documentType, String relationType +}); + + + + +} +/// @nodoc +class __$LegacySignUpRequestModelCopyWithImpl<$Res> + implements _$LegacySignUpRequestModelCopyWith<$Res> { + __$LegacySignUpRequestModelCopyWithImpl(this._self, this._then); + + final _LegacySignUpRequestModel _self; + final $Res Function(_LegacySignUpRequestModel) _then; + +/// Create a copy of LegacySignUpRequestModel +/// 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? placeOfBirth = null,Object? birthCountry = null,Object? document = null,Object? documentType = null,Object? relationType = null,}) { + return _then(_LegacySignUpRequestModel( +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,addresses: null == addresses ? _self._addresses : addresses // ignore: cast_nullable_to_non_nullable +as List,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,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,document: null == document ? _self.document : document // ignore: cast_nullable_to_non_nullable +as String,documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.g.dart new file mode 100644 index 00000000..db666dc0 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_request_model.g.dart @@ -0,0 +1,49 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sign_up_request_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacySignUpRequestModel _$LegacySignUpRequestModelFromJson( + Map json, +) => _LegacySignUpRequestModel( + 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) + .map((e) => LegacyAddressModel.fromJson(e as Map)) + .toList(), + addresses: (json['addresses'] as List) + .map((e) => LegacyAddressModel.fromJson(e as Map)) + .toList(), + bornAt: (json['bornAt'] as num).toInt(), + placeOfBirth: json['placeOfBirth'] as String, + birthCountry: json['birthCountry'] as String, + document: json['document'] as String, + documentType: json['documentType'] as String, + relationType: json['relationType'] as String, +); + +Map _$LegacySignUpRequestModelToJson( + _LegacySignUpRequestModel instance, +) => { + '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, + 'placeOfBirth': instance.placeOfBirth, + 'birthCountry': instance.birthCountry, + 'document': instance.document, + 'documentType': instance.documentType, + 'relationType': instance.relationType, +}; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.dart new file mode 100644 index 00000000..15f0ccb1 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.dart @@ -0,0 +1,30 @@ +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'sign_up_response_model.freezed.dart'; +part 'sign_up_response_model.g.dart'; + +@freezed +abstract class LegacySignUpResponseModel with _$LegacySignUpResponseModel { + const factory LegacySignUpResponseModel({ + required bool isCreated, + required LegacySignUpResponseItemModel item, + }) = _LegacySignUpResponseModel; + + factory LegacySignUpResponseModel.fromJson(Map json) => + _$LegacySignUpResponseModelFromJson(json); +} + +@freezed +abstract class LegacySignUpResponseItemModel with _$LegacySignUpResponseItemModel { + const factory LegacySignUpResponseItemModel({required String userId}) = + _LegacySignUpResponseItemModel; + + factory LegacySignUpResponseItemModel.fromJson(Map json) => + _$LegacySignUpResponseItemModelFromJson(json); +} + +extension LegacySignUpResponseModelMapper on LegacySignUpResponseModel { + LegacySignUpResponseEntity toEntity() => + LegacySignUpResponseEntity(isCreated: isCreated, userId: item.userId); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.freezed.dart new file mode 100644 index 00000000..cea6f2a6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.freezed.dart @@ -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 value) => value; + +/// @nodoc +mixin _$LegacySignUpResponseModel { + + bool get isCreated; LegacySignUpResponseItemModel get item; +/// Create a copy of LegacySignUpResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpResponseModelCopyWith get copyWith => _$LegacySignUpResponseModelCopyWithImpl(this as LegacySignUpResponseModel, _$identity); + + /// Serializes this LegacySignUpResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpResponseModel&&(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 'LegacySignUpResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpResponseModelCopyWith<$Res> { + factory $LegacySignUpResponseModelCopyWith(LegacySignUpResponseModel value, $Res Function(LegacySignUpResponseModel) _then) = _$LegacySignUpResponseModelCopyWithImpl; +@useResult +$Res call({ + bool isCreated, LegacySignUpResponseItemModel item +}); + + +$LegacySignUpResponseItemModelCopyWith<$Res> get item; + +} +/// @nodoc +class _$LegacySignUpResponseModelCopyWithImpl<$Res> + implements $LegacySignUpResponseModelCopyWith<$Res> { + _$LegacySignUpResponseModelCopyWithImpl(this._self, this._then); + + final LegacySignUpResponseModel _self; + final $Res Function(LegacySignUpResponseModel) _then; + +/// Create a copy of LegacySignUpResponseModel +/// 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 LegacySignUpResponseItemModel, + )); +} +/// Create a copy of LegacySignUpResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacySignUpResponseItemModelCopyWith<$Res> get item { + + return $LegacySignUpResponseItemModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacySignUpResponseModel]. +extension LegacySignUpResponseModelPatterns on LegacySignUpResponseModel { +/// 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 Function( _LegacySignUpResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseModel() 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 Function( _LegacySignUpResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseModel(): +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? Function( _LegacySignUpResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseModel() 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 Function( bool isCreated, LegacySignUpResponseItemModel item)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpResponseModel() 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 Function( bool isCreated, LegacySignUpResponseItemModel item) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseModel(): +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? Function( bool isCreated, LegacySignUpResponseItemModel item)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseModel() when $default != null: +return $default(_that.isCreated,_that.item);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacySignUpResponseModel implements LegacySignUpResponseModel { + const _LegacySignUpResponseModel({required this.isCreated, required this.item}); + factory _LegacySignUpResponseModel.fromJson(Map json) => _$LegacySignUpResponseModelFromJson(json); + +@override final bool isCreated; +@override final LegacySignUpResponseItemModel item; + +/// Create a copy of LegacySignUpResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpResponseModelCopyWith<_LegacySignUpResponseModel> get copyWith => __$LegacySignUpResponseModelCopyWithImpl<_LegacySignUpResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacySignUpResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpResponseModel&&(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 'LegacySignUpResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpResponseModelCopyWith<$Res> implements $LegacySignUpResponseModelCopyWith<$Res> { + factory _$LegacySignUpResponseModelCopyWith(_LegacySignUpResponseModel value, $Res Function(_LegacySignUpResponseModel) _then) = __$LegacySignUpResponseModelCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, LegacySignUpResponseItemModel item +}); + + +@override $LegacySignUpResponseItemModelCopyWith<$Res> get item; + +} +/// @nodoc +class __$LegacySignUpResponseModelCopyWithImpl<$Res> + implements _$LegacySignUpResponseModelCopyWith<$Res> { + __$LegacySignUpResponseModelCopyWithImpl(this._self, this._then); + + final _LegacySignUpResponseModel _self; + final $Res Function(_LegacySignUpResponseModel) _then; + +/// Create a copy of LegacySignUpResponseModel +/// 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(_LegacySignUpResponseModel( +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 LegacySignUpResponseItemModel, + )); +} + +/// Create a copy of LegacySignUpResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacySignUpResponseItemModelCopyWith<$Res> get item { + + return $LegacySignUpResponseItemModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// @nodoc +mixin _$LegacySignUpResponseItemModel { + + String get userId; +/// Create a copy of LegacySignUpResponseItemModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpResponseItemModelCopyWith get copyWith => _$LegacySignUpResponseItemModelCopyWithImpl(this as LegacySignUpResponseItemModel, _$identity); + + /// Serializes this LegacySignUpResponseItemModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpResponseItemModel&&(identical(other.userId, userId) || other.userId == userId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,userId); + +@override +String toString() { + return 'LegacySignUpResponseItemModel(userId: $userId)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpResponseItemModelCopyWith<$Res> { + factory $LegacySignUpResponseItemModelCopyWith(LegacySignUpResponseItemModel value, $Res Function(LegacySignUpResponseItemModel) _then) = _$LegacySignUpResponseItemModelCopyWithImpl; +@useResult +$Res call({ + String userId +}); + + + + +} +/// @nodoc +class _$LegacySignUpResponseItemModelCopyWithImpl<$Res> + implements $LegacySignUpResponseItemModelCopyWith<$Res> { + _$LegacySignUpResponseItemModelCopyWithImpl(this._self, this._then); + + final LegacySignUpResponseItemModel _self; + final $Res Function(LegacySignUpResponseItemModel) _then; + +/// Create a copy of LegacySignUpResponseItemModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? userId = null,}) { + return _then(_self.copyWith( +userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacySignUpResponseItemModel]. +extension LegacySignUpResponseItemModelPatterns on LegacySignUpResponseItemModel { +/// 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 Function( _LegacySignUpResponseItemModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel() 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 Function( _LegacySignUpResponseItemModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel(): +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? Function( _LegacySignUpResponseItemModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel() 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 Function( String userId)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel() when $default != null: +return $default(_that.userId);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 Function( String userId) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel(): +return $default(_that.userId);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? Function( String userId)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseItemModel() when $default != null: +return $default(_that.userId);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacySignUpResponseItemModel implements LegacySignUpResponseItemModel { + const _LegacySignUpResponseItemModel({required this.userId}); + factory _LegacySignUpResponseItemModel.fromJson(Map json) => _$LegacySignUpResponseItemModelFromJson(json); + +@override final String userId; + +/// Create a copy of LegacySignUpResponseItemModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpResponseItemModelCopyWith<_LegacySignUpResponseItemModel> get copyWith => __$LegacySignUpResponseItemModelCopyWithImpl<_LegacySignUpResponseItemModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacySignUpResponseItemModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpResponseItemModel&&(identical(other.userId, userId) || other.userId == userId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,userId); + +@override +String toString() { + return 'LegacySignUpResponseItemModel(userId: $userId)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpResponseItemModelCopyWith<$Res> implements $LegacySignUpResponseItemModelCopyWith<$Res> { + factory _$LegacySignUpResponseItemModelCopyWith(_LegacySignUpResponseItemModel value, $Res Function(_LegacySignUpResponseItemModel) _then) = __$LegacySignUpResponseItemModelCopyWithImpl; +@override @useResult +$Res call({ + String userId +}); + + + + +} +/// @nodoc +class __$LegacySignUpResponseItemModelCopyWithImpl<$Res> + implements _$LegacySignUpResponseItemModelCopyWith<$Res> { + __$LegacySignUpResponseItemModelCopyWithImpl(this._self, this._then); + + final _LegacySignUpResponseItemModel _self; + final $Res Function(_LegacySignUpResponseItemModel) _then; + +/// Create a copy of LegacySignUpResponseItemModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? userId = null,}) { + return _then(_LegacySignUpResponseItemModel( +userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.g.dart new file mode 100644 index 00000000..e3d716e7 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/sign_up_response_model.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sign_up_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacySignUpResponseModel _$LegacySignUpResponseModelFromJson( + Map json, +) => _LegacySignUpResponseModel( + isCreated: json['isCreated'] as bool, + item: LegacySignUpResponseItemModel.fromJson( + json['item'] as Map, + ), +); + +Map _$LegacySignUpResponseModelToJson( + _LegacySignUpResponseModel instance, +) => {'isCreated': instance.isCreated, 'item': instance.item}; + +_LegacySignUpResponseItemModel _$LegacySignUpResponseItemModelFromJson( + Map json, +) => _LegacySignUpResponseItemModel(userId: json['userId'] as String); + +Map _$LegacySignUpResponseItemModelToJson( + _LegacySignUpResponseItemModel instance, +) => {'userId': instance.userId}; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.dart new file mode 100644 index 00000000..b94d4501 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.dart @@ -0,0 +1,37 @@ +import 'package:legacy_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 LegacyTwoFASecretResponseModel with _$LegacyTwoFASecretResponseModel { + const factory LegacyTwoFASecretResponseModel({ + required bool isCreated, + required LegacyTwoFASecretItemResponseModel item, + }) = _LegacyTwoFASecretResponseModel; + + factory LegacyTwoFASecretResponseModel.fromJson(Map json) => + _$LegacyTwoFASecretResponseModelFromJson(json); +} + +@freezed +abstract class LegacyTwoFASecretItemResponseModel + with _$LegacyTwoFASecretItemResponseModel { + const factory LegacyTwoFASecretItemResponseModel({ + required String secret, + required String qr, + }) = _LegacyTwoFASecretItemResponseModel; + + factory LegacyTwoFASecretItemResponseModel.fromJson(Map json) => + _$LegacyTwoFASecretItemResponseModelFromJson(json); +} + +extension LegacyTwoFASecretResponseModelMapper on LegacyTwoFASecretResponseModel { + LegacyTwoFASecretEntity toEntity() { + return LegacyTwoFASecretEntity( + isCreated: isCreated, + item: LegacyTwoFASecretItemEntity(secret: item.secret, qr: item.qr), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.freezed.dart new file mode 100644 index 00000000..e3c33e20 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.freezed.dart @@ -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 value) => value; + +/// @nodoc +mixin _$LegacyTwoFASecretResponseModel { + + bool get isCreated; LegacyTwoFASecretItemResponseModel get item; +/// Create a copy of LegacyTwoFASecretResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyTwoFASecretResponseModelCopyWith get copyWith => _$LegacyTwoFASecretResponseModelCopyWithImpl(this as LegacyTwoFASecretResponseModel, _$identity); + + /// Serializes this LegacyTwoFASecretResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyTwoFASecretResponseModel&&(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 'LegacyTwoFASecretResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyTwoFASecretResponseModelCopyWith<$Res> { + factory $LegacyTwoFASecretResponseModelCopyWith(LegacyTwoFASecretResponseModel value, $Res Function(LegacyTwoFASecretResponseModel) _then) = _$LegacyTwoFASecretResponseModelCopyWithImpl; +@useResult +$Res call({ + bool isCreated, LegacyTwoFASecretItemResponseModel item +}); + + +$LegacyTwoFASecretItemResponseModelCopyWith<$Res> get item; + +} +/// @nodoc +class _$LegacyTwoFASecretResponseModelCopyWithImpl<$Res> + implements $LegacyTwoFASecretResponseModelCopyWith<$Res> { + _$LegacyTwoFASecretResponseModelCopyWithImpl(this._self, this._then); + + final LegacyTwoFASecretResponseModel _self; + final $Res Function(LegacyTwoFASecretResponseModel) _then; + +/// Create a copy of LegacyTwoFASecretResponseModel +/// 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 LegacyTwoFASecretItemResponseModel, + )); +} +/// Create a copy of LegacyTwoFASecretResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemResponseModelCopyWith<$Res> get item { + + return $LegacyTwoFASecretItemResponseModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacyTwoFASecretResponseModel]. +extension LegacyTwoFASecretResponseModelPatterns on LegacyTwoFASecretResponseModel { +/// 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 Function( _LegacyTwoFASecretResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel() 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 Function( _LegacyTwoFASecretResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel(): +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? Function( _LegacyTwoFASecretResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel() 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 Function( bool isCreated, LegacyTwoFASecretItemResponseModel item)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel() 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 Function( bool isCreated, LegacyTwoFASecretItemResponseModel item) $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel(): +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? Function( bool isCreated, LegacyTwoFASecretItemResponseModel item)? $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretResponseModel() when $default != null: +return $default(_that.isCreated,_that.item);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyTwoFASecretResponseModel implements LegacyTwoFASecretResponseModel { + const _LegacyTwoFASecretResponseModel({required this.isCreated, required this.item}); + factory _LegacyTwoFASecretResponseModel.fromJson(Map json) => _$LegacyTwoFASecretResponseModelFromJson(json); + +@override final bool isCreated; +@override final LegacyTwoFASecretItemResponseModel item; + +/// Create a copy of LegacyTwoFASecretResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyTwoFASecretResponseModelCopyWith<_LegacyTwoFASecretResponseModel> get copyWith => __$LegacyTwoFASecretResponseModelCopyWithImpl<_LegacyTwoFASecretResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyTwoFASecretResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyTwoFASecretResponseModel&&(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 'LegacyTwoFASecretResponseModel(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyTwoFASecretResponseModelCopyWith<$Res> implements $LegacyTwoFASecretResponseModelCopyWith<$Res> { + factory _$LegacyTwoFASecretResponseModelCopyWith(_LegacyTwoFASecretResponseModel value, $Res Function(_LegacyTwoFASecretResponseModel) _then) = __$LegacyTwoFASecretResponseModelCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, LegacyTwoFASecretItemResponseModel item +}); + + +@override $LegacyTwoFASecretItemResponseModelCopyWith<$Res> get item; + +} +/// @nodoc +class __$LegacyTwoFASecretResponseModelCopyWithImpl<$Res> + implements _$LegacyTwoFASecretResponseModelCopyWith<$Res> { + __$LegacyTwoFASecretResponseModelCopyWithImpl(this._self, this._then); + + final _LegacyTwoFASecretResponseModel _self; + final $Res Function(_LegacyTwoFASecretResponseModel) _then; + +/// Create a copy of LegacyTwoFASecretResponseModel +/// 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(_LegacyTwoFASecretResponseModel( +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 LegacyTwoFASecretItemResponseModel, + )); +} + +/// Create a copy of LegacyTwoFASecretResponseModel +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemResponseModelCopyWith<$Res> get item { + + return $LegacyTwoFASecretItemResponseModelCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// @nodoc +mixin _$LegacyTwoFASecretItemResponseModel { + + String get secret; String get qr; +/// Create a copy of LegacyTwoFASecretItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemResponseModelCopyWith get copyWith => _$LegacyTwoFASecretItemResponseModelCopyWithImpl(this as LegacyTwoFASecretItemResponseModel, _$identity); + + /// Serializes this LegacyTwoFASecretItemResponseModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyTwoFASecretItemResponseModel&&(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 'LegacyTwoFASecretItemResponseModel(secret: $secret, qr: $qr)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyTwoFASecretItemResponseModelCopyWith<$Res> { + factory $LegacyTwoFASecretItemResponseModelCopyWith(LegacyTwoFASecretItemResponseModel value, $Res Function(LegacyTwoFASecretItemResponseModel) _then) = _$LegacyTwoFASecretItemResponseModelCopyWithImpl; +@useResult +$Res call({ + String secret, String qr +}); + + + + +} +/// @nodoc +class _$LegacyTwoFASecretItemResponseModelCopyWithImpl<$Res> + implements $LegacyTwoFASecretItemResponseModelCopyWith<$Res> { + _$LegacyTwoFASecretItemResponseModelCopyWithImpl(this._self, this._then); + + final LegacyTwoFASecretItemResponseModel _self; + final $Res Function(LegacyTwoFASecretItemResponseModel) _then; + +/// Create a copy of LegacyTwoFASecretItemResponseModel +/// 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 [LegacyTwoFASecretItemResponseModel]. +extension LegacyTwoFASecretItemResponseModelPatterns on LegacyTwoFASecretItemResponseModel { +/// 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 Function( _LegacyTwoFASecretItemResponseModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel() 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 Function( _LegacyTwoFASecretItemResponseModel value) $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel(): +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? Function( _LegacyTwoFASecretItemResponseModel value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel() 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 Function( String secret, String qr)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel() 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 Function( String secret, String qr) $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel(): +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? Function( String secret, String qr)? $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemResponseModel() when $default != null: +return $default(_that.secret,_that.qr);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _LegacyTwoFASecretItemResponseModel implements LegacyTwoFASecretItemResponseModel { + const _LegacyTwoFASecretItemResponseModel({required this.secret, required this.qr}); + factory _LegacyTwoFASecretItemResponseModel.fromJson(Map json) => _$LegacyTwoFASecretItemResponseModelFromJson(json); + +@override final String secret; +@override final String qr; + +/// Create a copy of LegacyTwoFASecretItemResponseModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyTwoFASecretItemResponseModelCopyWith<_LegacyTwoFASecretItemResponseModel> get copyWith => __$LegacyTwoFASecretItemResponseModelCopyWithImpl<_LegacyTwoFASecretItemResponseModel>(this, _$identity); + +@override +Map toJson() { + return _$LegacyTwoFASecretItemResponseModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyTwoFASecretItemResponseModel&&(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 'LegacyTwoFASecretItemResponseModel(secret: $secret, qr: $qr)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyTwoFASecretItemResponseModelCopyWith<$Res> implements $LegacyTwoFASecretItemResponseModelCopyWith<$Res> { + factory _$LegacyTwoFASecretItemResponseModelCopyWith(_LegacyTwoFASecretItemResponseModel value, $Res Function(_LegacyTwoFASecretItemResponseModel) _then) = __$LegacyTwoFASecretItemResponseModelCopyWithImpl; +@override @useResult +$Res call({ + String secret, String qr +}); + + + + +} +/// @nodoc +class __$LegacyTwoFASecretItemResponseModelCopyWithImpl<$Res> + implements _$LegacyTwoFASecretItemResponseModelCopyWith<$Res> { + __$LegacyTwoFASecretItemResponseModelCopyWithImpl(this._self, this._then); + + final _LegacyTwoFASecretItemResponseModel _self; + final $Res Function(_LegacyTwoFASecretItemResponseModel) _then; + +/// Create a copy of LegacyTwoFASecretItemResponseModel +/// 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(_LegacyTwoFASecretItemResponseModel( +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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.g.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.g.dart new file mode 100644 index 00000000..08dd394d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/models/two_fa_secret_response_model.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'two_fa_secret_response_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_LegacyTwoFASecretResponseModel _$LegacyTwoFASecretResponseModelFromJson( + Map json, +) => _LegacyTwoFASecretResponseModel( + isCreated: json['isCreated'] as bool, + item: LegacyTwoFASecretItemResponseModel.fromJson( + json['item'] as Map, + ), +); + +Map _$LegacyTwoFASecretResponseModelToJson( + _LegacyTwoFASecretResponseModel instance, +) => {'isCreated': instance.isCreated, 'item': instance.item}; + +_LegacyTwoFASecretItemResponseModel +_$LegacyTwoFASecretItemResponseModelFromJson(Map json) => + _LegacyTwoFASecretItemResponseModel( + secret: json['secret'] as String, + qr: json['qr'] as String, + ); + +Map _$LegacyTwoFASecretItemResponseModelToJson( + _LegacyTwoFASecretItemResponseModel instance, +) => {'secret': instance.secret, 'qr': instance.qr}; diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/data/repositories/auth_repository_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/core/data/repositories/auth_repository_impl.dart new file mode 100644 index 00000000..7bbe43f1 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/data/repositories/auth_repository_impl.dart @@ -0,0 +1,160 @@ +import 'package:legacy_auth/src/core/data/datasource/auth_remote_datasource.dart'; +import 'package:legacy_auth/src/core/data/models/child_profile_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_request_model.dart'; +import 'package:legacy_auth/src/core/data/models/sign_up_response_model.dart'; +import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart'; +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/entities/child_profile_entity.dart'; +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; +import 'package:legacy_auth/src/core/data/models/login_response_model.dart'; + +class LegacyAuthRepositoryImpl implements LegacyAuthRepository { + const LegacyAuthRepositoryImpl(this._remote); + + final LegacyAuthRemoteDatasource _remote; + + @override + Future requestPhoneCode({required String phone}) { + return _remote.requestPhoneCode(phone: phone); + } + + @override + Future verifyPhoneCode({required String phone, required String code}) { + return _remote.verifyPhoneCode(phone: phone, code: code); + } + + @override + Future login({ + required String email, + required String password, + }) async { + final responseModel = await _remote.login(email: email, password: password); + + return LegacyLoginResponseModelMapper(responseModel).toEntity(); + } + + @override + Future twoFARequestCode({ + required String token, + required String methodType, + }) { + return _remote.twoFARequestCode(token: token, methodType: methodType); + } + + @override + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }) { + return _remote.twoFASendCode( + token: token, + code: code, + methodType: methodType, + ); + } + + // @override + // Future totpLogin({required String token, required String code}) { + // return _remote.totpLogin(token: token, code: code); + // } + + @override + Future signUp({ + required LegacySignUpRequestEntity request, + }) async { + final model = request.toModel(); + final responseModel = await _remote.signUp(request: model); + return responseModel.toEntity(); + } + + @override + Future generateTwoFASignUp({ + required String token, + }) { + return _remote.generateTwoFASignUp(token: token); + } + + @override + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }) { + return _remote.verifyTwoFACodeSignUp(token: token, code: code); + } + + @override + Future requestPasswordReset({required String email}) { + return _remote.requestPasswordReset(email: email); + } + + @override + Future recoverPassword({ + required String newPassword, + required String token, + }) { + return _remote.recoverPassword(newPassword: newPassword, token: token); + } + + @override + Future logout() { + return _remote.logout(); + } + + @override + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }) async { + final model = await _remote.createChildProfile( + id: id, + parentId: parentId, + firstName: firstName, + lastName: lastName, + bornAt: bornAt, + genrer: genrer, + relationType: relationType, + address: address, + cardPublicKey: cardPublicKey, + deviceActivationCode: deviceActivationCode, + scaProof: scaProof, + ); + + if (!model.isCreated) { + throw Exception('Child profile creation failed: isCreated=false'); + } + + return model.toEntity(); + } +} + +extension LegacyLoginResponseModelMapper on LegacyLoginResponseModel { + LegacyLoginResponseEntity toEntity() { + return LegacyLoginResponseEntity( + token: token, + availableMethods: availableMethods + .map( + (m) => LegacyAvailableMethodEntity( + id: m.id, + userId: m.userId, + methodType: m.methodType, + status: m.status, + isDefault: m.isDefault, + createdAt: m.createdAt, + ), + ) + .toList(), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/domain/repositories/auth_repository.dart b/modules/legacy/modules/legacy_auth/lib/src/core/domain/repositories/auth_repository.dart new file mode 100644 index 00000000..4adb66ea --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/domain/repositories/auth_repository.dart @@ -0,0 +1,57 @@ +import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/entities/child_profile_entity.dart'; +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; + +abstract class LegacyAuthRepository { + Future requestPhoneCode({required String phone}); + + Future verifyPhoneCode({required String phone, required String code}); + + Future login({ + required String email, + required String password, + }); + Future twoFARequestCode({ + required String token, + required String methodType, + }); + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }); + + Future signUp({required LegacySignUpRequestEntity request}); + + Future generateTwoFASignUp({required String token}); + + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }); + + Future requestPasswordReset({required String email}); + + Future recoverPassword({ + required String newPassword, + required String token, + }); + + Future logout(); + + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_remote_datasource_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_remote_datasource_provider.dart new file mode 100644 index 00000000..992b128b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_remote_datasource_provider.dart @@ -0,0 +1,9 @@ +import 'package:legacy_auth/src/core/data/datasource/auth_remote_datasource.dart'; +import 'package:legacy_auth/src/core/data/datasource/auth_remote_datasource_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_infrastructure/sf_infrastructure.dart'; + +final legacyAuthRemoteDatasourceProvider = Provider((ref) { + final questiaRepository = getIt(); + return LegacyAuthRemoteDatasourceImpl(questiaRepository); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_repository_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_repository_provider.dart new file mode 100644 index 00000000..dae7525d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/providers/auth_repository_provider.dart @@ -0,0 +1,9 @@ +import 'package:legacy_auth/src/core/data/repositories/auth_repository_impl.dart'; +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/core/providers/auth_remote_datasource_provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyAuthRepositoryProvider = Provider((ref) { + final remote = ref.read(legacyAuthRemoteDatasourceProvider); + return LegacyAuthRepositoryImpl(remote); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/core/providers/session_local_datasource_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/core/providers/session_local_datasource_provider.dart new file mode 100644 index 00000000..bca73e7f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/core/providers/session_local_datasource_provider.dart @@ -0,0 +1,7 @@ +import 'package:legacy_auth/src/core/data/datasource/session_local_datasource.dart'; +import 'package:legacy_auth/src/core/data/datasource/session_local_datasource_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacySessionLocalDatasourceProvider = Provider((ref) { + return LegacySessionLocalDatasourceImpl(); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/device_setup_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/device_setup_builder.dart new file mode 100644 index 00000000..03890be7 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/device_setup_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/device_setup_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:go_router/go_router.dart'; +import 'package:navigation/navigation.dart'; + +class LegacyDeviceSetupBuilder { + const LegacyDeviceSetupBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyDeviceSetupScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case.dart new file mode 100644 index 00000000..3a7afbbf --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case.dart @@ -0,0 +1,17 @@ +import 'package:legacy_auth/src/features/device_setup/domain/entities/child_profile_entity.dart'; + +abstract class LegacyCreateChildProfileUseCase { + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case_impl.dart new file mode 100644 index 00000000..24a2f7c9 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/create_child_profile_use_case_impl.dart @@ -0,0 +1,38 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/create_child_profile_use_case.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/entities/child_profile_entity.dart'; + +class LegacyCreateChildProfileUseCaseImpl implements LegacyCreateChildProfileUseCase { + LegacyCreateChildProfileUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future createChildProfile({ + required String id, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String genrer, + required String relationType, + required String address, + required String cardPublicKey, + required String deviceActivationCode, + required String scaProof, + }) { + return _repository.createChildProfile( + id: id, + parentId: parentId, + firstName: firstName, + lastName: lastName, + bornAt: bornAt, + genrer: genrer, + relationType: relationType, + address: address, + cardPublicKey: cardPublicKey, + deviceActivationCode: deviceActivationCode, + scaProof: scaProof, + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.dart new file mode 100644 index 00000000..1c51ff87 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.dart @@ -0,0 +1,27 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'child_profile_entity.freezed.dart'; + +@freezed +abstract class LegacyChildProfileEntity with _$LegacyChildProfileEntity { + const factory LegacyChildProfileEntity({ + required bool isCreated, + required LegacyChildProfileItemEntity item, + }) = _LegacyChildProfileEntity; +} + +@freezed +abstract class LegacyChildProfileItemEntity with _$LegacyChildProfileItemEntity { + const factory LegacyChildProfileItemEntity({ + required String id, + required String deviceIdentificator, + required String parentId, + required String firstName, + required String lastName, + required int bornAt, + required String address, + required int createdAt, + int? updatedAt, + String? profileImageId, + }) = _LegacyChildProfileItemEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.freezed.dart new file mode 100644 index 00000000..cad2b37f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/domain/entities/child_profile_entity.freezed.dart @@ -0,0 +1,576 @@ +// 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 'child_profile_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacyChildProfileEntity { + + bool get isCreated; LegacyChildProfileItemEntity get item; +/// Create a copy of LegacyChildProfileEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyChildProfileEntityCopyWith get copyWith => _$LegacyChildProfileEntityCopyWithImpl(this as LegacyChildProfileEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyChildProfileEntity&&(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 'LegacyChildProfileEntity(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyChildProfileEntityCopyWith<$Res> { + factory $LegacyChildProfileEntityCopyWith(LegacyChildProfileEntity value, $Res Function(LegacyChildProfileEntity) _then) = _$LegacyChildProfileEntityCopyWithImpl; +@useResult +$Res call({ + bool isCreated, LegacyChildProfileItemEntity item +}); + + +$LegacyChildProfileItemEntityCopyWith<$Res> get item; + +} +/// @nodoc +class _$LegacyChildProfileEntityCopyWithImpl<$Res> + implements $LegacyChildProfileEntityCopyWith<$Res> { + _$LegacyChildProfileEntityCopyWithImpl(this._self, this._then); + + final LegacyChildProfileEntity _self; + final $Res Function(LegacyChildProfileEntity) _then; + +/// Create a copy of LegacyChildProfileEntity +/// 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 LegacyChildProfileItemEntity, + )); +} +/// Create a copy of LegacyChildProfileEntity +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyChildProfileItemEntityCopyWith<$Res> get item { + + return $LegacyChildProfileItemEntityCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacyChildProfileEntity]. +extension LegacyChildProfileEntityPatterns on LegacyChildProfileEntity { +/// 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 Function( _LegacyChildProfileEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyChildProfileEntity() 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 Function( _LegacyChildProfileEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileEntity(): +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? Function( _LegacyChildProfileEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileEntity() 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 Function( bool isCreated, LegacyChildProfileItemEntity item)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyChildProfileEntity() 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 Function( bool isCreated, LegacyChildProfileItemEntity item) $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileEntity(): +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? Function( bool isCreated, LegacyChildProfileItemEntity item)? $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileEntity() when $default != null: +return $default(_that.isCreated,_that.item);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyChildProfileEntity implements LegacyChildProfileEntity { + const _LegacyChildProfileEntity({required this.isCreated, required this.item}); + + +@override final bool isCreated; +@override final LegacyChildProfileItemEntity item; + +/// Create a copy of LegacyChildProfileEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyChildProfileEntityCopyWith<_LegacyChildProfileEntity> get copyWith => __$LegacyChildProfileEntityCopyWithImpl<_LegacyChildProfileEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyChildProfileEntity&&(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 'LegacyChildProfileEntity(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyChildProfileEntityCopyWith<$Res> implements $LegacyChildProfileEntityCopyWith<$Res> { + factory _$LegacyChildProfileEntityCopyWith(_LegacyChildProfileEntity value, $Res Function(_LegacyChildProfileEntity) _then) = __$LegacyChildProfileEntityCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, LegacyChildProfileItemEntity item +}); + + +@override $LegacyChildProfileItemEntityCopyWith<$Res> get item; + +} +/// @nodoc +class __$LegacyChildProfileEntityCopyWithImpl<$Res> + implements _$LegacyChildProfileEntityCopyWith<$Res> { + __$LegacyChildProfileEntityCopyWithImpl(this._self, this._then); + + final _LegacyChildProfileEntity _self; + final $Res Function(_LegacyChildProfileEntity) _then; + +/// Create a copy of LegacyChildProfileEntity +/// 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(_LegacyChildProfileEntity( +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 LegacyChildProfileItemEntity, + )); +} + +/// Create a copy of LegacyChildProfileEntity +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyChildProfileItemEntityCopyWith<$Res> get item { + + return $LegacyChildProfileItemEntityCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + +/// @nodoc +mixin _$LegacyChildProfileItemEntity { + + String get id; String get deviceIdentificator; String get parentId; String get firstName; String get lastName; int get bornAt; String get address; int get createdAt; int? get updatedAt; String? get profileImageId; +/// Create a copy of LegacyChildProfileItemEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyChildProfileItemEntityCopyWith get copyWith => _$LegacyChildProfileItemEntityCopyWithImpl(this as LegacyChildProfileItemEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyChildProfileItemEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.profileImageId, profileImageId) || other.profileImageId == profileImageId)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,parentId,firstName,lastName,bornAt,address,createdAt,updatedAt,profileImageId); + +@override +String toString() { + return 'LegacyChildProfileItemEntity(id: $id, deviceIdentificator: $deviceIdentificator, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, createdAt: $createdAt, updatedAt: $updatedAt, profileImageId: $profileImageId)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyChildProfileItemEntityCopyWith<$Res> { + factory $LegacyChildProfileItemEntityCopyWith(LegacyChildProfileItemEntity value, $Res Function(LegacyChildProfileItemEntity) _then) = _$LegacyChildProfileItemEntityCopyWithImpl; +@useResult +$Res call({ + String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId +}); + + + + +} +/// @nodoc +class _$LegacyChildProfileItemEntityCopyWithImpl<$Res> + implements $LegacyChildProfileItemEntityCopyWith<$Res> { + _$LegacyChildProfileItemEntityCopyWithImpl(this._self, this._then); + + final LegacyChildProfileItemEntity _self; + final $Res Function(LegacyChildProfileItemEntity) _then; + +/// Create a copy of LegacyChildProfileItemEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = null,Object? address = null,Object? createdAt = null,Object? updatedAt = freezed,Object? profileImageId = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?,profileImageId: freezed == profileImageId ? _self.profileImageId : profileImageId // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyChildProfileItemEntity]. +extension LegacyChildProfileItemEntityPatterns on LegacyChildProfileItemEntity { +/// 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 Function( _LegacyChildProfileItemEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity() 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 Function( _LegacyChildProfileItemEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity(): +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? Function( _LegacyChildProfileItemEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity() 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 Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);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 Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId) $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity(): +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);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? Function( String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId)? $default,) {final _that = this; +switch (_that) { +case _LegacyChildProfileItemEntity() when $default != null: +return $default(_that.id,_that.deviceIdentificator,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.createdAt,_that.updatedAt,_that.profileImageId);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyChildProfileItemEntity implements LegacyChildProfileItemEntity { + const _LegacyChildProfileItemEntity({required this.id, required this.deviceIdentificator, required this.parentId, required this.firstName, required this.lastName, required this.bornAt, required this.address, required this.createdAt, this.updatedAt, this.profileImageId}); + + +@override final String id; +@override final String deviceIdentificator; +@override final String parentId; +@override final String firstName; +@override final String lastName; +@override final int bornAt; +@override final String address; +@override final int createdAt; +@override final int? updatedAt; +@override final String? profileImageId; + +/// Create a copy of LegacyChildProfileItemEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyChildProfileItemEntityCopyWith<_LegacyChildProfileItemEntity> get copyWith => __$LegacyChildProfileItemEntityCopyWithImpl<_LegacyChildProfileItemEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyChildProfileItemEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.profileImageId, profileImageId) || other.profileImageId == profileImageId)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,parentId,firstName,lastName,bornAt,address,createdAt,updatedAt,profileImageId); + +@override +String toString() { + return 'LegacyChildProfileItemEntity(id: $id, deviceIdentificator: $deviceIdentificator, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, createdAt: $createdAt, updatedAt: $updatedAt, profileImageId: $profileImageId)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyChildProfileItemEntityCopyWith<$Res> implements $LegacyChildProfileItemEntityCopyWith<$Res> { + factory _$LegacyChildProfileItemEntityCopyWith(_LegacyChildProfileItemEntity value, $Res Function(_LegacyChildProfileItemEntity) _then) = __$LegacyChildProfileItemEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String deviceIdentificator, String parentId, String firstName, String lastName, int bornAt, String address, int createdAt, int? updatedAt, String? profileImageId +}); + + + + +} +/// @nodoc +class __$LegacyChildProfileItemEntityCopyWithImpl<$Res> + implements _$LegacyChildProfileItemEntityCopyWith<$Res> { + __$LegacyChildProfileItemEntityCopyWithImpl(this._self, this._then); + + final _LegacyChildProfileItemEntity _self; + final $Res Function(_LegacyChildProfileItemEntity) _then; + +/// Create a copy of LegacyChildProfileItemEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = null,Object? address = null,Object? createdAt = null,Object? updatedAt = freezed,Object? profileImageId = freezed,}) { + return _then(_LegacyChildProfileItemEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable +as int?,profileImageId: freezed == profileImageId ? _self.profileImageId : profileImageId // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/add_kid_step_mapper.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/add_kid_step_mapper.dart new file mode 100644 index 00000000..9703832b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/add_kid_step_mapper.dart @@ -0,0 +1,19 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_main_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_step.dart'; + +extension LegacyAddKidStepMapper on LegacyAddKidStep { + LegacyAddKidMainStep get mainStep { + switch (this) { + case LegacyAddKidStep.linkInfo: + case LegacyAddKidStep.scanStrap: + case LegacyAddKidStep.scanWatch: + return LegacyAddKidMainStep.linkDevice; + case LegacyAddKidStep.profile: + return LegacyAddKidMainStep.profile; + case LegacyAddKidStep.allowance: + return LegacyAddKidMainStep.allowance; + case LegacyAddKidStep.intro: + return LegacyAddKidMainStep.linkDevice; + } + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/contact_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/contact_screen.dart new file mode 100644 index 00000000..77233326 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/contact_screen.dart @@ -0,0 +1,74 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class LegacyContactScreen extends ConsumerWidget { + const LegacyContactScreen({super.key}); + + @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: 10, + children: [ + Text( + "Contáctanos", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30), + ), + Text( + "Trasládanos tus dudas e intentaremos responderte lo antes posible", + ), + DropdownMenu( + initialSelection: "es", + label: Text("País"), + dropdownMenuEntries: [ + DropdownMenuEntry(value: "es", label: "España"), + DropdownMenuEntry(value: "fr", label: "Francia"), + DropdownMenuEntry(value: "pt", label: "Portugal"), + ], + ), + DropdownMenu( + initialSelection: "online", + label: Text("Canal de compra"), + dropdownMenuEntries: [ + DropdownMenuEntry(value: "online", label: "SF online shop"), + ], + ), + Expanded( + child: CustomTextField( + label: "Nombre", + hint: "Nombre y apellidos", + ), + ), + Expanded( + child: CustomTextField( + label: "Correo electrónico", + hint: "Correo electrónico", + ), + ), + Expanded( + child: CustomTextField( + lines: 3, + label: "Asunto del mensaje", + hint: "Escribe tu mensaje", + ), + ), + Expanded( + child: FilledButton( + onPressed: () => Navigator.pop(context), + child: Text("Enviar"), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart new file mode 100644 index 00000000..0bfdb938 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/device_setup_screen.dart @@ -0,0 +1,156 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/add_kid_step_mapper.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_model.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_main_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/step_body.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/success_screen.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/flow_footer.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:navigation/app_routes.dart'; +import 'package:navigation/navigation_contract.dart'; +import 'package:payments/payments.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyDeviceSetupScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyDeviceSetupScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(legacyDeviceSetupViewModelProvider); + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + final theme = ref.watch(themePortProvider); + final mainStep = state.step.mainStep; + + final isIntro = state.step == LegacyAddKidStep.intro; + final isAllowance = state.step == LegacyAddKidStep.allowance; + + final canPopRoute = state.step == LegacyAddKidStep.intro; + + return PopScope( + canPop: canPopRoute, + onPopInvokedWithResult: (didPop, result) { + if (didPop || isAllowance) return; + vm.back(); + }, + child: Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: SafeArea( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 12, left: 8, right: 8), + child: Row( + children: [ + if (isIntro || isAllowance) + const SizedBox(width: 48) + else + IconButton( + onPressed: vm.back, + icon: const Icon(Icons.arrow_back_ios_new_rounded), + color: theme.getColorFor(ThemeCode.textPrimary), + tooltip: MaterialLocalizations.of( + context, + ).backButtonTooltip, + ), + Expanded( + child: isIntro + ? const SizedBox.shrink() + : StepIndicator( + total: LegacyAddKidMainStep.values.length, + current: mainStep.index + 1, + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + ), + IconButton( + onPressed: () => + navigationContract.goTo(AppRoutes.dashboardHome), + icon: const Icon(Icons.close), + color: theme.getColorFor(ThemeCode.textPrimary), + ), + ], + ), + ), + + Expanded( + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 250), + child: LegacyStepBody(key: ValueKey(state.step), state: state), + ), + ), + + LegacyFlowFooter( + primaryText: context.translate(primaryButtonText(state.step)), + onPrimary: () async { + if (state.step == LegacyAddKidStep.profile) { + if (!vm.validateProfile()) return; + final ok = await vm.createChildProfile(); + if (!context.mounted) return; + if (ok) { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => LegacySuccessScreen()), + ); + } + return; + } + if (state.step == LegacyAddKidStep.allowance) { + _pushHiPayScreen(context, ref); + return; + } + vm.next(); + }, + secondaryText: isAllowance + ? context.translate(I18n.deviceSetup_skipAndConfigureLater) + : null, + onSecondary: isAllowance + ? () => navigationContract.pushTo(AppRoutes.dashboardHome) + : null, + theme: theme, + ), + ], + ), + ), + ), + ); + } + + Future _pushHiPayScreen(BuildContext context, WidgetRef ref) async { + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + final result = await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => + HiPayWebViewScreen(navigationContract: navigationContract), + ), + ); + if (!context.mounted) return; + if (result == HiPayResult.success) { + vm.setError(''); + showTopSnackbar( + context, + message: context.translate(I18n.deviceSetup_cardRegistered), + type: MessageType.success, + ); + navigationContract.pushTo(AppRoutes.dashboardHome); + } else { + showTopSnackbar( + context, + message: context.translate(I18n.deviceSetup_paymentCancelled), + type: MessageType.error, + ); + } + } + + String primaryButtonText(LegacyAddKidStep step) { + switch (step) { + case LegacyAddKidStep.intro: + return I18n.deviceSetup_start; + case LegacyAddKidStep.allowance: + return I18n.deviceSetup_addCreditCard; + default: + return I18n.continueKey; + } + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_main_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_main_step.dart new file mode 100644 index 00000000..63c144eb --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_main_step.dart @@ -0,0 +1 @@ +enum LegacyAddKidMainStep { linkDevice, profile, allowance } diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_step.dart new file mode 100644 index 00000000..403bfce0 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/add_kid_step.dart @@ -0,0 +1 @@ +enum LegacyAddKidStep { intro, linkInfo, scanStrap, scanWatch, profile, allowance } diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/scan_link_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/scan_link_step.dart new file mode 100644 index 00000000..93b8e724 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/enums/scan_link_step.dart @@ -0,0 +1 @@ +enum LegacyScanLinkStep { strap, watch } diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/providers/create_child_profile_use_case_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/providers/create_child_profile_use_case_provider.dart new file mode 100644 index 00000000..a18db250 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/providers/create_child_profile_use_case_provider.dart @@ -0,0 +1,10 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/create_child_profile_use_case.dart'; +import 'package:legacy_auth/src/features/device_setup/domain/create_child_profile_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyCreateChildProfileUseCaseProvider = + Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyCreateChildProfileUseCaseImpl(authRepository); + }); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/qr_scanner_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/qr_scanner_screen.dart new file mode 100644 index 00000000..ab74bafb --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/qr_scanner_screen.dart @@ -0,0 +1,182 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyQrScannerScreen extends StatefulWidget { + const LegacyQrScannerScreen({super.key}); + + @override + State createState() => _LegacyQrScannerScreenState(); +} + +class _LegacyQrScannerScreenState extends State { + late final MobileScannerController _controller; + + bool _alreadyReturned = false; + + @override + void initState() { + super.initState(); + _controller = MobileScannerController( + detectionSpeed: DetectionSpeed.noDuplicates, + formats: const [BarcodeFormat.qrCode], + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _returnResult(String value) { + if (_alreadyReturned) return; + _alreadyReturned = true; + Navigator.of(context).pop(value); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + appBar: AppBar( + backgroundColor: Colors.black, + foregroundColor: Colors.white, + title: Text(context.translate(I18n.deviceSetup_scanQr)), + actions: [ + IconButton( + icon: const Icon(Icons.flash_on), + onPressed: () => _controller.toggleTorch(), + ), + ], + ), + body: Stack( + children: [ + MobileScanner( + controller: _controller, + onDetect: (capture) { + if (capture.barcodes.isEmpty) return; + + final rawValue = capture.barcodes.first.rawValue; + if (rawValue == null || rawValue.isEmpty) return; + + _returnResult(rawValue); + }, + ), + + const Positioned.fill( + child: LegacyQrScannerOverlay( + cutOutSize: 260, + borderRadius: 18, + borderWidth: 3, + ), + ), + + Positioned( + left: 0, + right: 0, + bottom: 50, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 14, + vertical: 10, + ), + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(14), + ), + child: Text( + context.translate(I18n.deviceSetup_scanQr_hint), + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 15), + ), + ), + ), + ), + ], + ), + ); + } +} + +class LegacyQrScannerOverlay extends StatelessWidget { + const LegacyQrScannerOverlay({ + super.key, + required this.cutOutSize, + required this.borderRadius, + required this.borderWidth, + }); + + final double cutOutSize; + final double borderRadius; + final double borderWidth; + + @override + Widget build(BuildContext context) { + return IgnorePointer( + child: CustomPaint( + painter: _LegacyQrScannerOverlayPainter( + cutOutSize: cutOutSize, + borderRadius: borderRadius, + borderWidth: borderWidth, + ), + ), + ); + } +} + +class _LegacyQrScannerOverlayPainter extends CustomPainter { + _LegacyQrScannerOverlayPainter({ + required this.cutOutSize, + required this.borderRadius, + required this.borderWidth, + }); + + final double cutOutSize; + final double borderRadius; + final double borderWidth; + + @override + void paint(Canvas canvas, Size size) { + final screenRect = Rect.fromLTWH(0, 0, size.width, size.height); + + final cutOutRect = Rect.fromCenter( + center: screenRect.center, + width: cutOutSize, + height: cutOutSize, + ); + + final cutOutRRect = RRect.fromRectXY( + cutOutRect, + borderRadius, + borderRadius, + ); + + final backgroundPath = Path()..addRect(screenRect); + final cutOutPath = Path()..addRRect(cutOutRRect); + + final overlayPath = Path.combine( + PathOperation.difference, + backgroundPath, + cutOutPath, + ); + + final overlayPaint = Paint() + ..color = Colors.black.withValues(alpha: 0.55) + ..style = PaintingStyle.fill; + + canvas.drawPath(overlayPath, overlayPaint); + + final borderPaint = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = borderWidth + ..color = Colors.white; + + canvas.drawRRect(cutOutRRect, borderPaint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_model.dart new file mode 100644 index 00000000..0b4faa0e --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_model.dart @@ -0,0 +1,355 @@ +import 'package:legacy_auth/src/features/device_setup/domain/create_child_profile_use_case.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/scan_link_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/providers/create_child_profile_use_case_provider.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_state.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_step.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:sf_shared/sf_shared.dart'; +import 'package:uuid/uuid.dart'; + +final legacyDeviceSetupViewModelProvider = + NotifierProvider( + LegacyDeviceSetupViewModel.new, + ); + +class LegacyDeviceSetupViewModel extends Notifier { + late final LegacyCreateChildProfileUseCase _createChildProfileUseCase; + late final GetUserInfoUseCase _getUserInfoUseCase; + + late final TextEditingController bornAtController; + late final TextEditingController firstNameController; + late final TextEditingController lastNameController; + late final TextEditingController addressController; + late final TextEditingController strapCodeController; + late final TextEditingController watchCodeController; + late final TextEditingController allowanceAmountController; + + @override + LegacyDeviceSetupViewState build() { + final initial = LegacyDeviceSetupViewState(id: const Uuid().v4()); + _initControllers(initial); + _addListeners(); + + ref.onDispose(disposeControllers); + + return initial; + } + + void _initControllers(LegacyDeviceSetupViewState s) { + _createChildProfileUseCase = ref.read(legacyCreateChildProfileUseCaseProvider); + _getUserInfoUseCase = ref.read(getUserInfoUseCaseProvider); + + firstNameController = TextEditingController(text: s.firstName); + lastNameController = TextEditingController(text: s.lastName); + bornAtController = TextEditingController( + text: s.bornAt == null ? '' : _formatDate(s.bornAt!), + ); + + addressController = TextEditingController(text: s.address); + strapCodeController = TextEditingController(text: s.strapCode); + watchCodeController = TextEditingController(text: s.watchCode); + allowanceAmountController = TextEditingController(text: s.allowanceAmount); + } + + void _addListeners() { + firstNameController.addListener(_onFirstNameChanged); + lastNameController.addListener(_onLastNameChanged); + bornAtController.addListener(_onBornAtTextChanged); + addressController.addListener(_onAddressChanged); + + strapCodeController.addListener(_onStrapCodeChanged); + watchCodeController.addListener(_onWatchCodeChanged); + allowanceAmountController.addListener(_onAllowanceAmountChanged); + } + + void next() { + switch (state.step) { + case LegacyAddKidStep.intro: + state = state.copyWith(step: LegacyAddKidStep.linkInfo); + return; + case LegacyAddKidStep.linkInfo: + state = state.copyWith(step: LegacyAddKidStep.scanStrap); + return; + case LegacyAddKidStep.scanStrap: + final hasStrap = state.strapQr.isNotEmpty || state.strapCode.isNotEmpty; + if (!hasStrap) { + state = state.copyWith(errorMessage: I18n.errorScanStrapRequired); + return; + } + state = state.copyWith(step: LegacyAddKidStep.scanWatch, errorMessage: ''); + return; + case LegacyAddKidStep.scanWatch: + final hasWatch = state.watchQr.isNotEmpty || state.watchCode.isNotEmpty; + if (!hasWatch) { + state = state.copyWith(errorMessage: I18n.errorScanWatchRequired); + return; + } + state = state.copyWith(step: LegacyAddKidStep.profile, errorMessage: ''); + return; + case LegacyAddKidStep.profile: + return; + case LegacyAddKidStep.allowance: + return; + } + } + + void back() { + switch (state.step) { + case LegacyAddKidStep.intro: + return; + + case LegacyAddKidStep.linkInfo: + state = state.copyWith(step: LegacyAddKidStep.intro, errorMessage: ''); + return; + case LegacyAddKidStep.scanStrap: + state = state.copyWith(step: LegacyAddKidStep.linkInfo); + return; + case LegacyAddKidStep.scanWatch: + state = state.copyWith(step: LegacyAddKidStep.scanStrap); + return; + case LegacyAddKidStep.profile: + state = state.copyWith(step: LegacyAddKidStep.scanWatch); + return; + case LegacyAddKidStep.allowance: + state = state.copyWith(step: LegacyAddKidStep.profile); + return; + } + } + + void onQrScanned({required LegacyScanLinkStep step, required String qr}) { + switch (step) { + case LegacyScanLinkStep.strap: + state = state.copyWith(strapQr: qr, step: LegacyAddKidStep.scanWatch); + break; + + case LegacyScanLinkStep.watch: + state = state.copyWith(watchQr: qr, step: LegacyAddKidStep.profile); + break; + } + } + + Future 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 setBornAt(DateTime date) { + bornAtController.text = _formatDate(date); + state = state.copyWith(bornAt: date); + } + + Future createChildProfile() async { + await getUserInfo(); + final firstName = state.firstName.trim(); + final lastName = state.lastName.trim(); + final birth = state.bornAt!; + final bornAt = DateTime.utc(birth.year, birth.month, birth.day) + .millisecondsSinceEpoch; + final address = state.address.trim(); + final genrer = state.genrer.trim(); + final relationType = state.relationType.trim(); + + state = state.copyWith(isLoading: true); + + try { + await _createChildProfileUseCase.createChildProfile( + id: state.id, + parentId: state.parentId, + firstName: firstName, + lastName: lastName, + bornAt: bornAt, + genrer: genrer, + relationType: relationType, + address: address, + cardPublicKey: state.strapCode, + deviceActivationCode: state.watchCode, + scaProof: '', + ); + + if (!ref.mounted) return false; + + state = state.copyWith( + isLoading: false, + isSuccess: true, + ); + return true; + } catch (e) { + if (!ref.mounted) return false; + + state = state.copyWith(isLoading: false, errorMessage: e.toString()); + return false; + } + } + + Future getUserInfo() async { + state = state.copyWith(isLoading: true, errorMessage: ''); + + try { + final user = await _getUserInfoUseCase.getUserInfo(); + + if (ref.mounted) { + state = state.copyWith(isLoading: false); + } + + debugPrint('[getUserInfo] userId => ${user.id}'); + state = state.copyWith(parentId: user.id); + + return user; + } catch (e) { + if (ref.mounted) { + state = state.copyWith(isLoading: false, errorMessage: e.toString()); + } + return null; + } + } + + bool validateProfile() { + final isInvalid = + state.firstName.trim().isEmpty || + state.lastName.trim().isEmpty || + state.bornAt == null || + state.address.trim().isEmpty || + state.genrer.trim().isEmpty || + state.relationType.trim().isEmpty; + + if (isInvalid) { + state = state.copyWith(errorMessage: I18n.errorAllFieldsRequired); + return false; + } + return true; + } + + 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 _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 _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 _onAddressChanged() { + final text = addressController.text; + if (text == state.address) return; + state = state.copyWith(address: text, errorMessage: ''); + } + + void _onStrapCodeChanged() { + final text = strapCodeController.text; + if (text == state.strapCode) return; + state = state.copyWith(strapCode: text, errorMessage: ''); + } + + void _onWatchCodeChanged() { + final text = watchCodeController.text; + if (text == state.watchCode) return; + state = state.copyWith(watchCode: text, errorMessage: ''); + } + + void _onAllowanceAmountChanged() { + final text = allowanceAmountController.text; + if (text == state.allowanceAmount) return; + state = state.copyWith(allowanceAmount: text, errorMessage: ''); + } + + void setError(String message) { + state = state.copyWith(errorMessage: message); + } + + void goToAllowance() { + state = state.copyWith(step: LegacyAddKidStep.allowance, errorMessage: ''); + } + + void onGenrerChanged(String? value) { + final v = value ?? ''; + if (v == state.genrer) return; + state = state.copyWith(genrer: v, errorMessage: ''); + } + + void onRelationTypeChanged(String? value) { + final v = value ?? ''; + if (v == state.relationType) return; + state = state.copyWith(relationType: v, errorMessage: ''); + } + + 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; + } + + void resetForNewKid() { + firstNameController.clear(); + lastNameController.clear(); + bornAtController.clear(); + addressController.clear(); + strapCodeController.clear(); + watchCodeController.clear(); + allowanceAmountController.clear(); + + state = LegacyDeviceSetupViewState(id: const Uuid().v4()); + } + + void disposeControllers() { + // firstNameController.dispose(); + // lastNameController.dispose(); + bornAtController.dispose(); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.dart new file mode 100644 index 00000000..cb915884 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.dart @@ -0,0 +1,30 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_step.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'device_setup_view_state.freezed.dart'; + +@freezed +abstract class LegacyDeviceSetupViewState with _$LegacyDeviceSetupViewState { + const factory LegacyDeviceSetupViewState({ + @Default(LegacyAddKidStep.intro) LegacyAddKidStep step, + @Default('') String id, + @Default('') String parentId, + @Default('') String firstName, + @Default('') String lastName, + DateTime? bornAt, + @Default('') String address, + @Default('') String genrer, + @Default('') String relationType, + + @Default('') String strapQr, + @Default('') String strapCode, + @Default('') String watchQr, + @Default('') String watchCode, + + @Default(false) bool isLoading, + @Default('') String errorMessage, + @Default(false) bool isSuccess, + + @Default('') String allowanceAmount, + }) = _AddKidFlowState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.freezed.dart new file mode 100644 index 00000000..b6f5de2a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/state/device_setup_view_state.freezed.dart @@ -0,0 +1,319 @@ +// 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 'device_setup_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacyDeviceSetupViewState { + + LegacyAddKidStep get step; String get id; String get parentId; String get firstName; String get lastName; DateTime? get bornAt; String get address; String get genrer; String get relationType; String get strapQr; String get strapCode; String get watchQr; String get watchCode; bool get isLoading; String get errorMessage; bool get isSuccess; String get allowanceAmount; +/// Create a copy of LegacyDeviceSetupViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyDeviceSetupViewStateCopyWith get copyWith => _$LegacyDeviceSetupViewStateCopyWithImpl(this as LegacyDeviceSetupViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyDeviceSetupViewState&&(identical(other.step, step) || other.step == step)&&(identical(other.id, id) || other.id == id)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.genrer, genrer) || other.genrer == genrer)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.strapQr, strapQr) || other.strapQr == strapQr)&&(identical(other.strapCode, strapCode) || other.strapCode == strapCode)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess)&&(identical(other.allowanceAmount, allowanceAmount) || other.allowanceAmount == allowanceAmount)); +} + + +@override +int get hashCode => Object.hash(runtimeType,step,id,parentId,firstName,lastName,bornAt,address,genrer,relationType,strapQr,strapCode,watchQr,watchCode,isLoading,errorMessage,isSuccess,allowanceAmount); + +@override +String toString() { + return 'LegacyDeviceSetupViewState(step: $step, id: $id, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, genrer: $genrer, relationType: $relationType, strapQr: $strapQr, strapCode: $strapCode, watchQr: $watchQr, watchCode: $watchCode, isLoading: $isLoading, errorMessage: $errorMessage, isSuccess: $isSuccess, allowanceAmount: $allowanceAmount)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyDeviceSetupViewStateCopyWith<$Res> { + factory $LegacyDeviceSetupViewStateCopyWith(LegacyDeviceSetupViewState value, $Res Function(LegacyDeviceSetupViewState) _then) = _$LegacyDeviceSetupViewStateCopyWithImpl; +@useResult +$Res call({ + LegacyAddKidStep step, String id, String parentId, String firstName, String lastName, DateTime? bornAt, String address, String genrer, String relationType, String strapQr, String strapCode, String watchQr, String watchCode, bool isLoading, String errorMessage, bool isSuccess, String allowanceAmount +}); + + + + +} +/// @nodoc +class _$LegacyDeviceSetupViewStateCopyWithImpl<$Res> + implements $LegacyDeviceSetupViewStateCopyWith<$Res> { + _$LegacyDeviceSetupViewStateCopyWithImpl(this._self, this._then); + + final LegacyDeviceSetupViewState _self; + final $Res Function(LegacyDeviceSetupViewState) _then; + +/// Create a copy of LegacyDeviceSetupViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? step = null,Object? id = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = freezed,Object? address = null,Object? genrer = null,Object? relationType = null,Object? strapQr = null,Object? strapCode = null,Object? watchQr = null,Object? watchCode = null,Object? isLoading = null,Object? errorMessage = null,Object? isSuccess = null,Object? allowanceAmount = null,}) { + return _then(_self.copyWith( +step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable +as LegacyAddKidStep,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as DateTime?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,genrer: null == genrer ? _self.genrer : genrer // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable +as String,strapQr: null == strapQr ? _self.strapQr : strapQr // ignore: cast_nullable_to_non_nullable +as String,strapCode: null == strapCode ? _self.strapCode : strapCode // ignore: cast_nullable_to_non_nullable +as String,watchQr: null == watchQr ? _self.watchQr : watchQr // ignore: cast_nullable_to_non_nullable +as String,watchCode: null == watchCode ? _self.watchCode : watchCode // ignore: cast_nullable_to_non_nullable +as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String,isSuccess: null == isSuccess ? _self.isSuccess : isSuccess // ignore: cast_nullable_to_non_nullable +as bool,allowanceAmount: null == allowanceAmount ? _self.allowanceAmount : allowanceAmount // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyDeviceSetupViewState]. +extension LegacyDeviceSetupViewStatePatterns on LegacyDeviceSetupViewState { +/// 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 Function( _AddKidFlowState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AddKidFlowState() 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 Function( _AddKidFlowState value) $default,){ +final _that = this; +switch (_that) { +case _AddKidFlowState(): +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? Function( _AddKidFlowState value)? $default,){ +final _that = this; +switch (_that) { +case _AddKidFlowState() 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 Function( LegacyAddKidStep step, String id, String parentId, String firstName, String lastName, DateTime? bornAt, String address, String genrer, String relationType, String strapQr, String strapCode, String watchQr, String watchCode, bool isLoading, String errorMessage, bool isSuccess, String allowanceAmount)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AddKidFlowState() when $default != null: +return $default(_that.step,_that.id,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.genrer,_that.relationType,_that.strapQr,_that.strapCode,_that.watchQr,_that.watchCode,_that.isLoading,_that.errorMessage,_that.isSuccess,_that.allowanceAmount);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 Function( LegacyAddKidStep step, String id, String parentId, String firstName, String lastName, DateTime? bornAt, String address, String genrer, String relationType, String strapQr, String strapCode, String watchQr, String watchCode, bool isLoading, String errorMessage, bool isSuccess, String allowanceAmount) $default,) {final _that = this; +switch (_that) { +case _AddKidFlowState(): +return $default(_that.step,_that.id,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.genrer,_that.relationType,_that.strapQr,_that.strapCode,_that.watchQr,_that.watchCode,_that.isLoading,_that.errorMessage,_that.isSuccess,_that.allowanceAmount);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? Function( LegacyAddKidStep step, String id, String parentId, String firstName, String lastName, DateTime? bornAt, String address, String genrer, String relationType, String strapQr, String strapCode, String watchQr, String watchCode, bool isLoading, String errorMessage, bool isSuccess, String allowanceAmount)? $default,) {final _that = this; +switch (_that) { +case _AddKidFlowState() when $default != null: +return $default(_that.step,_that.id,_that.parentId,_that.firstName,_that.lastName,_that.bornAt,_that.address,_that.genrer,_that.relationType,_that.strapQr,_that.strapCode,_that.watchQr,_that.watchCode,_that.isLoading,_that.errorMessage,_that.isSuccess,_that.allowanceAmount);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _AddKidFlowState implements LegacyDeviceSetupViewState { + const _AddKidFlowState({this.step = LegacyAddKidStep.intro, this.id = '', this.parentId = '', this.firstName = '', this.lastName = '', this.bornAt, this.address = '', this.genrer = '', this.relationType = '', this.strapQr = '', this.strapCode = '', this.watchQr = '', this.watchCode = '', this.isLoading = false, this.errorMessage = '', this.isSuccess = false, this.allowanceAmount = ''}); + + +@override@JsonKey() final LegacyAddKidStep step; +@override@JsonKey() final String id; +@override@JsonKey() final String parentId; +@override@JsonKey() final String firstName; +@override@JsonKey() final String lastName; +@override final DateTime? bornAt; +@override@JsonKey() final String address; +@override@JsonKey() final String genrer; +@override@JsonKey() final String relationType; +@override@JsonKey() final String strapQr; +@override@JsonKey() final String strapCode; +@override@JsonKey() final String watchQr; +@override@JsonKey() final String watchCode; +@override@JsonKey() final bool isLoading; +@override@JsonKey() final String errorMessage; +@override@JsonKey() final bool isSuccess; +@override@JsonKey() final String allowanceAmount; + +/// Create a copy of LegacyDeviceSetupViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AddKidFlowStateCopyWith<_AddKidFlowState> get copyWith => __$AddKidFlowStateCopyWithImpl<_AddKidFlowState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AddKidFlowState&&(identical(other.step, step) || other.step == step)&&(identical(other.id, id) || other.id == id)&&(identical(other.parentId, parentId) || other.parentId == parentId)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.address, address) || other.address == address)&&(identical(other.genrer, genrer) || other.genrer == genrer)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.strapQr, strapQr) || other.strapQr == strapQr)&&(identical(other.strapCode, strapCode) || other.strapCode == strapCode)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess)&&(identical(other.allowanceAmount, allowanceAmount) || other.allowanceAmount == allowanceAmount)); +} + + +@override +int get hashCode => Object.hash(runtimeType,step,id,parentId,firstName,lastName,bornAt,address,genrer,relationType,strapQr,strapCode,watchQr,watchCode,isLoading,errorMessage,isSuccess,allowanceAmount); + +@override +String toString() { + return 'LegacyDeviceSetupViewState(step: $step, id: $id, parentId: $parentId, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, address: $address, genrer: $genrer, relationType: $relationType, strapQr: $strapQr, strapCode: $strapCode, watchQr: $watchQr, watchCode: $watchCode, isLoading: $isLoading, errorMessage: $errorMessage, isSuccess: $isSuccess, allowanceAmount: $allowanceAmount)'; +} + + +} + +/// @nodoc +abstract mixin class _$AddKidFlowStateCopyWith<$Res> implements $LegacyDeviceSetupViewStateCopyWith<$Res> { + factory _$AddKidFlowStateCopyWith(_AddKidFlowState value, $Res Function(_AddKidFlowState) _then) = __$AddKidFlowStateCopyWithImpl; +@override @useResult +$Res call({ + LegacyAddKidStep step, String id, String parentId, String firstName, String lastName, DateTime? bornAt, String address, String genrer, String relationType, String strapQr, String strapCode, String watchQr, String watchCode, bool isLoading, String errorMessage, bool isSuccess, String allowanceAmount +}); + + + + +} +/// @nodoc +class __$AddKidFlowStateCopyWithImpl<$Res> + implements _$AddKidFlowStateCopyWith<$Res> { + __$AddKidFlowStateCopyWithImpl(this._self, this._then); + + final _AddKidFlowState _self; + final $Res Function(_AddKidFlowState) _then; + +/// Create a copy of LegacyDeviceSetupViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? step = null,Object? id = null,Object? parentId = null,Object? firstName = null,Object? lastName = null,Object? bornAt = freezed,Object? address = null,Object? genrer = null,Object? relationType = null,Object? strapQr = null,Object? strapCode = null,Object? watchQr = null,Object? watchCode = null,Object? isLoading = null,Object? errorMessage = null,Object? isSuccess = null,Object? allowanceAmount = null,}) { + return _then(_AddKidFlowState( +step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable +as LegacyAddKidStep,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,parentId: null == parentId ? _self.parentId : parentId // 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,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as DateTime?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String,genrer: null == genrer ? _self.genrer : genrer // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable +as String,strapQr: null == strapQr ? _self.strapQr : strapQr // ignore: cast_nullable_to_non_nullable +as String,strapCode: null == strapCode ? _self.strapCode : strapCode // ignore: cast_nullable_to_non_nullable +as String,watchQr: null == watchQr ? _self.watchQr : watchQr // ignore: cast_nullable_to_non_nullable +as String,watchCode: null == watchCode ? _self.watchCode : watchCode // ignore: cast_nullable_to_non_nullable +as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable +as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable +as String,isSuccess: null == isSuccess ? _self.isSuccess : isSuccess // ignore: cast_nullable_to_non_nullable +as bool,allowanceAmount: null == allowanceAmount ? _self.allowanceAmount : allowanceAmount // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/step_body.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/step_body.dart new file mode 100644 index 00000000..902e8bf8 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/step_body.dart @@ -0,0 +1,32 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_state.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/add_kid_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/enums/scan_link_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/intro_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/link_info_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/allowance_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/profile_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/scan_strap_and_watch_step.dart'; +import 'package:flutter/material.dart'; + +class LegacyStepBody extends StatelessWidget { + const LegacyStepBody({super.key, required this.state}); + final LegacyDeviceSetupViewState state; + + @override + Widget build(BuildContext context) { + switch (state.step) { + case LegacyAddKidStep.intro: + return LegacyIntroStepScreen(); + case LegacyAddKidStep.linkInfo: + return LegacyLinkInfoStepScreen(); + case LegacyAddKidStep.scanStrap: + return LegacyScanStrapAndWatchStepScreen(step: LegacyScanLinkStep.strap); + case LegacyAddKidStep.scanWatch: + return LegacyScanStrapAndWatchStepScreen(step: LegacyScanLinkStep.watch); + case LegacyAddKidStep.profile: + return LegacyProfileStepScreen(); + case LegacyAddKidStep.allowance: + return LegacyAllowanceStepScreen(); + } + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/allowance_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/allowance_step.dart new file mode 100644 index 00000000..fd889692 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/allowance_step.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyAllowanceStepScreen extends ConsumerWidget { + const LegacyAllowanceStepScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + Text( + context.translate(I18n.deviceSetup_addCreditCard_title), + style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Text( + context.translate(I18n.deviceSetup_addCreditCard_subtitle), + style: const TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + Text( + context.translate(I18n.deviceSetup_addCreditCard_info), + style: const TextStyle(fontSize: 14), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart new file mode 100644 index 00000000..980825ad --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/intro_step.dart @@ -0,0 +1,80 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/numbered_steps.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyIntroStepScreen extends ConsumerWidget { + const LegacyIntroStepScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + context.translate(I18n.deviceSetup_intro_title), + style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text( + context.translate(I18n.deviceSetup_intro_subtitle), + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + SizedBox(height: 40), + LegacyNumberedSteps( + steps: [ + context.translate(I18n.deviceSetup_intro_step_1), + context.translate(I18n.deviceSetup_intro_step_2), + context.translate(I18n.deviceSetup_intro_step_3), + ], + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + SizedBox(height: 40), + + Text( + context.translate(I18n.deviceSetup_intro_ready_title), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + SizedBox(height: 40), + + Text( + context.translate(I18n.deviceSetup_intro_remember_prefix), + style: TextStyle(fontSize: 16), + ), + Text( + context.translate(I18n.deviceSetup_intro_plan_name), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + SizedBox(height: 20), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50.0), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: context.translate(I18n.deviceSetup_intro_web_prefix), + style: TextStyle(fontSize: 16, color: Colors.black), + children: [ + TextSpan( + text: context.translate(I18n.deviceSetup_intro_web_link), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + decoration: TextDecoration.underline, + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/link_info_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/link_info_step.dart new file mode 100644 index 00000000..9f97e385 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/link_info_step.dart @@ -0,0 +1,71 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/link_info_item.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyLinkInfoStepScreen extends ConsumerWidget { + const LegacyLinkInfoStepScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 65), + child: Text( + context.translate(I18n.deviceSetup_linkInfo_title), + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + height: 1.2, + ), + textAlign: TextAlign.center, + ), + ), + + const SizedBox(height: 25), + + SvgPicture.asset("assets/shared/images/formulario.svg"), + + const SizedBox(height: 40), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + children: [ + LegacyLinkInfoItem( + number: 1, + boldWord: context.translate( + I18n.deviceSetup_linkInfo_item1_boldWord, + ), + titlePrefix: context.translate( + I18n.deviceSetup_linkInfo_item1_prefix, + ), + subtitle: context.translate( + I18n.deviceSetup_linkInfo_item1_subtitle, + ), + ), + SizedBox(height: 20), + LegacyLinkInfoItem( + number: 2, + boldWord: context.translate( + I18n.deviceSetup_linkInfo_item2_boldWord, + ), + titlePrefix: context.translate( + I18n.deviceSetup_linkInfo_item2_prefix, + ), + subtitle: context.translate( + I18n.deviceSetup_linkInfo_item2_subtitle, + ), + ), + ], + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/profile_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/profile_step.dart new file mode 100644 index 00000000..63208c3d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/profile_step.dart @@ -0,0 +1,118 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_model.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyProfileStepScreen extends ConsumerWidget { + const LegacyProfileStepScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + const Map genrer = { + 'F': 'Femenino', + 'M': 'Masculino', + 'O': 'Otro', + }; + + const Map relationship = { + 'FATHER': 'Padre', + 'MOTHER': 'Madre', + 'OTHER': 'Otro', + }; + + final state = ref.watch(legacyDeviceSetupViewModelProvider); + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + + return SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + Text( + context.translate(I18n.deviceSetup_intro_step_1), + style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text( + context.translate(I18n.deviceSetup_accountData_info), + style: const TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Text( + context.translate(I18n.deviceSetup_startWithOneKid_info), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + textAlign: TextAlign.center, + ), + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only(left: 24, right: 24), + child: Column( + children: [ + CustomTextField( + label: context.translate(I18n.firstNameLabel), + hint: context.translate(I18n.firstNameHint), + controller: vm.firstNameController, + ), + const SizedBox(height: 8), + CustomTextField( + label: context.translate(I18n.lastNameLabel), + hint: context.translate(I18n.lastNameHint), + controller: vm.lastNameController, + ), + const SizedBox(height: 8), + + GestureDetector( + onTap: () => vm.pickBornAt(context), + child: AbsorbPointer( + child: CustomTextField( + label: context.translate(I18n.birthDateLabel), + hint: context.translate(I18n.birthDateHint), + controller: vm.bornAtController, + readOnly: true, + keyboardType: TextInputType.none, + ), + ), + ), + + const SizedBox(height: 8), + + CustomDropdown( + items: genrer.values.map(Text.new).toList(growable: false), + values: genrer.keys.toList(growable: false), + value: state.genrer.isEmpty ? null : state.genrer, + hint: 'Género', + onChanged: (v) => vm.onGenrerChanged(v as String?), + ), + + const SizedBox(height: 8), + + CustomDropdown( + items: relationship.values + .map(Text.new) + .toList(growable: false), + values: relationship.keys.toList(growable: false), + value: state.relationType.isEmpty ? null : state.relationType, + hint: 'Relación', + onChanged: (v) => vm.onRelationTypeChanged(v as String?), + ), + + const SizedBox(height: 8), + + CustomTextField( + label: 'Dirección', + hint: 'Dirección', + controller: vm.addressController, + ), + + const SizedBox(height: 8), + ], + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/scan_strap_and_watch_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/scan_strap_and_watch_step.dart new file mode 100644 index 00000000..9f6b7d40 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/scan_strap_and_watch_step.dart @@ -0,0 +1,210 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/enums/scan_link_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/qr_scanner_screen.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_model.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/scan_link_steps_indicator.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyScanStrapAndWatchStepScreen extends ConsumerWidget { + const LegacyScanStrapAndWatchStepScreen({super.key, required this.step}); + + final LegacyScanLinkStep step; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final activeColor = theme.getColorFor(ThemeCode.buttonPrimary); + final inactiveCircleColor = theme.getColorFor( + ThemeCode.backgroundSecondary, + ); + final inactiveLineColor = Colors.grey.shade200; + final textPrimary = theme.getColorFor(ThemeCode.textPrimary); + + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + final state = ref.watch(legacyDeviceSetupViewModelProvider); + + return SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 65), + child: Text( + context.translate(I18n.deviceSetup_linkInfo_title), + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + height: 1.2, + ), + textAlign: TextAlign.center, + ), + ), + + const SizedBox(height: 18), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 100), + child: LegacyScanLinkStepsIndicator( + step: step, + activeColor: activeColor, + inactiveCircleColor: inactiveCircleColor, + inactiveLineColor: inactiveLineColor, + textPrimary: textPrimary, + ), + ), + + const SizedBox(height: 12), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 35), + child: Row( + children: [ + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Text.rich( + TextSpan( + children: [ + TextSpan( + text: context.translate( + I18n.deviceSetup_linkInfo_item1_prefix, + ), + ), + TextSpan( + text: context.translate( + I18n.deviceSetup_linkInfo_item1_boldWord, + ), + style: TextStyle(fontWeight: FontWeight.w800), + ), + ], + ), + style: const TextStyle(fontSize: 18), + ), + ), + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text.rich( + TextSpan( + children: [ + TextSpan( + text: context.translate( + I18n.deviceSetup_linkInfo_item2_prefix, + ), + ), + TextSpan( + text: context.translate( + I18n.deviceSetup_linkInfo_item2_boldWord, + ), + style: TextStyle(fontWeight: FontWeight.w800), + ), + ], + ), + style: const TextStyle(fontSize: 18), + ), + ), + ), + ], + ), + ), + + const SizedBox(height: 28), + + InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () async { + final result = await Navigator.of(context).push( + MaterialPageRoute(builder: (_) => const LegacyQrScannerScreen()), + ); + if (result == null || result.isEmpty) return; + vm.onQrScanned(step: step, qr: result); + }, + child: Container( + width: 170, + height: 170, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade500, width: 1), + borderRadius: BorderRadius.circular(16), + ), + child: Center( + child: SvgPicture.asset( + "assets/shared/images/qr.svg", + width: 90, + height: 90, + fit: BoxFit.contain, + ), + ), + ), + ), + + const SizedBox(height: 22), + + // if (step == LegacyScanLinkStep.watch) ...[ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.translate(I18n.deviceSetup_watchCode_orInsert), + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: CustomTextField( + hint: "XXXXXXXXXX", + controller: LegacyScanLinkStep.strap == step + ? vm.strapCodeController + : vm.watchCodeController, + // controller: vm.codeController, + ), + ), + const SizedBox(width: 12), + // Expanded( + // child: PrimaryButton( + // onPressed: () {}, + // text: context.translate( + // I18n.deviceSetup_watchCode_continueWithCode, + // ), + // size: 14, + // color: theme.getColorFor(ThemeCode.buttonSecondary), + // ), + // ), + ], + ), + ], + ), + ), + + // ], + const SizedBox(height: 10), + + Column( + children: [ + Text( + context.translate(I18n.deviceSetup_linkTroubleshoot_title), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + CustomTextButton( + onPressed: () {}, + text: context.translate(I18n.deviceSetup_contactUs), + weight: FontWeight.w800, + size: 18, + ), + ], + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/success_step.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/success_step.dart new file mode 100644 index 00000000..318d7a83 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/steps/success_step.dart @@ -0,0 +1,66 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_model.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacySuccessStepScreen extends ConsumerWidget { + const LegacySuccessStepScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final state = ref.watch(legacyDeviceSetupViewModelProvider); + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + + return Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.check, + color: theme.getColorFor(ThemeCode.buttonPrimary), + size: 50, + ), + const SizedBox(height: 20), + Text( + context.translate(I18n.accountCreatedTitle), + style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text( + context.translate(I18n.accountCreatedForLabel), + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + Text( + '${state.firstName} ${state.lastName}', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500), + textAlign: TextAlign.center, + ), + SizedBox(height: 40), + + Text( + 'Reloj: ${state.watchCode}', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 16), + ), + Text( + 'ID de la tarjeta: ${state.strapCode} ', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 16), + ), + SizedBox(height: 40), + + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + context.translate(I18n.deviceSetup_firstAllowance_title), + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart new file mode 100644 index 00000000..329a8448 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/success_screen.dart @@ -0,0 +1,44 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/state/device_setup_view_model.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/steps/success_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/flow_footer.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacySuccessScreen extends ConsumerWidget { + const LegacySuccessScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final vm = ref.read(legacyDeviceSetupViewModelProvider.notifier); + final theme = ref.watch(themePortProvider); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: SafeArea( + child: Column( + children: [ + const SizedBox(height: 20), + Expanded(child: LegacySuccessStepScreen()), + LegacyFlowFooter( + primaryText: context.translate( + I18n.deviceSetup_giveFirstAllowance, + ), + onPrimary: () { + vm.goToAllowance(); + Navigator.of(context).pop(); + }, + secondaryText: context.translate(I18n.deviceSetup_addAnotherKid), + onSecondary: () { + vm.resetForNewKid(); + Navigator.of(context).pop(); + }, + theme: theme, + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart new file mode 100644 index 00000000..e0ac9282 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/flow_footer.dart @@ -0,0 +1,71 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +class LegacyFlowFooter extends StatelessWidget { + const LegacyFlowFooter({ + super.key, + required this.primaryText, + required this.onPrimary, + required this.theme, + this.secondaryText, + this.onSecondary, + this.error, + }); + + final String primaryText; + final VoidCallback onPrimary; + final ThemePort theme; + + final String? secondaryText; + final VoidCallback? onSecondary; + + final String? error; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + border: Border(top: BorderSide(color: Colors.grey.shade300, width: 1)), + borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 10), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (error != null) ...[ + Text( + error!, + style: const TextStyle(color: Colors.red, fontSize: 13), + textAlign: TextAlign.center, + ), + const SizedBox(height: 8), + ], + PrimaryButton( + text: primaryText, + onPressed: onPrimary, + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + if (secondaryText != null && onSecondary != null) ...[ + const SizedBox(height: 10), + Material( + child: InkWell( + onTap: onSecondary, + child: Text( + secondaryText ?? '', + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + decoration: TextDecoration.underline, + ), + ), + ), + ), + ], + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/link_info_item.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/link_info_item.dart new file mode 100644 index 00000000..cadc7efd --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/link_info_item.dart @@ -0,0 +1,60 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/number_circle.dart'; +import 'package:flutter/material.dart'; + +class LegacyLinkInfoItem extends StatelessWidget { + const LegacyLinkInfoItem({ + super.key, + required this.number, + required this.titlePrefix, + required this.boldWord, + required this.subtitle, + }); + + final int number; + final String titlePrefix; + final String boldWord; + final String subtitle; + + @override + Widget build(BuildContext context) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LegacyNumberCircle(number: number), + const SizedBox(width: 10), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text.rich( + TextSpan( + children: [ + TextSpan( + text: titlePrefix, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + color: Color(0xFF4B4B4B), + ), + ), + TextSpan( + text: boldWord, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w800, + color: Color(0xFF4B4B4B), + ), + ), + ], + ), + ), + const SizedBox(height: 4), + Text(subtitle, style: const TextStyle(fontSize: 16)), + ], + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/number_circle.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/number_circle.dart new file mode 100644 index 00000000..92dcaa5d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/number_circle.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class LegacyNumberCircle extends StatelessWidget { + const LegacyNumberCircle({super.key, required this.number}); + + final int number; + + @override + Widget build(BuildContext context) { + return Container( + width: 48, + height: 48, + alignment: Alignment.center, + decoration: const BoxDecoration( + color: Color(0xFFF2F2F2), + shape: BoxShape.circle, + ), + child: Text( + number.toString(), + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w700, + color: Color(0xFF5A5A5A), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/numbered_steps.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/numbered_steps.dart new file mode 100644 index 00000000..8f6babe0 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/numbered_steps.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; + +class LegacyNumberedSteps extends StatelessWidget { + const LegacyNumberedSteps({ + super.key, + required this.steps, + this.color, + this.textColor, + this.textStyle, + }); + + final List steps; + + final Color? color; + final Color? textColor; + + final TextStyle? textStyle; + + @override + @override + Widget build(BuildContext context) { + final Color resolvedColor = + color ?? Theme.of(context).colorScheme.secondaryContainer; + final Color resolvedTextColor = textColor ?? Colors.grey.shade800; + final TextStyle resolvedTextStyle = + textStyle ?? + TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: resolvedTextColor, + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: List.generate(steps.length, (index) { + final isLast = index == steps.length - 1; + + return Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 32, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _LegacyStepCircle( + number: index + 1, + size: 32, + color: resolvedColor, + ), + if (!isLast) + Container( + width: 4, + height: 15, + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(99), + ), + ), + ], + ), + ), + const SizedBox(width: 10), + Padding( + padding: const EdgeInsets.only(top: 32 * 0.15), + child: Text(steps[index], style: resolvedTextStyle), + ), + ], + ); + }), + ); + } +} + +class _LegacyStepCircle extends StatelessWidget { + const _LegacyStepCircle({ + required this.number, + required this.size, + required this.color, + }); + + final int number; + final double size; + final Color color; + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + alignment: Alignment.center, + decoration: BoxDecoration(color: color, shape: BoxShape.circle), + child: Text( + '$number', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w700, + fontSize: size * 0.55, + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/scan_link_steps_indicator.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/scan_link_steps_indicator.dart new file mode 100644 index 00000000..60f06a03 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/scan_link_steps_indicator.dart @@ -0,0 +1,60 @@ +import 'package:legacy_auth/src/features/device_setup/presentation/enums/scan_link_step.dart'; +import 'package:legacy_auth/src/features/device_setup/presentation/widgets/step_circle.dart'; +import 'package:flutter/material.dart'; + +class LegacyScanLinkStepsIndicator extends StatelessWidget { + const LegacyScanLinkStepsIndicator({ + super.key, + required this.step, + required this.activeColor, + required this.inactiveCircleColor, + required this.inactiveLineColor, + required this.textPrimary, + }); + + final LegacyScanLinkStep step; + final Color activeColor; + final Color inactiveCircleColor; + final Color inactiveLineColor; + final Color textPrimary; + + bool get isWatch => step == LegacyScanLinkStep.watch; + + @override + Widget build(BuildContext context) { + const circleSize = 48.0; + const lineHeight = 4.0; + + return Row( + children: [ + LegacyStepCircle( + label: "1", + size: circleSize, + background: activeColor, + textColor: Colors.white, + ), + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular(99), + child: SizedBox( + height: lineHeight, + child: Row( + children: [ + Expanded(child: Container(color: activeColor)), + if (!isWatch) + Expanded(child: Container(color: inactiveLineColor)), + ], + ), + ), + ), + ), + LegacyStepCircle( + label: "2", + size: circleSize, + background: isWatch ? activeColor : inactiveCircleColor, + textColor: isWatch ? Colors.white : textPrimary, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/step_circle.dart b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/step_circle.dart new file mode 100644 index 00000000..42083866 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/device_setup/presentation/widgets/step_circle.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class LegacyStepCircle extends StatelessWidget { + const LegacyStepCircle({ + super.key, + required this.label, + required this.size, + required this.background, + required this.textColor, + }); + + final String label; + final double size; + final Color background; + final Color textColor; + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + alignment: Alignment.center, + decoration: BoxDecoration(color: background, shape: BoxShape.circle), + child: Text( + label, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w800, + color: textColor, + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case.dart new file mode 100644 index 00000000..bb1bdf2b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case.dart @@ -0,0 +1,5 @@ +abstract class LegacyLinkPhoneUseCase { + Future requestCode({required String phone}); + + Future verifyCode({required String phone, required String code}); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart new file mode 100644 index 00000000..55cdb599 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart @@ -0,0 +1,20 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart'; + +class LegacyLinkPhoneUseCaseImpl implements LegacyLinkPhoneUseCase { + LegacyLinkPhoneUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future requestCode({required String phone}) async { + // return _repository.requestPhoneCode(phone: phone); + await Future.delayed(const Duration(milliseconds: 500)); + } + + @override + Future verifyCode({required String phone, required String code}) async { + // return _repository.verifyPhoneCode(phone: phone, code: code); + await Future.delayed(const Duration(milliseconds: 500)); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/providers/link_phone_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/providers/link_phone_provider.dart new file mode 100644 index 00000000..a27273c9 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/providers/link_phone_provider.dart @@ -0,0 +1,9 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart'; +import 'package:legacy_auth/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyLinkPhoneUseCaseProvider = Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyLinkPhoneUseCaseImpl(authRepository); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart new file mode 100644 index 00000000..ac0f5b82 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacyRequestLinkPhoneBuilder { + const LegacyRequestLinkPhoneBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyRequestLinkPhoneScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart new file mode 100644 index 00000000..39561826 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart @@ -0,0 +1,110 @@ +import 'package:legacy_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'; + +class LegacyRequestLinkPhoneScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyRequestLinkPhoneScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(legacyLinkPhoneViewModelProvider.notifier); + final viewState = ref.watch(legacyLinkPhoneViewModelProvider); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + context.translate(I18n.linkPhoneTitle), + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.w500, + letterSpacing: 0, + ), + ), + const SizedBox(height: 24), + Text( + context.translate(I18n.linkPhoneSubtitle), + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 16, letterSpacing: 0), + ), + const SizedBox(height: 48), + + Column( + spacing: 8, + children: [ + Align( + alignment: Alignment.bottomLeft, + child: Text( + context.translate(I18n.mobilePhone), + style: const TextStyle(fontSize: 14, letterSpacing: 0), + ), + ), + Row( + spacing: 10, + children: [ + CountryPrefixPicker( + headerText: context.translate(I18n.selectYourCountry), + initialSelection: viewState.dialCode, + onChanged: (country) { + viewModel.updateDialCode( + country.dialCode ?? viewState.dialCode, + ); + }, + ), + Expanded( + child: CustomTextField( + controller: viewModel.phoneNumberController, + hint: context.translate(I18n.phoneNumber), + keyboardType: TextInputType.number, + ), + ), + ], + ), + ], + ), + + const SizedBox(height: 16), + + if (viewState.errorMessage.isNotEmpty) ...[ + const SizedBox(height: 4), + Text( + viewState.errorMessage, + textAlign: TextAlign.center, + style: const TextStyle( + color: Color.fromRGBO(239, 17, 17, 1), + fontSize: 12, + ), + ), + ], + + const SizedBox(height: 24), + + PrimaryButton( + onPressed: () async { + await viewModel.requestCode(); + final updatedState = ref.read(legacyLinkPhoneViewModelProvider); + if (updatedState.errorMessage.isEmpty) { + navigationContract.pushTo(AppRoutes.phoneCode); + } + }, + text: context.translate(I18n.next), + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart new file mode 100644 index 00000000..1c3b685c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart @@ -0,0 +1,148 @@ +import 'package:legacy_auth/src/features/link_phone/presentation/providers/link_phone_provider.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:legacy_auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart'; +import 'package:legacy_auth/src/features/link_phone/presentation/state/link_phone_view_state.dart'; + +final legacyLinkPhoneViewModelProvider = + NotifierProvider.autoDispose( + LegacyLinkPhoneViewModel.new, + ); + +class LegacyLinkPhoneViewModel extends Notifier { + late final LegacyLinkPhoneUseCase _linkPhoneUseCase; + late final TextEditingController phoneNumberController; + late final TextEditingController codeController; + + @override + LegacyLinkPhoneViewState build() { + _linkPhoneUseCase = ref.read(legacyLinkPhoneUseCaseProvider); + + phoneNumberController = TextEditingController(); + phoneNumberController.addListener(_onPhoneNumberChanged); + + codeController = TextEditingController(); + + ref.onDispose(disposeControllers); + + return const LegacyLinkPhoneViewState(); + } + + void _onPhoneNumberChanged() { + final raw = phoneNumberController.text; + state = state.copyWith( + phoneNumber: raw, + errorMessage: '', + codeVerified: false, + ); + } + + void updateDialCode(String dialCode) { + state = state.copyWith( + dialCode: dialCode, + errorMessage: '', + codeVerified: false, + ); + } + + void updateCode(String code) { + codeController.text = code; + state = state.copyWith(errorMessage: '', codeVerified: false); + } + + Future requestCode() async { + final trimmedNumber = state.phoneNumber.trim(); + + if (trimmedNumber.isEmpty) { + state = state.copyWith( + errorMessage: 'errorMessagePhoneIsEmpty', + codeVerified: false, + ); + return; + } + + final fullPhone = '${state.dialCode}$trimmedNumber'; + + state = state.copyWith( + isLoading: true, + errorMessage: '', + codeRequested: false, + codeVerified: false, + ); + + try { + await _linkPhoneUseCase.requestCode(phone: fullPhone); + if (!ref.mounted) return; + + state = state.copyWith( + isLoading: false, + errorMessage: '', + codeRequested: true, + ); + } catch (e) { + if (!ref.mounted) return; + + state = state.copyWith( + isLoading: false, + errorMessage: e.toString(), + codeRequested: false, + codeVerified: false, + ); + } + } + + Future 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, + ); + } + } + + void disposeControllers() { + phoneNumberController.removeListener(_onPhoneNumberChanged); + phoneNumberController.dispose(); + codeController.dispose(); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart new file mode 100644 index 00000000..70ffd15c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'link_phone_view_state.freezed.dart'; + +@freezed +abstract class LegacyLinkPhoneViewState with _$LegacyLinkPhoneViewState { + const factory LegacyLinkPhoneViewState({ + @Default('') String phoneNumber, + @Default('+34') String dialCode, + @Default('') String errorMessage, + @Default(false) bool isLoading, + @Default(false) bool codeRequested, + @Default(false) bool codeVerified, + }) = _LegacyLinkPhoneViewState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart new file mode 100644 index 00000000..30a86518 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart @@ -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 'link_phone_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacyLinkPhoneViewState { + + String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested; bool get codeVerified; +/// Create a copy of LegacyLinkPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyLinkPhoneViewStateCopyWith get copyWith => _$LegacyLinkPhoneViewStateCopyWithImpl(this as LegacyLinkPhoneViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyLinkPhoneViewState&&(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,codeVerified); + +@override +String toString() { + return 'LegacyLinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyLinkPhoneViewStateCopyWith<$Res> { + factory $LegacyLinkPhoneViewStateCopyWith(LegacyLinkPhoneViewState value, $Res Function(LegacyLinkPhoneViewState) _then) = _$LegacyLinkPhoneViewStateCopyWithImpl; +@useResult +$Res call({ + String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified +}); + + + + +} +/// @nodoc +class _$LegacyLinkPhoneViewStateCopyWithImpl<$Res> + implements $LegacyLinkPhoneViewStateCopyWith<$Res> { + _$LegacyLinkPhoneViewStateCopyWithImpl(this._self, this._then); + + final LegacyLinkPhoneViewState _self; + final $Res Function(LegacyLinkPhoneViewState) _then; + +/// Create a copy of LegacyLinkPhoneViewState +/// 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,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, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyLinkPhoneViewState]. +extension LegacyLinkPhoneViewStatePatterns on LegacyLinkPhoneViewState { +/// 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 Function( _LegacyLinkPhoneViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState() 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 Function( _LegacyLinkPhoneViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState(): +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? Function( _LegacyLinkPhoneViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState() 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 Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState() when $default != null: +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);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 Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified) $default,) {final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState(): +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);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? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified)? $default,) {final _that = this; +switch (_that) { +case _LegacyLinkPhoneViewState() when $default != null: +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyLinkPhoneViewState implements LegacyLinkPhoneViewState { + const _LegacyLinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false, this.codeVerified = false}); + + +@override@JsonKey() final String phoneNumber; +@override@JsonKey() final String dialCode; +@override@JsonKey() final String errorMessage; +@override@JsonKey() final bool isLoading; +@override@JsonKey() final bool codeRequested; +@override@JsonKey() final bool codeVerified; + +/// Create a copy of LegacyLinkPhoneViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyLinkPhoneViewStateCopyWith<_LegacyLinkPhoneViewState> get copyWith => __$LegacyLinkPhoneViewStateCopyWithImpl<_LegacyLinkPhoneViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyLinkPhoneViewState&&(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,codeVerified); + +@override +String toString() { + return 'LegacyLinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyLinkPhoneViewStateCopyWith<$Res> implements $LegacyLinkPhoneViewStateCopyWith<$Res> { + factory _$LegacyLinkPhoneViewStateCopyWith(_LegacyLinkPhoneViewState value, $Res Function(_LegacyLinkPhoneViewState) _then) = __$LegacyLinkPhoneViewStateCopyWithImpl; +@override @useResult +$Res call({ + String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified +}); + + + + +} +/// @nodoc +class __$LegacyLinkPhoneViewStateCopyWithImpl<$Res> + implements _$LegacyLinkPhoneViewStateCopyWith<$Res> { + __$LegacyLinkPhoneViewStateCopyWithImpl(this._self, this._then); + + final _LegacyLinkPhoneViewState _self; + final $Res Function(_LegacyLinkPhoneViewState) _then; + +/// Create a copy of LegacyLinkPhoneViewState +/// 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,Object? codeVerified = null,}) { + return _then(_LegacyLinkPhoneViewState( +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, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart new file mode 100644 index 00000000..84e4f551 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacyVerifyLinkPhoneCodeBuilder { + const LegacyVerifyLinkPhoneCodeBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyVerifyLinkPhoneCodeScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart new file mode 100644 index 00000000..9190097a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart @@ -0,0 +1,118 @@ +import 'package:legacy_auth/src/features/link_phone/presentation/state/link_phone_view_model.dart'; +import 'package:legacy_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'; + +class LegacyVerifyLinkPhoneCodeScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyVerifyLinkPhoneCodeScreen({ + super.key, + required this.navigationContract, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(legacyLinkPhoneViewModelProvider.notifier); + final viewState = ref.watch(legacyLinkPhoneViewModelProvider); + + 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: 30), + ), + const SizedBox(height: 24), + Text.rich( + TextSpan( + text: context.translate(I18n.verificationCodeSentTo), + children: [ + TextSpan( + text: '${viewState.dialCode}${viewState.phoneNumber}', + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + ], + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 48), + Text( + context.translate(I18n.enterCodeHere), + style: TextStyle(fontSize: 16), + ), + const SizedBox(height: 24), + + LegacyLinkPhoneCodeInput( + 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(legacyLinkPhoneViewModelProvider); + + if (updatedState.codeVerified) { + navigationContract.pushTo(AppRoutes.login); + } + }, + text: context.translate(I18n.enter), + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + const SizedBox(height: 24), + Text( + context.translate(I18n.didNotReceiveIt), + style: TextStyle( + fontSize: 18, + letterSpacing: 0, + height: 1.5, + ), + ), + const SizedBox(height: 8), + CustomTextButton( + onPressed: () => navigationContract.goBack(), + text: context.translate(I18n.tryAgain), + size: 18, + weight: FontWeight.w500, + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart new file mode 100644 index 00000000..2aaf507e --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class LegacyLinkPhoneCodeInput extends StatefulWidget { + const LegacyLinkPhoneCodeInput({ + super.key, + this.length = 6, + required this.onCodeChanged, + }); + + final int length; + final ValueChanged onCodeChanged; + + @override + State createState() => _LegacyLinkPhoneCodeInputState(); +} + +class _LegacyLinkPhoneCodeInputState extends State { + late final List _controllers; + late final List _focusNodes; + + @override + void initState() { + super.initState(); + _controllers = List.generate( + widget.length, + (_) => TextEditingController(), + ); + _focusNodes = List.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.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(), + ), + maxLength: 1, + onChanged: (value) => _onDigitChanged(i, value), + ), + ); + }), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/loading_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/loading_screen.dart new file mode 100644 index 00000000..c2c773b2 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/link_phone/presentation/widgets/loading_screen.dart @@ -0,0 +1,26 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class LegacyLoadingScreen extends StatelessWidget{ + const LegacyLoadingScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Expanded( + child: Center( + child: Column( + spacing: 50, + children: [ + Spacer(flex: 8), + SvgPicture.asset("assets/shared/images/logo_sf.svg"), + AppLoadingIndicator(), + Spacer(flex: 10) + ], + ), + ) + ), + ); + } +} \ No newline at end of file diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.dart new file mode 100644 index 00000000..c7dabae6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.dart @@ -0,0 +1,24 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'login_response_entity.freezed.dart'; + +@freezed +abstract class LegacyLoginResponseEntity with _$LegacyLoginResponseEntity { + const factory LegacyLoginResponseEntity({ + required String token, + @Default([]) + List availableMethods, + }) = _LegacyLoginResponseEntity; +} + +@freezed +abstract class LegacyAvailableMethodEntity with _$LegacyAvailableMethodEntity { + const factory LegacyAvailableMethodEntity({ + required String id, + required String userId, + required String methodType, + required String status, + required bool isDefault, + required int createdAt, + }) = _LegacyAvailableMethodEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.freezed.dart new file mode 100644 index 00000000..f85f0006 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/entities/login_response_entity.freezed.dart @@ -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 'login_response_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacyLoginResponseEntity { + + String get token; List get availableMethods; +/// Create a copy of LegacyLoginResponseEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyLoginResponseEntityCopyWith get copyWith => _$LegacyLoginResponseEntityCopyWithImpl(this as LegacyLoginResponseEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyLoginResponseEntity&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other.availableMethods, availableMethods)); +} + + +@override +int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(availableMethods)); + +@override +String toString() { + return 'LegacyLoginResponseEntity(token: $token, availableMethods: $availableMethods)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyLoginResponseEntityCopyWith<$Res> { + factory $LegacyLoginResponseEntityCopyWith(LegacyLoginResponseEntity value, $Res Function(LegacyLoginResponseEntity) _then) = _$LegacyLoginResponseEntityCopyWithImpl; +@useResult +$Res call({ + String token, List availableMethods +}); + + + + +} +/// @nodoc +class _$LegacyLoginResponseEntityCopyWithImpl<$Res> + implements $LegacyLoginResponseEntityCopyWith<$Res> { + _$LegacyLoginResponseEntityCopyWithImpl(this._self, this._then); + + final LegacyLoginResponseEntity _self; + final $Res Function(LegacyLoginResponseEntity) _then; + +/// Create a copy of LegacyLoginResponseEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? token = null,Object? availableMethods = null,}) { + return _then(_self.copyWith( +token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,availableMethods: null == availableMethods ? _self.availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyLoginResponseEntity]. +extension LegacyLoginResponseEntityPatterns on LegacyLoginResponseEntity { +/// 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 Function( _LegacyLoginResponseEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity() 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 Function( _LegacyLoginResponseEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity(): +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? Function( _LegacyLoginResponseEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity() 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 Function( String token, List availableMethods)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity() when $default != null: +return $default(_that.token,_that.availableMethods);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 Function( String token, List availableMethods) $default,) {final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity(): +return $default(_that.token,_that.availableMethods);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? Function( String token, List availableMethods)? $default,) {final _that = this; +switch (_that) { +case _LegacyLoginResponseEntity() when $default != null: +return $default(_that.token,_that.availableMethods);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyLoginResponseEntity implements LegacyLoginResponseEntity { + const _LegacyLoginResponseEntity({required this.token, final List availableMethods = const []}): _availableMethods = availableMethods; + + +@override final String token; + final List _availableMethods; +@override@JsonKey() List get availableMethods { + if (_availableMethods is EqualUnmodifiableListView) return _availableMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_availableMethods); +} + + +/// Create a copy of LegacyLoginResponseEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyLoginResponseEntityCopyWith<_LegacyLoginResponseEntity> get copyWith => __$LegacyLoginResponseEntityCopyWithImpl<_LegacyLoginResponseEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyLoginResponseEntity&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other._availableMethods, _availableMethods)); +} + + +@override +int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(_availableMethods)); + +@override +String toString() { + return 'LegacyLoginResponseEntity(token: $token, availableMethods: $availableMethods)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyLoginResponseEntityCopyWith<$Res> implements $LegacyLoginResponseEntityCopyWith<$Res> { + factory _$LegacyLoginResponseEntityCopyWith(_LegacyLoginResponseEntity value, $Res Function(_LegacyLoginResponseEntity) _then) = __$LegacyLoginResponseEntityCopyWithImpl; +@override @useResult +$Res call({ + String token, List availableMethods +}); + + + + +} +/// @nodoc +class __$LegacyLoginResponseEntityCopyWithImpl<$Res> + implements _$LegacyLoginResponseEntityCopyWith<$Res> { + __$LegacyLoginResponseEntityCopyWithImpl(this._self, this._then); + + final _LegacyLoginResponseEntity _self; + final $Res Function(_LegacyLoginResponseEntity) _then; + +/// Create a copy of LegacyLoginResponseEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? token = null,Object? availableMethods = null,}) { + return _then(_LegacyLoginResponseEntity( +token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,availableMethods: null == availableMethods ? _self._availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List, + )); +} + + +} + +/// @nodoc +mixin _$LegacyAvailableMethodEntity { + + String get id; String get userId; String get methodType; String get status; bool get isDefault; int get createdAt; +/// Create a copy of LegacyAvailableMethodEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyAvailableMethodEntityCopyWith get copyWith => _$LegacyAvailableMethodEntityCopyWithImpl(this as LegacyAvailableMethodEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyAvailableMethodEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.methodType, methodType) || other.methodType == methodType)&&(identical(other.status, status) || other.status == status)&&(identical(other.isDefault, isDefault) || other.isDefault == isDefault)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,userId,methodType,status,isDefault,createdAt); + +@override +String toString() { + return 'LegacyAvailableMethodEntity(id: $id, userId: $userId, methodType: $methodType, status: $status, isDefault: $isDefault, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyAvailableMethodEntityCopyWith<$Res> { + factory $LegacyAvailableMethodEntityCopyWith(LegacyAvailableMethodEntity value, $Res Function(LegacyAvailableMethodEntity) _then) = _$LegacyAvailableMethodEntityCopyWithImpl; +@useResult +$Res call({ + String id, String userId, String methodType, String status, bool isDefault, int createdAt +}); + + + + +} +/// @nodoc +class _$LegacyAvailableMethodEntityCopyWithImpl<$Res> + implements $LegacyAvailableMethodEntityCopyWith<$Res> { + _$LegacyAvailableMethodEntityCopyWithImpl(this._self, this._then); + + final LegacyAvailableMethodEntity _self; + final $Res Function(LegacyAvailableMethodEntity) _then; + +/// Create a copy of LegacyAvailableMethodEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? userId = null,Object? methodType = null,Object? status = null,Object? isDefault = null,Object? createdAt = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,methodType: null == methodType ? _self.methodType : methodType // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as String,isDefault: null == isDefault ? _self.isDefault : isDefault // ignore: cast_nullable_to_non_nullable +as bool,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyAvailableMethodEntity]. +extension LegacyAvailableMethodEntityPatterns on LegacyAvailableMethodEntity { +/// 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 Function( _LegacyAvailableMethodEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity() 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 Function( _LegacyAvailableMethodEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity(): +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? Function( _LegacyAvailableMethodEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity() 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 Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity() when $default != null: +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);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 Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt) $default,) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity(): +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);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? Function( String id, String userId, String methodType, String status, bool isDefault, int createdAt)? $default,) {final _that = this; +switch (_that) { +case _LegacyAvailableMethodEntity() when $default != null: +return $default(_that.id,_that.userId,_that.methodType,_that.status,_that.isDefault,_that.createdAt);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyAvailableMethodEntity implements LegacyAvailableMethodEntity { + const _LegacyAvailableMethodEntity({required this.id, required this.userId, required this.methodType, required this.status, required this.isDefault, required this.createdAt}); + + +@override final String id; +@override final String userId; +@override final String methodType; +@override final String status; +@override final bool isDefault; +@override final int createdAt; + +/// Create a copy of LegacyAvailableMethodEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyAvailableMethodEntityCopyWith<_LegacyAvailableMethodEntity> get copyWith => __$LegacyAvailableMethodEntityCopyWithImpl<_LegacyAvailableMethodEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyAvailableMethodEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.methodType, methodType) || other.methodType == methodType)&&(identical(other.status, status) || other.status == status)&&(identical(other.isDefault, isDefault) || other.isDefault == isDefault)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,userId,methodType,status,isDefault,createdAt); + +@override +String toString() { + return 'LegacyAvailableMethodEntity(id: $id, userId: $userId, methodType: $methodType, status: $status, isDefault: $isDefault, createdAt: $createdAt)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyAvailableMethodEntityCopyWith<$Res> implements $LegacyAvailableMethodEntityCopyWith<$Res> { + factory _$LegacyAvailableMethodEntityCopyWith(_LegacyAvailableMethodEntity value, $Res Function(_LegacyAvailableMethodEntity) _then) = __$LegacyAvailableMethodEntityCopyWithImpl; +@override @useResult +$Res call({ + String id, String userId, String methodType, String status, bool isDefault, int createdAt +}); + + + + +} +/// @nodoc +class __$LegacyAvailableMethodEntityCopyWithImpl<$Res> + implements _$LegacyAvailableMethodEntityCopyWith<$Res> { + __$LegacyAvailableMethodEntityCopyWithImpl(this._self, this._then); + + final _LegacyAvailableMethodEntity _self; + final $Res Function(_LegacyAvailableMethodEntity) _then; + +/// Create a copy of LegacyAvailableMethodEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? userId = null,Object? methodType = null,Object? status = null,Object? isDefault = null,Object? createdAt = null,}) { + return _then(_LegacyAvailableMethodEntity( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,methodType: null == methodType ? _self.methodType : methodType // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as String,isDefault: null == isDefault ? _self.isDefault : isDefault // ignore: cast_nullable_to_non_nullable +as bool,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable +as int, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case.dart new file mode 100644 index 00000000..d1510301 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case.dart @@ -0,0 +1,8 @@ +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; + +abstract class LegacyLoginUseCase { + Future login({ + required String email, + required String password, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case_impl.dart new file mode 100644 index 00000000..84b5f05d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/login_use_case_impl.dart @@ -0,0 +1,17 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; +import 'package:legacy_auth/src/features/login/domain/login_use_case.dart'; + +class LegacyLoginUseCaseImpl implements LegacyLoginUseCase { + LegacyLoginUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future login({ + required String email, + required String password, + }) { + return _repository.login(email: email, password: password); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case.dart new file mode 100644 index 00000000..0c3c0265 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case.dart @@ -0,0 +1,6 @@ +abstract class LegacyTwoFARequestCodeUseCase { + Future twoFARequestCode({ + required String token, + required String methodType, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case_impl.dart new file mode 100644 index 00000000..a06ca034 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_request_code_use_case_impl.dart @@ -0,0 +1,16 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_request_code_use_case.dart'; + +class LegacyTwoFARequestCodeUseCaseImpl implements LegacyTwoFARequestCodeUseCase { + LegacyTwoFARequestCodeUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future twoFARequestCode({ + required String token, + required String methodType, + }) { + return _repository.twoFARequestCode(token: token, methodType: methodType); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case.dart new file mode 100644 index 00000000..bf34f66f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case.dart @@ -0,0 +1,7 @@ +abstract class LegacyTwoFASendCodeUseCase { + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case_impl.dart new file mode 100644 index 00000000..49d10aaf --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/domain/two_fa_send_code_use_case_impl.dart @@ -0,0 +1,21 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_send_code_use_case.dart'; + +class LegacyTwoFASendCodeUseCaseImpl implements LegacyTwoFASendCodeUseCase { + LegacyTwoFASendCodeUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future twoFASendCode({ + required String token, + required String code, + required String methodType, + }) { + return _repository.twoFASendCode( + token: token, + methodType: methodType, + code: code, + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/login_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/login_builder.dart new file mode 100644 index 00000000..d62debb3 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/login_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_auth/src/features/login/presentation/login_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 LegacyLoginBuilder { + const LegacyLoginBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyLoginScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart new file mode 100644 index 00000000..46324e01 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/loading_google_screen.dart @@ -0,0 +1,29 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +class LegacyLoadingGoogleScreen extends StatelessWidget { + const LegacyLoadingGoogleScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Expanded( + child: Center( + child: Column( + spacing: 50, + children: [ + Spacer(flex: 8), + Text( + "Continuar con Google", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30), + ), + AppLoadingIndicator(), + Text("Redirigiendo a Google"), + Spacer(flex: 10), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart new file mode 100644 index 00000000..03a9510c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/login_screen.dart @@ -0,0 +1,263 @@ +import 'package:legacy_auth/src/features/login/presentation/state/login_view_model.dart'; +import 'package:legacy_auth/src/features/login/presentation/widgets/field_error_text.dart'; +import 'package:legacy_auth/src/features/login/presentation/widgets/two_factor_sheet_launcher.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 LegacyLoginScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyLoginScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + final bool isLoading = ref.watch( + legacyLoginViewModelProvider.select((s) => s.isLoading), + ); + + ref.listen( + legacyLoginViewModelProvider.select( + (s) => ( + error: s.errorMessage, + twoFA: s.twoFARequested, + verified: s.twoFAVerified, + ), + ), + (previous, next) { + if (next.error.isNotEmpty && !next.twoFA) { + showTopSnackbar( + context, + message: context.translate(next.error), + type: MessageType.error, + ); + } + if (next.twoFA && previous?.twoFA != true) { + showTwoFactorSheet(context); + } + if (next.verified) { + showTopSnackbar( + context, + message: context.translate(I18n.loginSuccess), + type: MessageType.success, + ); + navigationContract.goTo(AppRoutes.controlPanel); + } + }, + ); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: SafeArea( + child: AbsorbPointer( + absorbing: isLoading, + child: SingleChildScrollView( + padding: EdgeInsets.symmetric(horizontal: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _Header(theme: theme), + SizedBox(height: 48), + _EmailSection(), + SizedBox(height: 24), + _PasswordSection( + onSubmitted: () { + FocusManager.instance.primaryFocus?.unfocus(); + ref.read(legacyLoginViewModelProvider.notifier).login(); + }, + ), + SizedBox(height: 16), + _ForgotPassword(navigationContract: navigationContract), + SizedBox(height: 30), + _SignInSection( + theme: theme, + onSignIn: () { + FocusManager.instance.primaryFocus?.unfocus(); + ref.read(legacyLoginViewModelProvider.notifier).login(); + }, + ), + SizedBox(height: 30), + _Footer(navigationContract: navigationContract), + ], + ), + ), + ), + ), + ); + } +} + +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: 54, + ), + Text( + context.translate(I18n.welcome), + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold), + ), + ], + ); + } +} + +class _EmailSection extends ConsumerWidget { + const _EmailSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final vm = ref.read(legacyLoginViewModelProvider.notifier); + final String emailErrorKey = ref.watch( + legacyLoginViewModelProvider.select((s) => s.emailError), + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + CustomTextField( + hint: context.translate(I18n.username), + label: context.translate(I18n.username), + controller: vm.emailController, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + ), + FieldErrorText(errorKey: emailErrorKey), + ], + ); + } +} + +class _PasswordSection extends ConsumerWidget { + const _PasswordSection({required this.onSubmitted}); + final VoidCallback onSubmitted; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final vm = ref.read(legacyLoginViewModelProvider.notifier); + final bool passwordVisible = ref.watch( + legacyLoginViewModelProvider.select((s) => s.passwordVisible), + ); + final String passwordErrorKey = ref.watch( + legacyLoginViewModelProvider.select((s) => s.passwordError), + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + CustomTextField( + showPassword: passwordVisible, + label: context.translate(I18n.password), + hint: '********', + controller: vm.passwordController, + textInputAction: TextInputAction.done, + onSubmitted: (_) => onSubmitted(), + ), + FieldErrorText(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( + legacyLoginViewModelProvider.select((s) => s.isLoading), + ); + + return Align( + alignment: Alignment.topLeft, + child: CustomTextButton( + text: context.translate(I18n.forgotPassword), + onPressed: isLoading + ? () {} + : () => navigationContract.pushTo(AppRoutes.legacyRecoverPassword), + size: 16, + ), + ); + } +} + +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( + legacyLoginViewModelProvider.select((s) => s.isLoading), + ); + + 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, + ), + ], + ); + } +} + +class _Footer extends ConsumerWidget { + const _Footer({required this.navigationContract}); + final NavigationContract navigationContract; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final bool isLoading = ref.watch( + legacyLoginViewModelProvider.select((s) => s.isLoading), + ); + + return Column( + children: [ + Text( + context.translate(I18n.dontHaveAccount), + style: const TextStyle(fontSize: 18, letterSpacing: 0), + ), + TextButton( + onPressed: isLoading + ? null + : () => navigationContract.pushTo(AppRoutes.legacySignup), + child: Text( + context.translate(I18n.createOneNow), + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + letterSpacing: 0, + ), + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/login_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/login_provider.dart new file mode 100644 index 00000000..b5e37261 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/login_provider.dart @@ -0,0 +1,9 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/login/domain/login_use_case.dart'; +import 'package:legacy_auth/src/features/login/domain/login_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyLoginUseCaseProvider = Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyLoginUseCaseImpl(authRepository); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_request_code_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_request_code_provider.dart new file mode 100644 index 00000000..fad9c918 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_request_code_provider.dart @@ -0,0 +1,10 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_request_code_use_case.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_request_code_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyTwoFARequestCodeUseCaseProvider = + Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyTwoFARequestCodeUseCaseImpl(authRepository); + }); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_send_code_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_send_code_provider.dart new file mode 100644 index 00000000..eb3a6ccb --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/providers/two_fa_send_code_provider.dart @@ -0,0 +1,11 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_send_code_use_case.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_send_code_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyTwoFASendCodeUseCaseProvider = Provider.autoDispose( + (ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyTwoFASendCodeUseCaseImpl(authRepository); + }, +); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart new file mode 100644 index 00000000..55252875 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_model.dart @@ -0,0 +1,271 @@ +import 'dart:async'; + +import 'package:legacy_auth/src/features/login/domain/login_use_case.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_request_code_use_case.dart'; +import 'package:legacy_auth/src/features/login/domain/two_fa_send_code_use_case.dart'; +import 'package:legacy_auth/src/features/login/presentation/providers/login_provider.dart'; +import 'package:legacy_auth/src/features/login/presentation/providers/two_fa_request_code_provider.dart'; +import 'package:legacy_auth/src/features/login/presentation/providers/two_fa_send_code_provider.dart'; +import 'package:legacy_auth/src/features/login/presentation/state/login_view_state.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:sf_shared/sf_shared.dart'; + +final legacyLoginViewModelProvider = + NotifierProvider.autoDispose( + LegacyLoginViewModel.new, + ); + +class LegacyLoginViewModel extends Notifier { + late final LegacyLoginUseCase _loginUseCase; + late final LegacyTwoFARequestCodeUseCase _twoFARequestCodeUseCase; + late final LegacyTwoFASendCodeUseCase _twoFASendCodeUseCase; + late final GetUserInfoUseCase _getUserInfoUseCase; + + late final TextEditingController emailController; + late final TextEditingController passwordController; + + Timer? _cooldownTimer; + + static const int resendCooldownSeconds = 30; + + static final RegExp _emailRegex = RegExp( + r'^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$', + caseSensitive: false, + ); + + @override + LegacyLoginViewState build() { + _loginUseCase = ref.read(legacyLoginUseCaseProvider); + _twoFARequestCodeUseCase = ref.read(legacyTwoFARequestCodeUseCaseProvider); + _twoFASendCodeUseCase = ref.read(legacyTwoFASendCodeUseCaseProvider); + _getUserInfoUseCase = ref.read(getUserInfoUseCaseProvider); + + emailController = TextEditingController(); + emailController.addListener(_onEmailChanged); + + passwordController = TextEditingController(); + passwordController.addListener(_onPasswordChanged); + + ref.onDispose(_dispose); + + return const LegacyLoginViewState(); + } + + void _onEmailChanged() { + final value = emailController.text; + if (value == state.email) return; + state = state.copyWith( + email: value, + errorMessage: '', + emailError: state.showErrors ? _validateEmail(value) : state.emailError, + ); + } + + void _onPasswordChanged() { + final value = passwordController.text; + if (value == state.password) return; + state = state.copyWith( + password: value, + errorMessage: '', + passwordError: + state.showErrors ? _validatePassword(value) : state.passwordError, + ); + } + + void _dispose() { + _cooldownTimer?.cancel(); + emailController.removeListener(_onEmailChanged); + emailController.dispose(); + passwordController.removeListener(_onPasswordChanged); + passwordController.dispose(); + } + + void togglePasswordVisible() { + state = state.copyWith(passwordVisible: !state.passwordVisible); + } + + String _validateEmail(String value) { + final email = value.trim(); + if (email.isEmpty) return I18n.errorEmailRequired; + if (!_emailRegex.hasMatch(email)) return I18n.errorEmailInvalid; + return ''; + } + + String _validatePassword(String value) { + final password = value.trim(); + if (password.isEmpty) return I18n.errorPasswordRequired; + if (password.length < 6) return I18n.errorPasswordMinLength; + return ''; + } + + bool _validateForm() { + final emailError = _validateEmail(state.email); + final passwordError = _validatePassword(state.password); + + state = state.copyWith( + showErrors: true, + emailError: emailError, + passwordError: passwordError, + errorMessage: '', + ); + + return emailError.isEmpty && passwordError.isEmpty; + } + + Future login() async { + if (!_validateForm()) return; + + final email = state.email.trim(); + final password = state.password.trim(); + + state = state.copyWith( + isLoading: true, + twoFARequested: false, + twoFAVerified: false, + ); + + try { + final response = await _loginUseCase.login( + email: email, + password: password, + ); + + if (!ref.mounted) return; + + state = state.copyWith( + token: response.token, + availableMethods: response.availableMethods, + code: '', + ); + } catch (e) { + if (!ref.mounted) return; + + state = state.copyWith( + isLoading: false, + errorMessage: _formatErrorMessage(e), + ); + return; + } + + await _requestTwoFACode(updateLoading: true); + } + + void dismissTwoFA() { + state = state.copyWith(twoFARequested: false); + } + + void setCode(String code) { + state = state.copyWith(code: code, codeError: ''); + } + + String _validateCode(String value) { + final code = value.trim(); + if (code.isEmpty) return I18n.errorTwoFactorCodeRequired; + if (code.length != 6) return I18n.errorTwoFactorCodeInvalidLength; + return ''; + } + + Future _requestTwoFACode({bool updateLoading = false}) async { + if (state.availableMethods.isEmpty) { + state = state.copyWith( + errorMessage: I18n.errorTwoFactorNoMethods, + isLoading: updateLoading ? false : state.isLoading, + ); + return; + } + + try { + await _twoFARequestCodeUseCase.twoFARequestCode( + token: state.token, + methodType: state.availableMethods.first.methodType, + ); + + if (!ref.mounted) return; + + _startResendCooldown(); + state = state.copyWith( + twoFARequested: true, + isLoading: updateLoading ? false : state.isLoading, + ); + } catch (e) { + if (!ref.mounted) return; + + state = state.copyWith( + errorMessage: _formatErrorMessage(e), + isLoading: updateLoading ? false : state.isLoading, + ); + } + } + + void _startResendCooldown() { + _cooldownTimer?.cancel(); + state = state.copyWith(resendCooldown: resendCooldownSeconds); + _cooldownTimer = Timer.periodic( + const Duration(seconds: 1), + (_) { + if (!ref.mounted) { + _cooldownTimer?.cancel(); + return; + } + final next = state.resendCooldown - 1; + state = state.copyWith(resendCooldown: next); + if (next <= 0) _cooldownTimer?.cancel(); + }, + ); + } + + Future submitTwoFACode() async { + final codeError = _validateCode(state.code); + if (codeError.isNotEmpty) { + state = state.copyWith(showErrors: true, codeError: codeError); + return; + } + + if (state.availableMethods.isEmpty) return; + + final method = state.availableMethods.firstWhere( + (m) => m.isDefault, + orElse: () => state.availableMethods.first, + ); + + state = state.copyWith(isLoading: true, errorMessage: '', codeError: ''); + + try { + await _twoFASendCodeUseCase.twoFASendCode( + token: state.token, + code: state.code.trim(), + methodType: method.methodType, + ); + + if (!ref.mounted) return; + + await _getUserInfoUseCase.getUserInfo(); + + if (!ref.mounted) return; + + state = state.copyWith(isLoading: false, twoFAVerified: true); + } catch (e) { + if (!ref.mounted) return; + + state = state.copyWith( + isLoading: false, + errorMessage: _formatErrorMessage(e), + ); + } + } + + Future resendCode() async { + state = state.copyWith(code: '', isLoading: true); + await _requestTwoFACode(updateLoading: true); + } + + static String _formatErrorMessage(Object error) { + final raw = error.toString(); + if (raw.startsWith('Exception: ')) { + return raw.substring('Exception: '.length); + } + return raw; + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.dart new file mode 100644 index 00000000..dcac7e76 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.dart @@ -0,0 +1,26 @@ +import 'package:legacy_auth/src/features/login/domain/entities/login_response_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'login_view_state.freezed.dart'; + +@freezed +abstract class LegacyLoginViewState with _$LegacyLoginViewState { + const factory LegacyLoginViewState({ + @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([]) + List availableMethods, + @Default('') String token, + @Default(false) bool twoFARequested, + @Default('') String code, + @Default('') String codeError, + @Default(0) int resendCooldown, + @Default(false) bool twoFAVerified, + }) = _LegacyLoginViewState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.freezed.dart new file mode 100644 index 00000000..2f63909a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/state/login_view_state.freezed.dart @@ -0,0 +1,319 @@ +// 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 value) => value; +/// @nodoc +mixin _$LegacyLoginViewState { + + String get email; String get password; bool get passwordVisible; String get emailError; String get passwordError; String get errorMessage; bool get showErrors; bool get isLoading; List get availableMethods; String get token; bool get twoFARequested; String get code; String get codeError; int get resendCooldown; bool get twoFAVerified; +/// Create a copy of LegacyLoginViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyLoginViewStateCopyWith get copyWith => _$LegacyLoginViewStateCopyWithImpl(this as LegacyLoginViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyLoginViewState&&(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)&&const DeepCollectionEquality().equals(other.availableMethods, availableMethods)&&(identical(other.token, token) || other.token == token)&&(identical(other.twoFARequested, twoFARequested) || other.twoFARequested == twoFARequested)&&(identical(other.code, code) || other.code == code)&&(identical(other.codeError, codeError) || other.codeError == codeError)&&(identical(other.resendCooldown, resendCooldown) || other.resendCooldown == resendCooldown)&&(identical(other.twoFAVerified, twoFAVerified) || other.twoFAVerified == twoFAVerified)); +} + + +@override +int get hashCode => Object.hash(runtimeType,email,password,passwordVisible,emailError,passwordError,errorMessage,showErrors,isLoading,const DeepCollectionEquality().hash(availableMethods),token,twoFARequested,code,codeError,resendCooldown,twoFAVerified); + +@override +String toString() { + return 'LegacyLoginViewState(email: $email, password: $password, passwordVisible: $passwordVisible, emailError: $emailError, passwordError: $passwordError, errorMessage: $errorMessage, showErrors: $showErrors, isLoading: $isLoading, availableMethods: $availableMethods, token: $token, twoFARequested: $twoFARequested, code: $code, codeError: $codeError, resendCooldown: $resendCooldown, twoFAVerified: $twoFAVerified)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyLoginViewStateCopyWith<$Res> { + factory $LegacyLoginViewStateCopyWith(LegacyLoginViewState value, $Res Function(LegacyLoginViewState) _then) = _$LegacyLoginViewStateCopyWithImpl; +@useResult +$Res call({ + String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, List availableMethods, String token, bool twoFARequested, String code, String codeError, int resendCooldown, bool twoFAVerified +}); + + + + +} +/// @nodoc +class _$LegacyLoginViewStateCopyWithImpl<$Res> + implements $LegacyLoginViewStateCopyWith<$Res> { + _$LegacyLoginViewStateCopyWithImpl(this._self, this._then); + + final LegacyLoginViewState _self; + final $Res Function(LegacyLoginViewState) _then; + +/// Create a copy of LegacyLoginViewState +/// 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? availableMethods = null,Object? token = null,Object? twoFARequested = null,Object? code = null,Object? codeError = null,Object? resendCooldown = null,Object? twoFAVerified = 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,availableMethods: null == availableMethods ? _self.availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,twoFARequested: null == twoFARequested ? _self.twoFARequested : twoFARequested // ignore: cast_nullable_to_non_nullable +as bool,code: null == code ? _self.code : code // ignore: cast_nullable_to_non_nullable +as String,codeError: null == codeError ? _self.codeError : codeError // ignore: cast_nullable_to_non_nullable +as String,resendCooldown: null == resendCooldown ? _self.resendCooldown : resendCooldown // ignore: cast_nullable_to_non_nullable +as int,twoFAVerified: null == twoFAVerified ? _self.twoFAVerified : twoFAVerified // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyLoginViewState]. +extension LegacyLoginViewStatePatterns on LegacyLoginViewState { +/// 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 Function( _LegacyLoginViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyLoginViewState() 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 Function( _LegacyLoginViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginViewState(): +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? Function( _LegacyLoginViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyLoginViewState() 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 Function( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, List availableMethods, String token, bool twoFARequested, String code, String codeError, int resendCooldown, bool twoFAVerified)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyLoginViewState() when $default != null: +return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.availableMethods,_that.token,_that.twoFARequested,_that.code,_that.codeError,_that.resendCooldown,_that.twoFAVerified);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 Function( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, List availableMethods, String token, bool twoFARequested, String code, String codeError, int resendCooldown, bool twoFAVerified) $default,) {final _that = this; +switch (_that) { +case _LegacyLoginViewState(): +return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.availableMethods,_that.token,_that.twoFARequested,_that.code,_that.codeError,_that.resendCooldown,_that.twoFAVerified);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? Function( String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, List availableMethods, String token, bool twoFARequested, String code, String codeError, int resendCooldown, bool twoFAVerified)? $default,) {final _that = this; +switch (_that) { +case _LegacyLoginViewState() when $default != null: +return $default(_that.email,_that.password,_that.passwordVisible,_that.emailError,_that.passwordError,_that.errorMessage,_that.showErrors,_that.isLoading,_that.availableMethods,_that.token,_that.twoFARequested,_that.code,_that.codeError,_that.resendCooldown,_that.twoFAVerified);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyLoginViewState implements LegacyLoginViewState { + const _LegacyLoginViewState({this.email = '', this.password = '', this.passwordVisible = false, this.emailError = '', this.passwordError = '', this.errorMessage = '', this.showErrors = false, this.isLoading = false, final List availableMethods = const [], this.token = '', this.twoFARequested = false, this.code = '', this.codeError = '', this.resendCooldown = 0, this.twoFAVerified = false}): _availableMethods = availableMethods; + + +@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; + final List _availableMethods; +@override@JsonKey() List get availableMethods { + if (_availableMethods is EqualUnmodifiableListView) return _availableMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_availableMethods); +} + +@override@JsonKey() final String token; +@override@JsonKey() final bool twoFARequested; +@override@JsonKey() final String code; +@override@JsonKey() final String codeError; +@override@JsonKey() final int resendCooldown; +@override@JsonKey() final bool twoFAVerified; + +/// Create a copy of LegacyLoginViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyLoginViewStateCopyWith<_LegacyLoginViewState> get copyWith => __$LegacyLoginViewStateCopyWithImpl<_LegacyLoginViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyLoginViewState&&(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)&&const DeepCollectionEquality().equals(other._availableMethods, _availableMethods)&&(identical(other.token, token) || other.token == token)&&(identical(other.twoFARequested, twoFARequested) || other.twoFARequested == twoFARequested)&&(identical(other.code, code) || other.code == code)&&(identical(other.codeError, codeError) || other.codeError == codeError)&&(identical(other.resendCooldown, resendCooldown) || other.resendCooldown == resendCooldown)&&(identical(other.twoFAVerified, twoFAVerified) || other.twoFAVerified == twoFAVerified)); +} + + +@override +int get hashCode => Object.hash(runtimeType,email,password,passwordVisible,emailError,passwordError,errorMessage,showErrors,isLoading,const DeepCollectionEquality().hash(_availableMethods),token,twoFARequested,code,codeError,resendCooldown,twoFAVerified); + +@override +String toString() { + return 'LegacyLoginViewState(email: $email, password: $password, passwordVisible: $passwordVisible, emailError: $emailError, passwordError: $passwordError, errorMessage: $errorMessage, showErrors: $showErrors, isLoading: $isLoading, availableMethods: $availableMethods, token: $token, twoFARequested: $twoFARequested, code: $code, codeError: $codeError, resendCooldown: $resendCooldown, twoFAVerified: $twoFAVerified)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyLoginViewStateCopyWith<$Res> implements $LegacyLoginViewStateCopyWith<$Res> { + factory _$LegacyLoginViewStateCopyWith(_LegacyLoginViewState value, $Res Function(_LegacyLoginViewState) _then) = __$LegacyLoginViewStateCopyWithImpl; +@override @useResult +$Res call({ + String email, String password, bool passwordVisible, String emailError, String passwordError, String errorMessage, bool showErrors, bool isLoading, List availableMethods, String token, bool twoFARequested, String code, String codeError, int resendCooldown, bool twoFAVerified +}); + + + + +} +/// @nodoc +class __$LegacyLoginViewStateCopyWithImpl<$Res> + implements _$LegacyLoginViewStateCopyWith<$Res> { + __$LegacyLoginViewStateCopyWithImpl(this._self, this._then); + + final _LegacyLoginViewState _self; + final $Res Function(_LegacyLoginViewState) _then; + +/// Create a copy of LegacyLoginViewState +/// 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? availableMethods = null,Object? token = null,Object? twoFARequested = null,Object? code = null,Object? codeError = null,Object? resendCooldown = null,Object? twoFAVerified = null,}) { + return _then(_LegacyLoginViewState( +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,availableMethods: null == availableMethods ? _self._availableMethods : availableMethods // ignore: cast_nullable_to_non_nullable +as List,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String,twoFARequested: null == twoFARequested ? _self.twoFARequested : twoFARequested // ignore: cast_nullable_to_non_nullable +as bool,code: null == code ? _self.code : code // ignore: cast_nullable_to_non_nullable +as String,codeError: null == codeError ? _self.codeError : codeError // ignore: cast_nullable_to_non_nullable +as String,resendCooldown: null == resendCooldown ? _self.resendCooldown : resendCooldown // ignore: cast_nullable_to_non_nullable +as int,twoFAVerified: null == twoFAVerified ? _self.twoFAVerified : twoFAVerified // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/field_error_text.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/field_error_text.dart new file mode 100644 index 00000000..e21d9307 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/field_error_text.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class FieldErrorText extends StatelessWidget { + const FieldErrorText({super.key, required this.errorKey}); + final String errorKey; + + @override + Widget build(BuildContext context) { + if (errorKey.isEmpty) return const SizedBox.shrink(); + + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + context.translate(errorKey), + style: TextStyle( + color: Theme.of(context).colorScheme.error, + fontSize: 12, + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/otp_code_fields.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/otp_code_fields.dart new file mode 100644 index 00000000..f1da8fb7 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/otp_code_fields.dart @@ -0,0 +1,211 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class LegacyOtpCodeFields extends StatefulWidget { + const LegacyOtpCodeFields({ + 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? onChanged; + final ValueChanged? onCompleted; + final double boxSize; + final double gap; + + @override + State createState() => _LegacyOtpCodeFieldsState(); +} + +class _LegacyOtpCodeFieldsState extends State { + late final List _controllers; + late final List _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, + ), + ), + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart new file mode 100644 index 00000000..68e60e07 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart @@ -0,0 +1,129 @@ +import 'dart:async'; + +import 'package:legacy_auth/src/features/login/presentation/widgets/otp_code_fields.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +class LegacyTwoFactorBottomSheetView extends StatelessWidget { + const LegacyTwoFactorBottomSheetView({ + super.key, + required this.theme, + required this.title, + required this.subtitle, + required this.verifyText, + required this.resendText, + required this.closeText, + required this.isOtpLoading, + required this.canResend, + required this.otpCode, + required this.otpErrorText, + required this.onChanged, + required this.onVerify, + required this.onResend, + required this.onClose, + }); + + final ThemePort theme; + + final String title; + final String subtitle; + final String verifyText; + final String resendText; + final String closeText; + + final bool isOtpLoading; + final bool canResend; + final String otpCode; + final String otpErrorText; + + final ValueChanged onChanged; + final Future Function() onVerify; + final Future Function() onResend; + 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(12, 12, 12, 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), + + LegacyOtpCodeFields( + length: 6, + enabled: !isOtpLoading, + errorText: otpErrorText.isEmpty ? null : otpErrorText, + onChanged: onChanged, + onCompleted: (_) { + if (isOtpLoading || !_isValidOtp) return; + unawaited(onVerify()); + }, + ), + const SizedBox(height: 20), + + 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, + ), + + const SizedBox(height: 12), + + TextButton( + onPressed: canResend ? () => unawaited(onResend()) : null, + child: Text(resendText), + ), + + const SizedBox(height: 4), + + TextButton( + onPressed: isOtpLoading ? null : onClose, + child: Text(closeText), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_sheet_launcher.dart b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_sheet_launcher.dart new file mode 100644 index 00000000..0b0d610a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/login/presentation/widgets/two_factor_sheet_launcher.dart @@ -0,0 +1,86 @@ +import 'package:legacy_auth/src/features/login/presentation/state/login_view_model.dart'; +import 'package:legacy_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:sf_localizations/sf_localizations.dart'; + +void showTwoFactorSheet(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useSafeArea: true, + isDismissible: false, + enableDrag: false, + backgroundColor: Colors.transparent, + builder: (sheetContext) { + return Consumer( + builder: (sheetContext, ref, _) { + final theme = ref.watch(themePortProvider); + final vm = ref.read(legacyLoginViewModelProvider.notifier); + + final otpErrorKey = ref.watch( + legacyLoginViewModelProvider.select((s) => s.codeError), + ); + final isLoading = ref.watch( + legacyLoginViewModelProvider.select((s) => s.isLoading), + ); + final code = ref.watch( + legacyLoginViewModelProvider.select((s) => s.code), + ); + final resendCooldown = ref.watch( + legacyLoginViewModelProvider.select((s) => s.resendCooldown), + ); + + final otpErrorText = + otpErrorKey.isEmpty ? '' : sheetContext.translate(otpErrorKey); + + ref.listen( + legacyLoginViewModelProvider.select( + (s) => (error: s.errorMessage, verified: s.twoFAVerified), + ), + (previous, next) { + if (next.error.isNotEmpty && next.error != previous?.error) { + showTopSnackbar( + sheetContext, + message: sheetContext.translate(next.error), + type: MessageType.error, + ); + } + if (next.verified) { + Navigator.of(sheetContext).pop(); + } + }, + ); + + final canResend = !isLoading && resendCooldown == 0; + + return LegacyTwoFactorBottomSheetView( + theme: theme, + title: sheetContext.translate(I18n.twoFactorTitle), + subtitle: sheetContext.translate(I18n.twoFactorSubtitle), + verifyText: sheetContext.translate(I18n.twoFactorVerify), + resendText: resendCooldown > 0 + ? '${sheetContext.translate(I18n.twoFactorResend)} (${resendCooldown}s)' + : sheetContext.translate(I18n.twoFactorResend), + closeText: sheetContext.translate(I18n.close), + isOtpLoading: isLoading, + canResend: canResend, + otpCode: code, + otpErrorText: otpErrorText, + onChanged: vm.setCode, + onVerify: () async { + FocusManager.instance.primaryFocus?.unfocus(); + await vm.submitTwoFACode(); + }, + onResend: () => vm.resendCode(), + onClose: () { + vm.dismissTwoFA(); + Navigator.of(sheetContext).pop(); + }, + ); + }, + ); + }, + ); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/domain/onboarding_page.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/domain/onboarding_page.dart new file mode 100644 index 00000000..f1c7c817 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/domain/onboarding_page.dart @@ -0,0 +1,31 @@ +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyOnboardingPage { + final String image; + final String title; + final String subtitle; + + const LegacyOnboardingPage({ + required this.image, + required this.title, + required this.subtitle, + }); +} + +const List onboardingPages = [ + LegacyOnboardingPage( + image: 'assets/shared/images/real_time_device_location.svg', + title: I18n.onboardingTitle1, + subtitle: I18n.onboardingSubtitle1, + ), + LegacyOnboardingPage( + image: 'assets/shared/images/safety_zone.svg', + title: I18n.onboardingTitle2, + subtitle: I18n.onboardingSubtitle2, + ), + LegacyOnboardingPage( + image: 'assets/shared/images/chat.svg', + title: I18n.onboardingTitle3, + subtitle: I18n.onboardingSubtitle3, + ), +]; diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/onboarding_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/onboarding_builder.dart new file mode 100644 index 00000000..ceca40fb --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/onboarding_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_auth/src/features/onboarding/presentation/onboarding_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 LegacyOnboardingBuilder { + const LegacyOnboardingBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyOnboardingScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart new file mode 100644 index 00000000..c1549e5a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_screen.dart @@ -0,0 +1,133 @@ +import 'package:legacy_auth/src/features/onboarding/domain/onboarding_page.dart'; +import 'package:legacy_auth/src/features/onboarding/presentation/onboarding_view_model.dart'; +import 'package:legacy_auth/src/features/onboarding/presentation/widgets/onboarding_content.dart'; +import 'package:design_system/design_system.dart'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:fonts/fonts.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +final legacyOnboardingPageControllerProvider = Provider.autoDispose(( + ref, +) { + final controller = PageController(); + ref.onDispose(controller.dispose); + return controller; +}); + +class LegacyOnboardingScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyOnboardingScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(legacyOnBoardingViewModelProvider); + final viewModel = ref.read(legacyOnBoardingViewModelProvider.notifier); + final pageController = ref.watch(legacyOnboardingPageControllerProvider); + + final isLast = state.cardIndex >= onboardingPages.length - 1; + + void goToNext() { + if (isLast) { + navigationContract.goTo(AppRoutes.login); + } else { + pageController.nextPage( + duration: const Duration(milliseconds: 400), + curve: Curves.easeOut, + ); + } + } + + return Scaffold( + backgroundColor: Color.fromRGBO(247, 247, 247, 1), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + children: [ + Expanded( + child: PageView.builder( + controller: pageController, + itemCount: onboardingPages.length, + onPageChanged: viewModel.onPageChanged, + itemBuilder: (context, index) { + final page = onboardingPages[index]; + return LegacyOnboardingContent( + image: page.image, + title: page.title, + subtitle: page.subtitle, + ); + }, + ), + ), + StepIndicator( + current: state.cardIndex + 1, + total: onboardingPages.length, + color: Color.fromRGBO(88, 142, 165, 1), + ), + const SizedBox(height: 38), + Container( + padding: const EdgeInsets.symmetric(horizontal: 24), + width: double.infinity, + child: TextButton( + onPressed: goToNext, + style: TextButton.styleFrom( + backgroundColor: isLast + ? const Color.fromRGBO(88, 142, 165, 1) + : const Color.fromRGBO(255, 255, 255, 1), + foregroundColor: isLast + ? const Color.fromRGBO(255, 255, 255, 1) + : const Color.fromRGBO(88, 142, 165, 1), + padding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 24, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + side: const BorderSide( + color: Color.fromRGBO(88, 142, 165, 1), + width: 3, + ), + ), + ), + child: Text( + isLast + ? context.translate(I18n.start) + : context.translate(I18n.next), + style: AppFonts.stolzlStyle( + size: 18, + weight: FontWeight.w600, + ), + ), + ), + ), + const SizedBox(height: 8), + SizedBox( + height: 48, + child: Center( + child: isLast + ? const SizedBox.shrink() + : TextButton( + onPressed: () => + navigationContract.goTo(AppRoutes.login), + child: Text( + context.translate(I18n.skip), + style: AppFonts.stolzlStyle( + color: Color.fromRGBO(88, 142, 165, 1), + decoration: TextDecoration.underline, + weight: FontWeight.w600, + size: 18, + ), + ), + ), + ), + ), + const SizedBox(height: 48), + ], + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_model.dart new file mode 100644 index 00000000..619eba11 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_model.dart @@ -0,0 +1,19 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:legacy_auth/src/features/onboarding/presentation/onboarding_view_state.dart'; + +final legacyOnBoardingViewModelProvider = + NotifierProvider.autoDispose( + LegacyOnBoardingViewModel.new, + ); + +class LegacyOnBoardingViewModel extends Notifier { + @override + LegacyOnboardingViewState build() { + return const LegacyOnboardingViewState(); + } + + void onPageChanged(int index) { + state = state.copyWith(cardIndex: index); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.dart new file mode 100644 index 00000000..ce2e4ba1 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'onboarding_view_state.freezed.dart'; + +@freezed +abstract class LegacyOnboardingViewState with _$LegacyOnboardingViewState { + const factory LegacyOnboardingViewState({ + @Default(0) int cardIndex, + String? error, + }) = _LegacyOnboardingViewState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.freezed.dart new file mode 100644 index 00000000..b04854ac --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/onboarding_view_state.freezed.dart @@ -0,0 +1,274 @@ +// 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 'onboarding_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacyOnboardingViewState { + + int get cardIndex; String? get error; +/// Create a copy of LegacyOnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyOnboardingViewStateCopyWith get copyWith => _$LegacyOnboardingViewStateCopyWithImpl(this as LegacyOnboardingViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyOnboardingViewState&&(identical(other.cardIndex, cardIndex) || other.cardIndex == cardIndex)&&(identical(other.error, error) || other.error == error)); +} + + +@override +int get hashCode => Object.hash(runtimeType,cardIndex,error); + +@override +String toString() { + return 'LegacyOnboardingViewState(cardIndex: $cardIndex, error: $error)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyOnboardingViewStateCopyWith<$Res> { + factory $LegacyOnboardingViewStateCopyWith(LegacyOnboardingViewState value, $Res Function(LegacyOnboardingViewState) _then) = _$LegacyOnboardingViewStateCopyWithImpl; +@useResult +$Res call({ + int cardIndex, String? error +}); + + + + +} +/// @nodoc +class _$LegacyOnboardingViewStateCopyWithImpl<$Res> + implements $LegacyOnboardingViewStateCopyWith<$Res> { + _$LegacyOnboardingViewStateCopyWithImpl(this._self, this._then); + + final LegacyOnboardingViewState _self; + final $Res Function(LegacyOnboardingViewState) _then; + +/// Create a copy of LegacyOnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? cardIndex = null,Object? error = freezed,}) { + return _then(_self.copyWith( +cardIndex: null == cardIndex ? _self.cardIndex : cardIndex // ignore: cast_nullable_to_non_nullable +as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyOnboardingViewState]. +extension LegacyOnboardingViewStatePatterns on LegacyOnboardingViewState { +/// 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 Function( _LegacyOnboardingViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyOnboardingViewState() 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 Function( _LegacyOnboardingViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacyOnboardingViewState(): +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? Function( _LegacyOnboardingViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyOnboardingViewState() 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 Function( int cardIndex, String? error)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyOnboardingViewState() when $default != null: +return $default(_that.cardIndex,_that.error);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 Function( int cardIndex, String? error) $default,) {final _that = this; +switch (_that) { +case _LegacyOnboardingViewState(): +return $default(_that.cardIndex,_that.error);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? Function( int cardIndex, String? error)? $default,) {final _that = this; +switch (_that) { +case _LegacyOnboardingViewState() when $default != null: +return $default(_that.cardIndex,_that.error);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyOnboardingViewState implements LegacyOnboardingViewState { + const _LegacyOnboardingViewState({this.cardIndex = 0, this.error}); + + +@override@JsonKey() final int cardIndex; +@override final String? error; + +/// Create a copy of LegacyOnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyOnboardingViewStateCopyWith<_LegacyOnboardingViewState> get copyWith => __$LegacyOnboardingViewStateCopyWithImpl<_LegacyOnboardingViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyOnboardingViewState&&(identical(other.cardIndex, cardIndex) || other.cardIndex == cardIndex)&&(identical(other.error, error) || other.error == error)); +} + + +@override +int get hashCode => Object.hash(runtimeType,cardIndex,error); + +@override +String toString() { + return 'LegacyOnboardingViewState(cardIndex: $cardIndex, error: $error)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyOnboardingViewStateCopyWith<$Res> implements $LegacyOnboardingViewStateCopyWith<$Res> { + factory _$LegacyOnboardingViewStateCopyWith(_LegacyOnboardingViewState value, $Res Function(_LegacyOnboardingViewState) _then) = __$LegacyOnboardingViewStateCopyWithImpl; +@override @useResult +$Res call({ + int cardIndex, String? error +}); + + + + +} +/// @nodoc +class __$LegacyOnboardingViewStateCopyWithImpl<$Res> + implements _$LegacyOnboardingViewStateCopyWith<$Res> { + __$LegacyOnboardingViewStateCopyWithImpl(this._self, this._then); + + final _LegacyOnboardingViewState _self; + final $Res Function(_LegacyOnboardingViewState) _then; + +/// Create a copy of LegacyOnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? cardIndex = null,Object? error = freezed,}) { + return _then(_LegacyOnboardingViewState( +cardIndex: null == cardIndex ? _self.cardIndex : cardIndex // ignore: cast_nullable_to_non_nullable +as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/widgets/onboarding_content.dart b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/widgets/onboarding_content.dart new file mode 100644 index 00000000..267b9e99 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/onboarding/presentation/widgets/onboarding_content.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:fonts/fonts.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacyOnboardingContent extends StatelessWidget { + final String image; + final String title; + final String subtitle; + + const LegacyOnboardingContent({ + super.key, + required this.image, + required this.title, + required this.subtitle, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(image, height: 250), + const SizedBox(height: 48), + Text( + context.translate(title), + textAlign: TextAlign.center, + style: AppFonts.stolzlStyle( + size: 28, + weight: FontWeight.w700, + color: const Color(0xFF4A4A4A), + height: 1.4, + letterSpacing: 0.3, + ), + // style: const TextStyle( + // fontWeight: FontWeight.w700, + // fontSize: 28, + // height: 1.4, + // letterSpacing: 0.3, + // color: Color(0xFF4A4A4A), + // ), + ), + const SizedBox(height: 16), + Text( + context.translate(subtitle), + textAlign: TextAlign.center, + style: AppFonts.stolzlStyle( + size: 18, + height: 1.4, + letterSpacing: 0.3, + color: const Color(0xFF333333), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case.dart new file mode 100644 index 00000000..f2bc7308 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case.dart @@ -0,0 +1,8 @@ +abstract class LegacyRecoverPasswordUseCase { + Future requestEmail({required String email}); + + Future recoverPassword({ + required String newPassword, + required String token, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case_impl.dart new file mode 100644 index 00000000..c0fecdb6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/domain/use_cases/recover_password_use_case_impl.dart @@ -0,0 +1,21 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart'; + +class LegacyRecoverPasswordUseCaseImpl implements LegacyRecoverPasswordUseCase { + LegacyRecoverPasswordUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future requestEmail({required String email}) async { + return await _repository.requestPasswordReset(email: email); + } + + @override + Future recoverPassword({ + required String newPassword, + required String token, + }) async { + await _repository.recoverPassword(newPassword: newPassword, token: token); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_builder.dart new file mode 100644 index 00000000..242dcd20 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacyNewPasswordBuilder { + const LegacyNewPasswordBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyNewPasswordScreen(navigationContract: navigationContract), + ); + } +} \ No newline at end of file diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart new file mode 100644 index 00000000..88bed7fd --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/new_password/new_password_screen.dart @@ -0,0 +1,249 @@ +import 'package:legacy_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 LegacyNewPasswordScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyNewPasswordScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final NavigationContract navigationContract = GetIt.I(); + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(legacyRecoverPasswordViewModelProvider.notifier); + final viewState = ref.watch(legacyRecoverPasswordViewModelProvider); + + 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: 4), + 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: 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: 32, 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( + legacyRecoverPasswordViewModelProvider, + ); + if (updatedState.passwordChanged) { + navigationContract.goTo(AppRoutes.dashboardHome); + } + }, + text: context.translate(I18n.accept), + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/providers/recover_password_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/providers/recover_password_provider.dart new file mode 100644 index 00000000..35fa0021 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/providers/recover_password_provider.dart @@ -0,0 +1,10 @@ +import 'package:legacy_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 legacyRecoverPasswordUseCaseProvider = Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyRecoverPasswordUseCaseImpl(authRepository); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_builder.dart new file mode 100644 index 00000000..ff92553e --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacyRequestRecoveryBuilder { + const LegacyRequestRecoveryBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyRequestRecoveryScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart new file mode 100644 index 00000000..f0d0d2fd --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart @@ -0,0 +1,147 @@ +import 'package:legacy_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 LegacyRequestRecoveryScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyRequestRecoveryScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(legacyRecoverPasswordViewModelProvider.notifier); + final viewState = ref.watch(legacyRecoverPasswordViewModelProvider); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: Container( + margin: EdgeInsets.all( + 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.bold, + fontSize: SizeUtils.getByScreen(small: 29, big: 29, 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: 48)), + CustomTextField( + label: context.translate(I18n.email), + hint: context.translate(I18n.email), + controller: viewModel.emailController, + ), + SizedBox( + height: SizeUtils.getByScreen(small: 40, big: 40, xl: 28), + ), + 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), + initialSelection: 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( + legacyRecoverPasswordViewModelProvider, + ); + if (updatedState.recoveryRequested) { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => LegacySentScreen( + navigationContract: navigationContract, + ), + ), + ); + } + }, + text: context.translate(I18n.send), + size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14), + color: theme.getColorFor(ThemeCode.buttonSecondary), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_builder.dart new file mode 100644 index 00000000..92a239bf --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacySentBuilder { + const LegacySentBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacySentScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart new file mode 100644 index 00000000..46f1937f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/sent/sent_screen.dart @@ -0,0 +1,134 @@ +import 'package:legacy_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 LegacySentScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacySentScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(legacyRecoverPasswordViewModelProvider.notifier); + final viewState = ref.watch(legacyRecoverPasswordViewModelProvider); + + 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: 15), + letterSpacing: 0, + ), + ), + SizedBox(height: 16), + 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: 40), + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + onPressed: () { + if (viewState.recoveryFormat == "email") { + viewModel.requestEmail(); + } + }, + 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: (_) => LegacyNewPasswordScreen( + navigationContract: navigationContract, + ), + ), + ), + text: context.translate(I18n.continueKey), + color: theme.getColorFor(ThemeCode.buttonSecondary), + size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_model.dart new file mode 100644 index 00000000..ba473ac3 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_model.dart @@ -0,0 +1,239 @@ +import 'package:legacy_auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart'; +import 'package:legacy_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 legacyRecoverPasswordViewModelProvider = + NotifierProvider.autoDispose< + LegacyRecoverPasswordViewModel, + LegacyRecoverPasswordViewState + >(LegacyRecoverPasswordViewModel.new); + +class LegacyRecoverPasswordViewModel extends Notifier { + late final LegacyRecoverPasswordUseCase _recoverPasswordUseCase; + late final TextEditingController phoneNumberController; + late final TextEditingController emailController; + late final TextEditingController passwordController; + late final TextEditingController repeatedPasswordController; + late final TextEditingController newPhoneNumberController; + + @override + LegacyRecoverPasswordViewState build() { + _recoverPasswordUseCase = ref.read(legacyRecoverPasswordUseCaseProvider); + + 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 LegacyRecoverPasswordViewState(); + } + + 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 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 requestRecovery() async { + final email = state.email.trim(); + + state = state.copyWith( + isLoading: true, + errorMessage: '', + recoveryRequested: false, + ); + + if (email.isNotEmpty) { + await requestEmail(); + } else { + state = state.copyWith( + isLoading: false, + errorMessage: 'errorMessageContactIsEmpty', + ); + return; + } + } + + Future 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 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(); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.dart new file mode 100644 index 00000000..ef02b842 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.dart @@ -0,0 +1,30 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'recover_password_view_state.freezed.dart'; + +@freezed +abstract class LegacyRecoverPasswordViewState with _$LegacyRecoverPasswordViewState { + const factory LegacyRecoverPasswordViewState({ + @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 securityChecks, + }) = _LegacyRecoverPasswordViewState; +} \ No newline at end of file diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.freezed.dart new file mode 100644 index 00000000..c5cab1f6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/presentation/state/recover_password_view_state.freezed.dart @@ -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 value) => value; +/// @nodoc +mixin _$LegacyRecoverPasswordViewState { + + 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 get securityChecks; +/// Create a copy of LegacyRecoverPasswordViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyRecoverPasswordViewStateCopyWith get copyWith => _$LegacyRecoverPasswordViewStateCopyWithImpl(this as LegacyRecoverPasswordViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyRecoverPasswordViewState&&(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 'LegacyRecoverPasswordViewState(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 $LegacyRecoverPasswordViewStateCopyWith<$Res> { + factory $LegacyRecoverPasswordViewStateCopyWith(LegacyRecoverPasswordViewState value, $Res Function(LegacyRecoverPasswordViewState) _then) = _$LegacyRecoverPasswordViewStateCopyWithImpl; +@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 securityChecks +}); + + + + +} +/// @nodoc +class _$LegacyRecoverPasswordViewStateCopyWithImpl<$Res> + implements $LegacyRecoverPasswordViewStateCopyWith<$Res> { + _$LegacyRecoverPasswordViewStateCopyWithImpl(this._self, this._then); + + final LegacyRecoverPasswordViewState _self; + final $Res Function(LegacyRecoverPasswordViewState) _then; + +/// Create a copy of LegacyRecoverPasswordViewState +/// 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, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacyRecoverPasswordViewState]. +extension LegacyRecoverPasswordViewStatePatterns on LegacyRecoverPasswordViewState { +/// 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 Function( _LegacyRecoverPasswordViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState() 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 Function( _LegacyRecoverPasswordViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState(): +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? Function( _LegacyRecoverPasswordViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState() 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 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 securityChecks)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState() 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 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 securityChecks) $default,) {final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState(): +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? 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 securityChecks)? $default,) {final _that = this; +switch (_that) { +case _LegacyRecoverPasswordViewState() 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 _LegacyRecoverPasswordViewState implements LegacyRecoverPasswordViewState { + const _LegacyRecoverPasswordViewState({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 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 _securityChecks; +@override@JsonKey() Map get securityChecks { + if (_securityChecks is EqualUnmodifiableMapView) return _securityChecks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_securityChecks); +} + + +/// Create a copy of LegacyRecoverPasswordViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyRecoverPasswordViewStateCopyWith<_LegacyRecoverPasswordViewState> get copyWith => __$LegacyRecoverPasswordViewStateCopyWithImpl<_LegacyRecoverPasswordViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyRecoverPasswordViewState&&(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 'LegacyRecoverPasswordViewState(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 _$LegacyRecoverPasswordViewStateCopyWith<$Res> implements $LegacyRecoverPasswordViewStateCopyWith<$Res> { + factory _$LegacyRecoverPasswordViewStateCopyWith(_LegacyRecoverPasswordViewState value, $Res Function(_LegacyRecoverPasswordViewState) _then) = __$LegacyRecoverPasswordViewStateCopyWithImpl; +@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 securityChecks +}); + + + + +} +/// @nodoc +class __$LegacyRecoverPasswordViewStateCopyWithImpl<$Res> + implements _$LegacyRecoverPasswordViewStateCopyWith<$Res> { + __$LegacyRecoverPasswordViewStateCopyWithImpl(this._self, this._then); + + final _LegacyRecoverPasswordViewState _self; + final $Res Function(_LegacyRecoverPasswordViewState) _then; + +/// Create a copy of LegacyRecoverPasswordViewState +/// 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(_LegacyRecoverPasswordViewState( +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, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/recover_password_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/recover_password_builder.dart new file mode 100644 index 00000000..28be396d --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/recover_password/recover_password_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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 LegacyRecoverPasswordBuilder { + const LegacyRecoverPasswordBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacyRequestRecoveryScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.dart new file mode 100644 index 00000000..a6f18864 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'address_entity.freezed.dart'; + +@freezed +abstract class LegacyAddressEntity with _$LegacyAddressEntity { + const factory LegacyAddressEntity({ + required String street, + required String city, + required String province, + required String state, + required String country, + required int postCode, + }) = _LegacyAddressEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.freezed.dart new file mode 100644 index 00000000..5a48f509 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/address_entity.freezed.dart @@ -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 value) => value; +/// @nodoc +mixin _$LegacyAddressEntity { + + String get street; String get city; String get province; String get state; String get country; int get postCode; +/// Create a copy of LegacyAddressEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyAddressEntityCopyWith get copyWith => _$LegacyAddressEntityCopyWithImpl(this as LegacyAddressEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyAddressEntity&&(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 'LegacyAddressEntity(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyAddressEntityCopyWith<$Res> { + factory $LegacyAddressEntityCopyWith(LegacyAddressEntity value, $Res Function(LegacyAddressEntity) _then) = _$LegacyAddressEntityCopyWithImpl; +@useResult +$Res call({ + String street, String city, String province, String state, String country, int postCode +}); + + + + +} +/// @nodoc +class _$LegacyAddressEntityCopyWithImpl<$Res> + implements $LegacyAddressEntityCopyWith<$Res> { + _$LegacyAddressEntityCopyWithImpl(this._self, this._then); + + final LegacyAddressEntity _self; + final $Res Function(LegacyAddressEntity) _then; + +/// Create a copy of LegacyAddressEntity +/// 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 [LegacyAddressEntity]. +extension LegacyAddressEntityPatterns on LegacyAddressEntity { +/// 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 Function( _LegacyAddressEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyAddressEntity() 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 Function( _LegacyAddressEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressEntity(): +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? Function( _LegacyAddressEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressEntity() 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 Function( String street, String city, String province, String state, String country, int postCode)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyAddressEntity() 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 Function( String street, String city, String province, String state, String country, int postCode) $default,) {final _that = this; +switch (_that) { +case _LegacyAddressEntity(): +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? Function( String street, String city, String province, String state, String country, int postCode)? $default,) {final _that = this; +switch (_that) { +case _LegacyAddressEntity() when $default != null: +return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.postCode);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyAddressEntity implements LegacyAddressEntity { + const _LegacyAddressEntity({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 LegacyAddressEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyAddressEntityCopyWith<_LegacyAddressEntity> get copyWith => __$LegacyAddressEntityCopyWithImpl<_LegacyAddressEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyAddressEntity&&(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 'LegacyAddressEntity(street: $street, city: $city, province: $province, state: $state, country: $country, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyAddressEntityCopyWith<$Res> implements $LegacyAddressEntityCopyWith<$Res> { + factory _$LegacyAddressEntityCopyWith(_LegacyAddressEntity value, $Res Function(_LegacyAddressEntity) _then) = __$LegacyAddressEntityCopyWithImpl; +@override @useResult +$Res call({ + String street, String city, String province, String state, String country, int postCode +}); + + + + +} +/// @nodoc +class __$LegacyAddressEntityCopyWithImpl<$Res> + implements _$LegacyAddressEntityCopyWith<$Res> { + __$LegacyAddressEntityCopyWithImpl(this._self, this._then); + + final _LegacyAddressEntity _self; + final $Res Function(_LegacyAddressEntity) _then; + +/// Create a copy of LegacyAddressEntity +/// 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(_LegacyAddressEntity( +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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.dart new file mode 100644 index 00000000..885ebc3b --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.dart @@ -0,0 +1,24 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'address_entity.dart'; + +part 'sign_up_request_entity.freezed.dart'; + +@freezed +abstract class LegacySignUpRequestEntity with _$LegacySignUpRequestEntity { + const factory LegacySignUpRequestEntity({ + required String documentType, + required String document, + required String relationType, + required String firstName, + required String lastName, + required String email, + required String phone, + required String language, + required String password, + required List taxResidences, + required List addresses, + required int bornAt, + required String placeOfBirth, + required String birthCountry, + }) = _LegacySignUpRequestEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.freezed.dart new file mode 100644 index 00000000..b7333503 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_request_entity.freezed.dart @@ -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 'sign_up_request_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacySignUpRequestEntity { + + String get documentType; String get document; String get relationType; String get firstName; String get lastName; String get email; String get phone; String get language; String get password; List get taxResidences; List get addresses; int get bornAt; String get placeOfBirth; String get birthCountry; +/// Create a copy of LegacySignUpRequestEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpRequestEntityCopyWith get copyWith => _$LegacySignUpRequestEntityCopyWithImpl(this as LegacySignUpRequestEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpRequestEntity&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.document, document) || other.document == document)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(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.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)); +} + + +@override +int get hashCode => Object.hash(runtimeType,documentType,document,relationType,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(taxResidences),const DeepCollectionEquality().hash(addresses),bornAt,placeOfBirth,birthCountry); + +@override +String toString() { + return 'LegacySignUpRequestEntity(documentType: $documentType, document: $document, relationType: $relationType, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpRequestEntityCopyWith<$Res> { + factory $LegacySignUpRequestEntityCopyWith(LegacySignUpRequestEntity value, $Res Function(LegacySignUpRequestEntity) _then) = _$LegacySignUpRequestEntityCopyWithImpl; +@useResult +$Res call({ + String documentType, String document, String relationType, String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry +}); + + + + +} +/// @nodoc +class _$LegacySignUpRequestEntityCopyWithImpl<$Res> + implements $LegacySignUpRequestEntityCopyWith<$Res> { + _$LegacySignUpRequestEntityCopyWithImpl(this._self, this._then); + + final LegacySignUpRequestEntity _self; + final $Res Function(LegacySignUpRequestEntity) _then; + +/// Create a copy of LegacySignUpRequestEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? documentType = null,Object? document = null,Object? relationType = 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? placeOfBirth = null,Object? birthCountry = null,}) { + return _then(_self.copyWith( +documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable +as String,document: null == document ? _self.document : document // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // 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,addresses: null == addresses ? _self.addresses : addresses // ignore: cast_nullable_to_non_nullable +as List,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,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 [LegacySignUpRequestEntity]. +extension LegacySignUpRequestEntityPatterns on LegacySignUpRequestEntity { +/// 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 Function( _LegacySignUpRequestEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity() 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 Function( _LegacySignUpRequestEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity(): +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? Function( _LegacySignUpRequestEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity() 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 Function( String documentType, String document, String relationType, String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity() when $default != null: +return $default(_that.documentType,_that.document,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_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 Function( String documentType, String document, String relationType, String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity(): +return $default(_that.documentType,_that.document,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_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? Function( String documentType, String document, String relationType, String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpRequestEntity() when $default != null: +return $default(_that.documentType,_that.document,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.language,_that.password,_that.taxResidences,_that.addresses,_that.bornAt,_that.placeOfBirth,_that.birthCountry);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacySignUpRequestEntity implements LegacySignUpRequestEntity { + const _LegacySignUpRequestEntity({required this.documentType, required this.document, required this.relationType, required this.firstName, required this.lastName, required this.email, required this.phone, required this.language, required this.password, required final List taxResidences, required final List addresses, required this.bornAt, required this.placeOfBirth, required this.birthCountry}): _taxResidences = taxResidences,_addresses = addresses; + + +@override final String documentType; +@override final String document; +@override final String relationType; +@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 _taxResidences; +@override List get taxResidences { + if (_taxResidences is EqualUnmodifiableListView) return _taxResidences; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_taxResidences); +} + + final List _addresses; +@override List get addresses { + if (_addresses is EqualUnmodifiableListView) return _addresses; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_addresses); +} + +@override final int bornAt; +@override final String placeOfBirth; +@override final String birthCountry; + +/// Create a copy of LegacySignUpRequestEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpRequestEntityCopyWith<_LegacySignUpRequestEntity> get copyWith => __$LegacySignUpRequestEntityCopyWithImpl<_LegacySignUpRequestEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpRequestEntity&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.document, document) || other.document == document)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(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.placeOfBirth, placeOfBirth) || other.placeOfBirth == placeOfBirth)&&(identical(other.birthCountry, birthCountry) || other.birthCountry == birthCountry)); +} + + +@override +int get hashCode => Object.hash(runtimeType,documentType,document,relationType,firstName,lastName,email,phone,language,password,const DeepCollectionEquality().hash(_taxResidences),const DeepCollectionEquality().hash(_addresses),bornAt,placeOfBirth,birthCountry); + +@override +String toString() { + return 'LegacySignUpRequestEntity(documentType: $documentType, document: $document, relationType: $relationType, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, language: $language, password: $password, taxResidences: $taxResidences, addresses: $addresses, bornAt: $bornAt, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpRequestEntityCopyWith<$Res> implements $LegacySignUpRequestEntityCopyWith<$Res> { + factory _$LegacySignUpRequestEntityCopyWith(_LegacySignUpRequestEntity value, $Res Function(_LegacySignUpRequestEntity) _then) = __$LegacySignUpRequestEntityCopyWithImpl; +@override @useResult +$Res call({ + String documentType, String document, String relationType, String firstName, String lastName, String email, String phone, String language, String password, List taxResidences, List addresses, int bornAt, String placeOfBirth, String birthCountry +}); + + + + +} +/// @nodoc +class __$LegacySignUpRequestEntityCopyWithImpl<$Res> + implements _$LegacySignUpRequestEntityCopyWith<$Res> { + __$LegacySignUpRequestEntityCopyWithImpl(this._self, this._then); + + final _LegacySignUpRequestEntity _self; + final $Res Function(_LegacySignUpRequestEntity) _then; + +/// Create a copy of LegacySignUpRequestEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? documentType = null,Object? document = null,Object? relationType = 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? placeOfBirth = null,Object? birthCountry = null,}) { + return _then(_LegacySignUpRequestEntity( +documentType: null == documentType ? _self.documentType : documentType // ignore: cast_nullable_to_non_nullable +as String,document: null == document ? _self.document : document // ignore: cast_nullable_to_non_nullable +as String,relationType: null == relationType ? _self.relationType : relationType // 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,addresses: null == addresses ? _self._addresses : addresses // ignore: cast_nullable_to_non_nullable +as List,bornAt: null == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable +as int,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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.dart new file mode 100644 index 00000000..fa9d69e5 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'sign_up_response_entity.freezed.dart'; + +@freezed +abstract class LegacySignUpResponseEntity with _$LegacySignUpResponseEntity { + const factory LegacySignUpResponseEntity({ + required bool isCreated, + required String userId, + }) = _LegacySignUpResponseEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.freezed.dart new file mode 100644 index 00000000..7f407266 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/sign_up_response_entity.freezed.dart @@ -0,0 +1,274 @@ +// 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_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$LegacySignUpResponseEntity { + + bool get isCreated; String get userId; +/// Create a copy of LegacySignUpResponseEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpResponseEntityCopyWith get copyWith => _$LegacySignUpResponseEntityCopyWithImpl(this as LegacySignUpResponseEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpResponseEntity&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.userId, userId) || other.userId == userId)); +} + + +@override +int get hashCode => Object.hash(runtimeType,isCreated,userId); + +@override +String toString() { + return 'LegacySignUpResponseEntity(isCreated: $isCreated, userId: $userId)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpResponseEntityCopyWith<$Res> { + factory $LegacySignUpResponseEntityCopyWith(LegacySignUpResponseEntity value, $Res Function(LegacySignUpResponseEntity) _then) = _$LegacySignUpResponseEntityCopyWithImpl; +@useResult +$Res call({ + bool isCreated, String userId +}); + + + + +} +/// @nodoc +class _$LegacySignUpResponseEntityCopyWithImpl<$Res> + implements $LegacySignUpResponseEntityCopyWith<$Res> { + _$LegacySignUpResponseEntityCopyWithImpl(this._self, this._then); + + final LegacySignUpResponseEntity _self; + final $Res Function(LegacySignUpResponseEntity) _then; + +/// Create a copy of LegacySignUpResponseEntity +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? isCreated = null,Object? userId = null,}) { + return _then(_self.copyWith( +isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable +as bool,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [LegacySignUpResponseEntity]. +extension LegacySignUpResponseEntityPatterns on LegacySignUpResponseEntity { +/// 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 Function( _LegacySignUpResponseEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity() 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 Function( _LegacySignUpResponseEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity(): +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? Function( _LegacySignUpResponseEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity() 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 Function( bool isCreated, String userId)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity() when $default != null: +return $default(_that.isCreated,_that.userId);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 Function( bool isCreated, String userId) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity(): +return $default(_that.isCreated,_that.userId);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? Function( bool isCreated, String userId)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpResponseEntity() when $default != null: +return $default(_that.isCreated,_that.userId);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacySignUpResponseEntity implements LegacySignUpResponseEntity { + const _LegacySignUpResponseEntity({required this.isCreated, required this.userId}); + + +@override final bool isCreated; +@override final String userId; + +/// Create a copy of LegacySignUpResponseEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpResponseEntityCopyWith<_LegacySignUpResponseEntity> get copyWith => __$LegacySignUpResponseEntityCopyWithImpl<_LegacySignUpResponseEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpResponseEntity&&(identical(other.isCreated, isCreated) || other.isCreated == isCreated)&&(identical(other.userId, userId) || other.userId == userId)); +} + + +@override +int get hashCode => Object.hash(runtimeType,isCreated,userId); + +@override +String toString() { + return 'LegacySignUpResponseEntity(isCreated: $isCreated, userId: $userId)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpResponseEntityCopyWith<$Res> implements $LegacySignUpResponseEntityCopyWith<$Res> { + factory _$LegacySignUpResponseEntityCopyWith(_LegacySignUpResponseEntity value, $Res Function(_LegacySignUpResponseEntity) _then) = __$LegacySignUpResponseEntityCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, String userId +}); + + + + +} +/// @nodoc +class __$LegacySignUpResponseEntityCopyWithImpl<$Res> + implements _$LegacySignUpResponseEntityCopyWith<$Res> { + __$LegacySignUpResponseEntityCopyWithImpl(this._self, this._then); + + final _LegacySignUpResponseEntity _self; + final $Res Function(_LegacySignUpResponseEntity) _then; + +/// Create a copy of LegacySignUpResponseEntity +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? isCreated = null,Object? userId = null,}) { + return _then(_LegacySignUpResponseEntity( +isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable +as bool,userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.dart new file mode 100644 index 00000000..85f3c642 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.dart @@ -0,0 +1,19 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'two_fa_secret_entity.freezed.dart'; + +@freezed +abstract class LegacyTwoFASecretEntity with _$LegacyTwoFASecretEntity { + const factory LegacyTwoFASecretEntity({ + required bool isCreated, + required LegacyTwoFASecretItemEntity item, + }) = _LegacyTwoFASecretEntity; +} + +@freezed +abstract class LegacyTwoFASecretItemEntity with _$LegacyTwoFASecretItemEntity { + const factory LegacyTwoFASecretItemEntity({ + required String secret, + required String qr, + }) = _LegacyTwoFASecretItemEntity; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.freezed.dart new file mode 100644 index 00000000..da8f1509 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/entities/two_fa_secret_entity.freezed.dart @@ -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 value) => value; +/// @nodoc +mixin _$LegacyTwoFASecretEntity { + + bool get isCreated; LegacyTwoFASecretItemEntity get item; +/// Create a copy of LegacyTwoFASecretEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyTwoFASecretEntityCopyWith get copyWith => _$LegacyTwoFASecretEntityCopyWithImpl(this as LegacyTwoFASecretEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyTwoFASecretEntity&&(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 'LegacyTwoFASecretEntity(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyTwoFASecretEntityCopyWith<$Res> { + factory $LegacyTwoFASecretEntityCopyWith(LegacyTwoFASecretEntity value, $Res Function(LegacyTwoFASecretEntity) _then) = _$LegacyTwoFASecretEntityCopyWithImpl; +@useResult +$Res call({ + bool isCreated, LegacyTwoFASecretItemEntity item +}); + + +$LegacyTwoFASecretItemEntityCopyWith<$Res> get item; + +} +/// @nodoc +class _$LegacyTwoFASecretEntityCopyWithImpl<$Res> + implements $LegacyTwoFASecretEntityCopyWith<$Res> { + _$LegacyTwoFASecretEntityCopyWithImpl(this._self, this._then); + + final LegacyTwoFASecretEntity _self; + final $Res Function(LegacyTwoFASecretEntity) _then; + +/// Create a copy of LegacyTwoFASecretEntity +/// 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 LegacyTwoFASecretItemEntity, + )); +} +/// Create a copy of LegacyTwoFASecretEntity +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemEntityCopyWith<$Res> get item { + + return $LegacyTwoFASecretItemEntityCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacyTwoFASecretEntity]. +extension LegacyTwoFASecretEntityPatterns on LegacyTwoFASecretEntity { +/// 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 Function( _LegacyTwoFASecretEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity() 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 Function( _LegacyTwoFASecretEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity(): +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? Function( _LegacyTwoFASecretEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity() 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 Function( bool isCreated, LegacyTwoFASecretItemEntity item)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity() 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 Function( bool isCreated, LegacyTwoFASecretItemEntity item) $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity(): +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? Function( bool isCreated, LegacyTwoFASecretItemEntity item)? $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretEntity() when $default != null: +return $default(_that.isCreated,_that.item);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyTwoFASecretEntity implements LegacyTwoFASecretEntity { + const _LegacyTwoFASecretEntity({required this.isCreated, required this.item}); + + +@override final bool isCreated; +@override final LegacyTwoFASecretItemEntity item; + +/// Create a copy of LegacyTwoFASecretEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyTwoFASecretEntityCopyWith<_LegacyTwoFASecretEntity> get copyWith => __$LegacyTwoFASecretEntityCopyWithImpl<_LegacyTwoFASecretEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyTwoFASecretEntity&&(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 'LegacyTwoFASecretEntity(isCreated: $isCreated, item: $item)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyTwoFASecretEntityCopyWith<$Res> implements $LegacyTwoFASecretEntityCopyWith<$Res> { + factory _$LegacyTwoFASecretEntityCopyWith(_LegacyTwoFASecretEntity value, $Res Function(_LegacyTwoFASecretEntity) _then) = __$LegacyTwoFASecretEntityCopyWithImpl; +@override @useResult +$Res call({ + bool isCreated, LegacyTwoFASecretItemEntity item +}); + + +@override $LegacyTwoFASecretItemEntityCopyWith<$Res> get item; + +} +/// @nodoc +class __$LegacyTwoFASecretEntityCopyWithImpl<$Res> + implements _$LegacyTwoFASecretEntityCopyWith<$Res> { + __$LegacyTwoFASecretEntityCopyWithImpl(this._self, this._then); + + final _LegacyTwoFASecretEntity _self; + final $Res Function(_LegacyTwoFASecretEntity) _then; + +/// Create a copy of LegacyTwoFASecretEntity +/// 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(_LegacyTwoFASecretEntity( +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 LegacyTwoFASecretItemEntity, + )); +} + +/// Create a copy of LegacyTwoFASecretEntity +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemEntityCopyWith<$Res> get item { + + return $LegacyTwoFASecretItemEntityCopyWith<$Res>(_self.item, (value) { + return _then(_self.copyWith(item: value)); + }); +} +} + +/// @nodoc +mixin _$LegacyTwoFASecretItemEntity { + + String get secret; String get qr; +/// Create a copy of LegacyTwoFASecretItemEntity +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyTwoFASecretItemEntityCopyWith get copyWith => _$LegacyTwoFASecretItemEntityCopyWithImpl(this as LegacyTwoFASecretItemEntity, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyTwoFASecretItemEntity&&(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 'LegacyTwoFASecretItemEntity(secret: $secret, qr: $qr)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyTwoFASecretItemEntityCopyWith<$Res> { + factory $LegacyTwoFASecretItemEntityCopyWith(LegacyTwoFASecretItemEntity value, $Res Function(LegacyTwoFASecretItemEntity) _then) = _$LegacyTwoFASecretItemEntityCopyWithImpl; +@useResult +$Res call({ + String secret, String qr +}); + + + + +} +/// @nodoc +class _$LegacyTwoFASecretItemEntityCopyWithImpl<$Res> + implements $LegacyTwoFASecretItemEntityCopyWith<$Res> { + _$LegacyTwoFASecretItemEntityCopyWithImpl(this._self, this._then); + + final LegacyTwoFASecretItemEntity _self; + final $Res Function(LegacyTwoFASecretItemEntity) _then; + +/// Create a copy of LegacyTwoFASecretItemEntity +/// 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 [LegacyTwoFASecretItemEntity]. +extension LegacyTwoFASecretItemEntityPatterns on LegacyTwoFASecretItemEntity { +/// 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 Function( _LegacyTwoFASecretItemEntity value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity() 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 Function( _LegacyTwoFASecretItemEntity value) $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity(): +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? Function( _LegacyTwoFASecretItemEntity value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity() 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 Function( String secret, String qr)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity() 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 Function( String secret, String qr) $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity(): +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? Function( String secret, String qr)? $default,) {final _that = this; +switch (_that) { +case _LegacyTwoFASecretItemEntity() when $default != null: +return $default(_that.secret,_that.qr);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyTwoFASecretItemEntity implements LegacyTwoFASecretItemEntity { + const _LegacyTwoFASecretItemEntity({required this.secret, required this.qr}); + + +@override final String secret; +@override final String qr; + +/// Create a copy of LegacyTwoFASecretItemEntity +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyTwoFASecretItemEntityCopyWith<_LegacyTwoFASecretItemEntity> get copyWith => __$LegacyTwoFASecretItemEntityCopyWithImpl<_LegacyTwoFASecretItemEntity>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyTwoFASecretItemEntity&&(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 'LegacyTwoFASecretItemEntity(secret: $secret, qr: $qr)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyTwoFASecretItemEntityCopyWith<$Res> implements $LegacyTwoFASecretItemEntityCopyWith<$Res> { + factory _$LegacyTwoFASecretItemEntityCopyWith(_LegacyTwoFASecretItemEntity value, $Res Function(_LegacyTwoFASecretItemEntity) _then) = __$LegacyTwoFASecretItemEntityCopyWithImpl; +@override @useResult +$Res call({ + String secret, String qr +}); + + + + +} +/// @nodoc +class __$LegacyTwoFASecretItemEntityCopyWithImpl<$Res> + implements _$LegacyTwoFASecretItemEntityCopyWith<$Res> { + __$LegacyTwoFASecretItemEntityCopyWithImpl(this._self, this._then); + + final _LegacyTwoFASecretItemEntity _self; + final $Res Function(_LegacyTwoFASecretItemEntity) _then; + +/// Create a copy of LegacyTwoFASecretItemEntity +/// 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(_LegacyTwoFASecretItemEntity( +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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart new file mode 100644 index 00000000..8adfee15 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart @@ -0,0 +1,5 @@ +import 'package:legacy_auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart'; + +abstract class GenerateTwoFALegacySignUpUseCase { + Future generateTwoFASignUp({required String token}); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case_impl.dart new file mode 100644 index 00000000..6aa2151a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/generate_two_fa_sign_up_use_case_impl.dart @@ -0,0 +1,16 @@ +import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart'; +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/two_fa_secret_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart'; + +class GenerateTwoFALegacySignUpUseCaseImpl implements GenerateTwoFALegacySignUpUseCase { + GenerateTwoFALegacySignUpUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + @override + Future generateTwoFASignUp({required String token}) { + return _repository + .generateTwoFASignUp(token: token) + .then((model) => model.toEntity()); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case.dart new file mode 100644 index 00000000..ae57b67f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case.dart @@ -0,0 +1,6 @@ +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; + +abstract class LegacySignUpUseCase { + Future signUp({required LegacySignUpRequestEntity request}); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case_impl.dart new file mode 100644 index 00000000..c2a86c2c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/sign_up_use_case_impl.dart @@ -0,0 +1,15 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/sign_up_use_case.dart'; + +class LegacySignUpUseCaseImpl implements LegacySignUpUseCase { + LegacySignUpUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + + @override + Future signUp({required LegacySignUpRequestEntity request}) { + return _repository.signUp(request: request); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart new file mode 100644 index 00000000..55ed3f44 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart @@ -0,0 +1,6 @@ +abstract class LegacyVerifyTwoFACodeSignUpUseCase { + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case_impl.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case_impl.dart new file mode 100644 index 00000000..9a131081 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case_impl.dart @@ -0,0 +1,15 @@ +import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart'; + +class LegacyVerifyTwoFaCodeSignUpUseCaseImpl implements LegacyVerifyTwoFACodeSignUpUseCase { + LegacyVerifyTwoFaCodeSignUpUseCaseImpl(this._repository); + + final LegacyAuthRepository _repository; + @override + Future verifyTwoFACodeSignUp({ + required String token, + required String code, + }) { + return _repository.verifyTwoFACodeSignUp(token: token, code: code); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/models/sign_up_step_config.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/models/sign_up_step_config.dart new file mode 100644 index 00000000..38656796 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/models/sign_up_step_config.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +typedef LegacySignUpBodyBuilder = + Widget Function(BuildContext context, WidgetRef ref); + +class LegacySignUpStepConfig { + final String supertitle; + final String title; + final String? subtitle; + final LegacySignUpBodyBuilder bodyBuilder; + + const LegacySignUpStepConfig({ + required this.supertitle, + required this.title, + this.subtitle, + required this.bodyBuilder, + }); +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/address_view_state_mapper.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/address_view_state_mapper.dart new file mode 100644 index 00000000..818e5005 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/address_view_state_mapper.dart @@ -0,0 +1,23 @@ +import 'package:legacy_auth/src/features/sign_up/domain/entities/address_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/state/address_view_state.dart'; + +extension LegacyAddressViewStateMapper on LegacyAddressViewState { + bool get isValid => + street.trim().isNotEmpty && + city.trim().isNotEmpty && + province.trim().isNotEmpty && + state.trim().isNotEmpty && + country.trim().isNotEmpty && + (postCode != null); + + LegacyAddressEntity toEntity() { + return LegacyAddressEntity( + street: street.trim(), + city: city.trim(), + province: province.trim(), + state: state.trim(), + country: country.trim(), + postCode: postCode ?? 0, + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/sign_up_view_state_mapper.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/sign_up_view_state_mapper.dart new file mode 100644 index 00000000..6c5a1bad --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/mappers/sign_up_view_state_mapper.dart @@ -0,0 +1,44 @@ +import 'package:legacy_auth/src/features/sign_up/domain/entities/address_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/mappers/address_view_state_mapper.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/state/sign_up_view_state.dart'; + +extension LegacySignUpViewStateMapper on LegacySignUpViewState { + bool get canSubmit => + document.trim().isNotEmpty && + documentType.trim().isNotEmpty && + relationType.trim().isNotEmpty && + firstName.trim().isNotEmpty && + lastName.trim().isNotEmpty && + email.trim().isNotEmpty && + phone.trim().isNotEmpty && + password.isNotEmpty && + bornAt != null && + placeOfBirth.trim().isNotEmpty && + birthCountry.trim().isNotEmpty && + address.isValid; + + LegacySignUpRequestEntity toRequestEntity() { + final birth = bornAt; + if (birth == null) { + throw Exception('bornAt is required'); + } + + return LegacySignUpRequestEntity( + document: document.trim(), + documentType: documentType.trim(), + relationType: relationType.trim(), + firstName: firstName.trim(), + lastName: lastName.trim(), + email: email.trim(), + phone: phone.trim(), + language: language.trim(), + password: password, + bornAt: birth.millisecondsSinceEpoch, + placeOfBirth: placeOfBirth.trim(), + birthCountry: birthCountry.trim(), + addresses: [address.toEntity()], + taxResidences: [address.toEntity()], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/generate_two_fa_sign_up_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/generate_two_fa_sign_up_provider.dart new file mode 100644 index 00000000..33472d94 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/generate_two_fa_sign_up_provider.dart @@ -0,0 +1,10 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/generate_two_fa_sign_up_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final generateTwoFALegacySignUpUseCaseProvider = + Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return GenerateTwoFALegacySignUpUseCaseImpl(authRepository); + }); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/sign_up_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/sign_up_provider.dart new file mode 100644 index 00000000..5afb1474 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/sign_up_provider.dart @@ -0,0 +1,9 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/sign_up_use_case.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/sign_up_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacySignUpUseCaseProvider = Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacySignUpUseCaseImpl(authRepository); +}); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/verify_two_fa_code_sign_up_provider.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/verify_two_fa_code_sign_up_provider.dart new file mode 100644 index 00000000..57345a6a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/providers/verify_two_fa_code_sign_up_provider.dart @@ -0,0 +1,10 @@ +import 'package:legacy_auth/src/core/providers/auth_repository_provider.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/verify_two_fa_code_sign_up_use_case_impl.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final legacyVerifyTwoFACodeSignUpUseCaseProvider = + Provider.autoDispose((ref) { + final authRepository = ref.read(legacyAuthRepositoryProvider); + return LegacyVerifyTwoFaCodeSignUpUseCaseImpl(authRepository); + }); diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart new file mode 100644 index 00000000..981aa761 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/account_created_screen.dart @@ -0,0 +1,92 @@ +import 'package:legacy_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 LegacyAccountCreatedScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacyAccountCreatedScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final state = ref.watch(legacySignUpViewModelProvider); + + final String email = state.email; + final String fullName = '${state.firstName} ${state.lastName}'.trim(); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: Container( + margin: const EdgeInsets.all(30), + child: Center( + child: Column( + children: [ + const Spacer(flex: 10), + Icon( + Icons.check, + color: theme.getColorFor(ThemeCode.buttonPrimary), + size: 50, + ), + const SizedBox(height: 20), + Text( + context.translate(I18n.accountCreatedTitle), + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 20), + + Text.rich( + textAlign: TextAlign.center, + TextSpan( + text: '${context.translate(I18n.accountCreatedForLabel)}\n', + children: [ + TextSpan( + text: fullName, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + + const SizedBox(height: 16), + Text.rich( + textAlign: TextAlign.center, + TextSpan( + text: + '${context.translate(I18n.accountCreatedEmailVerificationSentLabel)}\n', + children: [ + TextSpan( + text: email, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + + const SizedBox(height: 20), + Text( + context.translate(I18n.accountCreatedChildSetupHint), + textAlign: TextAlign.center, + ), + + const SizedBox(height: 20), + PrimaryButton( + onPressed: () => navigationContract.goTo(AppRoutes.login), + text: context.translate(I18n.accountCreatedContinue), + color: Color.fromRGBO(88, 142, 165, 1), + ), + const Spacer(flex: 8), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/secret_code_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/secret_code_screen.dart new file mode 100644 index 00000000..905e9883 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/secret_code_screen.dart @@ -0,0 +1,281 @@ +// import 'dart:convert'; + +// import 'package:legacy_auth/src/features/login/presentation/widgets/two_factor_bottom_sheet.dart'; +// import 'package:legacy_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 _openTwoFactorSignUpBottomSheet( +// BuildContext context, +// WidgetRef ref, +// ) async { +// final token = ref.read(legacySignUpViewModelProvider).token; +// if (token.trim().isEmpty) return false; + +// return showModalBottomSheet( +// 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(legacySignUpViewModelProvider.notifier); + +// final otpErrorKey = ref.watch( +// legacySignUpViewModelProvider.select((s) => s.otpError), +// ); +// final isOtpLoading = ref.watch( +// legacySignUpViewModelProvider.select((s) => s.isOtpLoading), +// ); +// final otpCode = ref.watch( +// legacySignUpViewModelProvider.select((s) => s.otpCode), +// ); + +// final otpErrorText = otpErrorKey.isEmpty +// ? '' +// : context.translate(otpErrorKey); + +// Future 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 LegacyTwoFactorBottomSheetView( +// 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(legacySignUpViewModelProvider.notifier); +// final state = ref.watch(legacySignUpViewModelProvider); + +// 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), +// ), +// ), +// ], +// ), +// ); +// } +// } diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_address_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_address_screen.dart new file mode 100644 index 00000000..759af02c --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_address_screen.dart @@ -0,0 +1,232 @@ +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'; + +class LegacySignupAddressScreen extends StatelessWidget { + const LegacySignupAddressScreen({ + 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 onRelationshipChanged; + final List 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 onAddressCountryChanged; + final String addressCountryLabel; + final TextEditingController addressCountryController; + + final TextEditingController postCodeController; + + final String birthDateLabel; + final String birthDateHint; + + final String placeOfBirthLabel; + final String placeOfBirthHint; + final ValueChanged 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: const TextStyle(fontSize: 14)), + ), + 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, + hint: streetHint, + controller: streetController, + ), + const SizedBox(height: 8), + + CustomTextField( + label: cityLabel, + hint: cityHint, + controller: cityController, + ), + const SizedBox(height: 8), + + CustomTextField( + label: provinceLabel, + hint: provinceHint, + controller: provinceController, + ), + const SizedBox(height: 8), + + CustomTextField( + label: stateLabel, + 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, + hint: postCodeHint, + keyboardType: TextInputType.number, + controller: postCodeController, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_password_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_password_screen.dart new file mode 100644 index 00000000..e6eb27c6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_password_screen.dart @@ -0,0 +1,35 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +class LegacySignUpPasswordScreen extends StatelessWidget { + final bool isPasswordVisible; + final TextEditingController passwordTextFieldController; + final TextEditingController repeatPasswordTextFieldController; + const LegacySignUpPasswordScreen({ + 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, + ), + ], + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart new file mode 100644 index 00000000..d8bbe6d7 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/screens/sign_up_personal_screen.dart @@ -0,0 +1,154 @@ +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'; + +class LegacySignupPersonalScreen extends StatelessWidget { + final TextEditingController firstNameTextFieldController; + final TextEditingController lastNameTextFieldController; + final TextEditingController documentNumberTextFieldController; + final TextEditingController phoneTextFieldController; + final TextEditingController emailTextFieldController; + + final String? documentTypeSelected; + final ValueChanged onDocumentTypeChanged; + + final String firstNameLabel; + final String firstNameHint; + + final String lastNameLabel; + final String lastNameHint; + + final List documentTypeOptions; + final String documentTypeHint; + + final String documentNumberLabel; + final String documentNumberHint; + + final String phoneLabel; + final String phoneHint; + final ValueChanged onDialCodeChanged; + + final String emailLabel; + final String emailHint; + + final bool acceptTerms; + final ValueChanged? onAcceptTermsPressed; + final String termsText; + final ThemePort theme; + + const LegacySignupPersonalScreen({ + 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, + hint: firstNameHint, + controller: firstNameTextFieldController, + ), + const SizedBox(height: 8), + CustomTextField( + label: lastNameLabel, + 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, + hint: documentNumberHint, + controller: documentNumberTextFieldController, + ), + ), + ], + ), + const SizedBox(height: 8), + Align( + alignment: Alignment.bottomLeft, + child: Text(phoneLabel, style: const TextStyle(fontSize: 14)), + ), + 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, + hint: emailHint, + keyboardType: TextInputType.emailAddress, + controller: emailTextFieldController, + ), + + 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, + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_screen.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_screen.dart new file mode 100644 index 00000000..af07a843 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_screen.dart @@ -0,0 +1,76 @@ +import 'package:legacy_auth/src/features/sign_up/presentation/sign_up_steps.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/state/sign_up_view_model.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/screens/account_created_screen.dart'; +import 'package:legacy_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'; +import 'package:sf_localizations/sf_localizations.dart'; + +class LegacySignupScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const LegacySignupScreen({super.key, required this.navigationContract}); + + Future _onNextPressed(BuildContext context, WidgetRef ref) async { + FocusManager.instance.primaryFocus?.unfocus(); + + final vm = ref.read(legacySignUpViewModelProvider.notifier); + final state = ref.read(legacySignUpViewModelProvider); + + 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(legacySignUpViewModelProvider.notifier); + final state = ref.watch(legacySignUpViewModelProvider); + + ref.listen( + legacySignUpViewModelProvider.select((s) => s.errorMessage), + (previous, next) { + if (next.isNotEmpty) { + showTopSnackbar( + context, + message: context.translate(next), + type: MessageType.error, + ); + } + }, + ); + + final steps = signUpSteps(context); + final index = state.currentIndex.clamp(0, steps.length - 1); + final step = steps[index]; + + if (state.showAccountCreated) { + return LegacyAccountCreatedScreen(navigationContract: navigationContract); + } + return LegacySignUpLayout( + theme: theme, + supertitle: step.supertitle, + title: step.title, + subtitle: step.subtitle ?? '', + currentStep: index + 1, + numSteps: steps.length, + body: step.bodyBuilder(context, ref), + onBackPressed: state.currentIndex == 0 + ? navigationContract.goBack + : vm.back, + onNextPressed: () => _onNextPressed(context, ref), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_steps.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_steps.dart new file mode 100644 index 00000000..883a5bc1 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/sign_up_steps.dart @@ -0,0 +1,179 @@ +import 'package:legacy_auth/src/features/sign_up/models/sign_up_step_config.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/state/sign_up_view_model.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/screens/sign_up_address_screen.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/screens/sign_up_password_screen.dart'; +import 'package:legacy_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 documentType = { + 'DNI': I18n.documentTypeDni, + 'NIE': I18n.documentTypeNie, + 'PASSPORT': I18n.documentTypePassport, +}; +const Map relationship = { + 'FATHER': I18n.relationshipFather, + 'MOTHER': I18n.relationshipMother, + 'OTHER': I18n.relationshipTutor, +}; + +List signUpSteps(BuildContext context) => [ + LegacySignUpStepConfig( + 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(legacySignUpViewModelProvider.notifier); + final state = ref.watch(legacySignUpViewModelProvider); + final documentLabel = { + for (final e in documentType.entries) e.key: context.translate(e.value), + }; + + final documentKeys = { + for (final e in documentLabel.entries) e.value: e.key, + }; + + final String? documentTypeSelected = state.documentType.trim().isEmpty + ? null + : documentLabel[state.documentType]; + return LegacySignupPersonalScreen( + 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); + }, + ); + }, + ), + LegacySignUpStepConfig( + supertitle: context.translate(I18n.stepPersonalDataSupertitle), + title: context.translate(I18n.stepPersonalDataTitle), + subtitle: context.translate(I18n.stepPersonalDataSubtitle), + bodyBuilder: (context, ref) { + final vm = ref.read(legacySignUpViewModelProvider.notifier); + final state = ref.watch(legacySignUpViewModelProvider); + + final relationshipLabel = { + for (final e in relationship.entries) e.key: context.translate(e.value), + }; + final relationshipKeys = { + for (final e in relationshipLabel.entries) e.value: e.key, + }; + final String? relationshipSelected = state.relationType.trim().isEmpty + ? null + : relationshipLabel[state.relationType]; + + return LegacySignupAddressScreen( + 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 ?? '', code: value.code ?? ''); + }, + 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), + ); + }, + ), + LegacySignUpStepConfig( + supertitle: context.translate(I18n.stepAddressSupertitle), + title: context.translate(I18n.stepAddressTitle), + subtitle: context.translate(I18n.passwordRulesSubtitle), + bodyBuilder: (context, ref) { + final vm = ref.read(legacySignUpViewModelProvider.notifier); + final state = ref.watch(legacySignUpViewModelProvider); + + return LegacySignUpPasswordScreen( + isPasswordVisible: state.isShowPassword, + passwordTextFieldController: vm.passwordController, + repeatPasswordTextFieldController: vm.repeatPasswordController, + ); + }, + ), +]; diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.dart new file mode 100644 index 00000000..ab8855fc --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'address_view_state.freezed.dart'; + +@freezed +abstract class LegacyAddressViewState with _$LegacyAddressViewState { + const factory LegacyAddressViewState({ + @Default('') String street, + @Default('') String city, + @Default('') String province, + @Default('') String state, + @Default('España') String country, + @Default('ES') String countryCode, + int? postCode, + }) = _LegacyAddressViewState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.freezed.dart new file mode 100644 index 00000000..d8a8e5c0 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/address_view_state.freezed.dart @@ -0,0 +1,289 @@ +// 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 value) => value; +/// @nodoc +mixin _$LegacyAddressViewState { + + String get street; String get city; String get province; String get state; String get country; String get countryCode; int? get postCode; +/// Create a copy of LegacyAddressViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacyAddressViewStateCopyWith get copyWith => _$LegacyAddressViewStateCopyWithImpl(this as LegacyAddressViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacyAddressViewState&&(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.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.postCode, postCode) || other.postCode == postCode)); +} + + +@override +int get hashCode => Object.hash(runtimeType,street,city,province,state,country,countryCode,postCode); + +@override +String toString() { + return 'LegacyAddressViewState(street: $street, city: $city, province: $province, state: $state, country: $country, countryCode: $countryCode, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacyAddressViewStateCopyWith<$Res> { + factory $LegacyAddressViewStateCopyWith(LegacyAddressViewState value, $Res Function(LegacyAddressViewState) _then) = _$LegacyAddressViewStateCopyWithImpl; +@useResult +$Res call({ + String street, String city, String province, String state, String country, String countryCode, int? postCode +}); + + + + +} +/// @nodoc +class _$LegacyAddressViewStateCopyWithImpl<$Res> + implements $LegacyAddressViewStateCopyWith<$Res> { + _$LegacyAddressViewStateCopyWithImpl(this._self, this._then); + + final LegacyAddressViewState _self; + final $Res Function(LegacyAddressViewState) _then; + +/// Create a copy of LegacyAddressViewState +/// 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? countryCode = 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,countryCode: null == countryCode ? _self.countryCode : countryCode // 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 [LegacyAddressViewState]. +extension LegacyAddressViewStatePatterns on LegacyAddressViewState { +/// 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 Function( _LegacyAddressViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacyAddressViewState() 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 Function( _LegacyAddressViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressViewState(): +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? Function( _LegacyAddressViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacyAddressViewState() 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 Function( String street, String city, String province, String state, String country, String countryCode, int? postCode)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacyAddressViewState() when $default != null: +return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.countryCode,_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 Function( String street, String city, String province, String state, String country, String countryCode, int? postCode) $default,) {final _that = this; +switch (_that) { +case _LegacyAddressViewState(): +return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.countryCode,_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? Function( String street, String city, String province, String state, String country, String countryCode, int? postCode)? $default,) {final _that = this; +switch (_that) { +case _LegacyAddressViewState() when $default != null: +return $default(_that.street,_that.city,_that.province,_that.state,_that.country,_that.countryCode,_that.postCode);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacyAddressViewState implements LegacyAddressViewState { + const _LegacyAddressViewState({this.street = '', this.city = '', this.province = '', this.state = '', this.country = 'España', this.countryCode = 'ES', 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@JsonKey() final String countryCode; +@override final int? postCode; + +/// Create a copy of LegacyAddressViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacyAddressViewStateCopyWith<_LegacyAddressViewState> get copyWith => __$LegacyAddressViewStateCopyWithImpl<_LegacyAddressViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacyAddressViewState&&(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.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.postCode, postCode) || other.postCode == postCode)); +} + + +@override +int get hashCode => Object.hash(runtimeType,street,city,province,state,country,countryCode,postCode); + +@override +String toString() { + return 'LegacyAddressViewState(street: $street, city: $city, province: $province, state: $state, country: $country, countryCode: $countryCode, postCode: $postCode)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacyAddressViewStateCopyWith<$Res> implements $LegacyAddressViewStateCopyWith<$Res> { + factory _$LegacyAddressViewStateCopyWith(_LegacyAddressViewState value, $Res Function(_LegacyAddressViewState) _then) = __$LegacyAddressViewStateCopyWithImpl; +@override @useResult +$Res call({ + String street, String city, String province, String state, String country, String countryCode, int? postCode +}); + + + + +} +/// @nodoc +class __$LegacyAddressViewStateCopyWithImpl<$Res> + implements _$LegacyAddressViewStateCopyWith<$Res> { + __$LegacyAddressViewStateCopyWithImpl(this._self, this._then); + + final _LegacyAddressViewState _self; + final $Res Function(_LegacyAddressViewState) _then; + +/// Create a copy of LegacyAddressViewState +/// 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? countryCode = null,Object? postCode = freezed,}) { + return _then(_LegacyAddressViewState( +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,countryCode: null == countryCode ? _self.countryCode : countryCode // 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 diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_model.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_model.dart new file mode 100644 index 00000000..96705448 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_model.dart @@ -0,0 +1,702 @@ +import 'dart:async'; + +import 'package:legacy_auth/src/features/sign_up/domain/entities/address_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_response_entity.dart'; +import 'package:legacy_auth/src/features/sign_up/domain/sign_up_use_case.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/providers/sign_up_provider.dart'; +import 'package:legacy_auth/src/features/sign_up/presentation/state/address_view_state.dart'; +import 'package:legacy_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:sealed_countries/sealed_countries.dart'; + +final legacySignUpViewModelProvider = + NotifierProvider.autoDispose( + LegacySignUpViewModel.new, + ); + +class LegacySignUpViewModel extends Notifier { + late final LegacySignUpUseCase _signUpUseCase; + + 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}$'); + + static final RegExp _nameRegex = RegExp(r"^[a-zA-ZÀ-ÿ\s\-']+$"); + + @override + LegacySignUpViewState build() { + _signUpUseCase = ref.read(legacySignUpUseCaseProvider); + + final initial = LegacySignUpViewState(); + _initControllers(initial); + _addListeners(); + + ref.onDispose(disposeControllers); + + return initial; + } + + void _initControllers(LegacySignUpViewState s) { + firstNameController = TextEditingController(text: s.firstName); + lastNameController = TextEditingController(text: s.lastName); + documentNumberController = TextEditingController(text: s.document); + documentTypeController = TextEditingController(text: s.documentType); + phoneController = TextEditingController(text: s.phone); + emailController = TextEditingController(text: s.email); + + relationshipController = TextEditingController(text: s.relationType); + + 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 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, required String code}) { + addressCountryController.text = name; + state = state.copyWith( + address: state.address.copyWith(country: name, countryCode: code), + ); + } + + 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.document) return; + state = state.copyWith(document: 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.relationType) return; + state = state.copyWith(relationType: 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: '', + ); + } + } + + 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: I18n.errorFirstNameRequired); + return false; + } + if (!_nameRegex.hasMatch(state.firstName.trim())) { + state = state.copyWith(errorMessage: I18n.errorNameInvalidChars); + return false; + } + if (state.lastName.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorLastNameRequired); + return false; + } + if (!_nameRegex.hasMatch(state.lastName.trim())) { + state = state.copyWith(errorMessage: I18n.errorNameInvalidChars); + return false; + } + if (state.documentType.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorDocumentTypeRequired); + return false; + } + if (state.document.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorDocumentNumberRequired); + 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: I18n.errorAcceptTerms); + 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: I18n.errorBirthDateRequired); + return false; + } + if (state.relationType.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorRelationshipRequired); + return false; + } + + if (state.placeOfBirth.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorPlaceOfBirthRequired); + return false; + } + + if (state.birthCountry.trim().isEmpty) { + state = state.copyWith(errorMessage: I18n.errorBirthCountryRequired); + return false; + } + + if (!_isAddressValid(state.address)) { + state = state.copyWith(errorMessage: I18n.errorAddressRequired); + 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 (email.contains('+')) return I18n.errorEmailPlusNotAllowed; + 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(LegacyAddressViewState 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; + } + + LegacyAddressEntity _toLegacyAddressEntity(LegacyAddressViewState a) { + final country = WorldCountry.fromCodeShort(a.countryCode.toUpperCase()); + + return LegacyAddressEntity( + street: a.street.trim(), + city: a.city.trim(), + province: a.province.trim(), + state: a.state.trim(), + country: country.name.common, + postCode: a.postCode ?? 0, + ); + } + + LegacySignUpRequestEntity _toRequest() { + final bornAt = state.bornAt; + if (bornAt == null) throw Exception('bornAt is required'); + + return LegacySignUpRequestEntity( + documentType: state.documentType.trim(), + document: state.document.trim(), + relationType: state.relationType.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: DateTime.utc( + bornAt.year, + bornAt.month, + bornAt.day, + ).millisecondsSinceEpoch, + placeOfBirth: state.placeOfBirth.trim(), + birthCountry: state.birthCountryCode.trim(), + addresses: [_toLegacyAddressEntity(state.address)], + taxResidences: [_toLegacyAddressEntity(state.address)], + ); + } + + Future signUp() async { + if (state.isLoading) return false; + if (!_validateForm()) return false; + + _startLoadingForSignUp(); + + try { + final request = _toRequest(); + + final response = await _signUp(request); + if (!ref.mounted) return false; + + _finishWithSuccess(isCreated: response.isCreated); + return true; + } catch (e) { + if (!ref.mounted) return false; + _finishWithError(message: e.toString()); + return false; + } + } + + void _startLoadingForSignUp() { + state = state.copyWith( + isLoading: true, + errorMessage: '', + showAccountCreated: false, + ); + } + + Future _signUp(LegacySignUpRequestEntity request) { + return _signUpUseCase.signUp(request: request); + } + + void _finishWithSuccess({required bool isCreated}) { + state = state.copyWith( + isLoading: false, + isCreated: isCreated, + errorMessage: '', + showAccountCreated: true, + ); + } + + void _finishWithError({bool? isCreated, required String message}) { + state = state.copyWith( + isLoading: false, + isCreated: isCreated ?? state.isCreated, + errorMessage: message, + ); + } + + 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(); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.dart new file mode 100644 index 00000000..c3bf8904 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.dart @@ -0,0 +1,41 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'address_view_state.dart'; + +part 'sign_up_view_state.freezed.dart'; + +@freezed +abstract class LegacySignUpViewState with _$LegacySignUpViewState { + const factory LegacySignUpViewState({ + @Default(0) int currentIndex, + + @Default('') String document, + @Default('') String documentType, + @Default(false) bool acceptTerms, + @Default('') String relationType, + + @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(false) bool isCreated, + @Default('') String placeOfBirth, + @Default('España') String birthCountry, + @Default('ES') String birthCountryCode, + + @Default(LegacyAddressViewState()) LegacyAddressViewState address, + + @Default('') String emailError, + @Default('') String passwordError, + @Default('') String phoneError, + @Default('') String errorMessage, + @Default(false) bool isLoading, + @Default(false) bool showErrors, + @Default(false) bool showAccountCreated, + }) = _LegacySignUpViewState; +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.freezed.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.freezed.dart new file mode 100644 index 00000000..2925f802 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/presentation/state/sign_up_view_state.freezed.dart @@ -0,0 +1,367 @@ +// 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 value) => value; +/// @nodoc +mixin _$LegacySignUpViewState { + + int get currentIndex; String get document; String get documentType; bool get acceptTerms; String get relationType; 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; bool get isCreated; String get placeOfBirth; String get birthCountry; String get birthCountryCode; LegacyAddressViewState get address; String get emailError; String get passwordError; String get phoneError; String get errorMessage; bool get isLoading; bool get showErrors; bool get showAccountCreated; +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$LegacySignUpViewStateCopyWith get copyWith => _$LegacySignUpViewStateCopyWithImpl(this as LegacySignUpViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is LegacySignUpViewState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.document, document) || other.document == document)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.acceptTerms, acceptTerms) || other.acceptTerms == acceptTerms)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(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.isCreated, isCreated) || other.isCreated == isCreated)&&(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.showAccountCreated, showAccountCreated) || other.showAccountCreated == showAccountCreated)); +} + + +@override +int get hashCode => Object.hashAll([runtimeType,currentIndex,document,documentType,acceptTerms,relationType,firstName,lastName,email,phone,dialCode,language,bornAt,password,repeatPassword,isShowPassword,isCreated,placeOfBirth,birthCountry,birthCountryCode,address,emailError,passwordError,phoneError,errorMessage,isLoading,showErrors,showAccountCreated]); + +@override +String toString() { + return 'LegacySignUpViewState(currentIndex: $currentIndex, document: $document, documentType: $documentType, acceptTerms: $acceptTerms, relationType: $relationType, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, dialCode: $dialCode, language: $language, bornAt: $bornAt, password: $password, repeatPassword: $repeatPassword, isShowPassword: $isShowPassword, isCreated: $isCreated, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, birthCountryCode: $birthCountryCode, address: $address, emailError: $emailError, passwordError: $passwordError, phoneError: $phoneError, errorMessage: $errorMessage, isLoading: $isLoading, showErrors: $showErrors, showAccountCreated: $showAccountCreated)'; +} + + +} + +/// @nodoc +abstract mixin class $LegacySignUpViewStateCopyWith<$Res> { + factory $LegacySignUpViewStateCopyWith(LegacySignUpViewState value, $Res Function(LegacySignUpViewState) _then) = _$LegacySignUpViewStateCopyWithImpl; +@useResult +$Res call({ + int currentIndex, String document, String documentType, bool acceptTerms, String relationType, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, bool isCreated, String placeOfBirth, String birthCountry, String birthCountryCode, LegacyAddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, bool showAccountCreated +}); + + +$LegacyAddressViewStateCopyWith<$Res> get address; + +} +/// @nodoc +class _$LegacySignUpViewStateCopyWithImpl<$Res> + implements $LegacySignUpViewStateCopyWith<$Res> { + _$LegacySignUpViewStateCopyWithImpl(this._self, this._then); + + final LegacySignUpViewState _self; + final $Res Function(LegacySignUpViewState) _then; + +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,Object? document = null,Object? documentType = null,Object? acceptTerms = null,Object? relationType = 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? isCreated = 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? showAccountCreated = null,}) { + return _then(_self.copyWith( +currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable +as int,document: null == document ? _self.document : document // 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,relationType: null == relationType ? _self.relationType : relationType // 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,isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable +as bool,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 LegacyAddressViewState,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,showAccountCreated: null == showAccountCreated ? _self.showAccountCreated : showAccountCreated // ignore: cast_nullable_to_non_nullable +as bool, + )); +} +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyAddressViewStateCopyWith<$Res> get address { + + return $LegacyAddressViewStateCopyWith<$Res>(_self.address, (value) { + return _then(_self.copyWith(address: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [LegacySignUpViewState]. +extension LegacySignUpViewStatePatterns on LegacySignUpViewState { +/// 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 Function( _LegacySignUpViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _LegacySignUpViewState() 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 Function( _LegacySignUpViewState value) $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpViewState(): +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? Function( _LegacySignUpViewState value)? $default,){ +final _that = this; +switch (_that) { +case _LegacySignUpViewState() 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 Function( int currentIndex, String document, String documentType, bool acceptTerms, String relationType, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, bool isCreated, String placeOfBirth, String birthCountry, String birthCountryCode, LegacyAddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, bool showAccountCreated)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _LegacySignUpViewState() when $default != null: +return $default(_that.currentIndex,_that.document,_that.documentType,_that.acceptTerms,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.isCreated,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.showAccountCreated);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 Function( int currentIndex, String document, String documentType, bool acceptTerms, String relationType, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, bool isCreated, String placeOfBirth, String birthCountry, String birthCountryCode, LegacyAddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, bool showAccountCreated) $default,) {final _that = this; +switch (_that) { +case _LegacySignUpViewState(): +return $default(_that.currentIndex,_that.document,_that.documentType,_that.acceptTerms,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.isCreated,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.showAccountCreated);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? Function( int currentIndex, String document, String documentType, bool acceptTerms, String relationType, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, bool isCreated, String placeOfBirth, String birthCountry, String birthCountryCode, LegacyAddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, bool showAccountCreated)? $default,) {final _that = this; +switch (_that) { +case _LegacySignUpViewState() when $default != null: +return $default(_that.currentIndex,_that.document,_that.documentType,_that.acceptTerms,_that.relationType,_that.firstName,_that.lastName,_that.email,_that.phone,_that.dialCode,_that.language,_that.bornAt,_that.password,_that.repeatPassword,_that.isShowPassword,_that.isCreated,_that.placeOfBirth,_that.birthCountry,_that.birthCountryCode,_that.address,_that.emailError,_that.passwordError,_that.phoneError,_that.errorMessage,_that.isLoading,_that.showErrors,_that.showAccountCreated);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _LegacySignUpViewState implements LegacySignUpViewState { + const _LegacySignUpViewState({this.currentIndex = 0, this.document = '', this.documentType = '', this.acceptTerms = false, this.relationType = '', this.firstName = '', this.lastName = '', this.email = '', this.phone = '', this.dialCode = '+34', this.language = '', this.bornAt, this.password = '', this.repeatPassword = '', this.isShowPassword = false, this.isCreated = false, this.placeOfBirth = '', this.birthCountry = 'España', this.birthCountryCode = 'ES', this.address = const LegacyAddressViewState(), this.emailError = '', this.passwordError = '', this.phoneError = '', this.errorMessage = '', this.isLoading = false, this.showErrors = false, this.showAccountCreated = false}); + + +@override@JsonKey() final int currentIndex; +@override@JsonKey() final String document; +@override@JsonKey() final String documentType; +@override@JsonKey() final bool acceptTerms; +@override@JsonKey() final String relationType; +@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 bool isCreated; +@override@JsonKey() final String placeOfBirth; +@override@JsonKey() final String birthCountry; +@override@JsonKey() final String birthCountryCode; +@override@JsonKey() final LegacyAddressViewState 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 bool showAccountCreated; + +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$LegacySignUpViewStateCopyWith<_LegacySignUpViewState> get copyWith => __$LegacySignUpViewStateCopyWithImpl<_LegacySignUpViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LegacySignUpViewState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.document, document) || other.document == document)&&(identical(other.documentType, documentType) || other.documentType == documentType)&&(identical(other.acceptTerms, acceptTerms) || other.acceptTerms == acceptTerms)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(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.isCreated, isCreated) || other.isCreated == isCreated)&&(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.showAccountCreated, showAccountCreated) || other.showAccountCreated == showAccountCreated)); +} + + +@override +int get hashCode => Object.hashAll([runtimeType,currentIndex,document,documentType,acceptTerms,relationType,firstName,lastName,email,phone,dialCode,language,bornAt,password,repeatPassword,isShowPassword,isCreated,placeOfBirth,birthCountry,birthCountryCode,address,emailError,passwordError,phoneError,errorMessage,isLoading,showErrors,showAccountCreated]); + +@override +String toString() { + return 'LegacySignUpViewState(currentIndex: $currentIndex, document: $document, documentType: $documentType, acceptTerms: $acceptTerms, relationType: $relationType, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, dialCode: $dialCode, language: $language, bornAt: $bornAt, password: $password, repeatPassword: $repeatPassword, isShowPassword: $isShowPassword, isCreated: $isCreated, placeOfBirth: $placeOfBirth, birthCountry: $birthCountry, birthCountryCode: $birthCountryCode, address: $address, emailError: $emailError, passwordError: $passwordError, phoneError: $phoneError, errorMessage: $errorMessage, isLoading: $isLoading, showErrors: $showErrors, showAccountCreated: $showAccountCreated)'; +} + + +} + +/// @nodoc +abstract mixin class _$LegacySignUpViewStateCopyWith<$Res> implements $LegacySignUpViewStateCopyWith<$Res> { + factory _$LegacySignUpViewStateCopyWith(_LegacySignUpViewState value, $Res Function(_LegacySignUpViewState) _then) = __$LegacySignUpViewStateCopyWithImpl; +@override @useResult +$Res call({ + int currentIndex, String document, String documentType, bool acceptTerms, String relationType, String firstName, String lastName, String email, String phone, String dialCode, String language, DateTime? bornAt, String password, String repeatPassword, bool isShowPassword, bool isCreated, String placeOfBirth, String birthCountry, String birthCountryCode, LegacyAddressViewState address, String emailError, String passwordError, String phoneError, String errorMessage, bool isLoading, bool showErrors, bool showAccountCreated +}); + + +@override $LegacyAddressViewStateCopyWith<$Res> get address; + +} +/// @nodoc +class __$LegacySignUpViewStateCopyWithImpl<$Res> + implements _$LegacySignUpViewStateCopyWith<$Res> { + __$LegacySignUpViewStateCopyWithImpl(this._self, this._then); + + final _LegacySignUpViewState _self; + final $Res Function(_LegacySignUpViewState) _then; + +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? document = null,Object? documentType = null,Object? acceptTerms = null,Object? relationType = 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? isCreated = 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? showAccountCreated = null,}) { + return _then(_LegacySignUpViewState( +currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable +as int,document: null == document ? _self.document : document // 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,relationType: null == relationType ? _self.relationType : relationType // 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,isCreated: null == isCreated ? _self.isCreated : isCreated // ignore: cast_nullable_to_non_nullable +as bool,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 LegacyAddressViewState,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,showAccountCreated: null == showAccountCreated ? _self.showAccountCreated : showAccountCreated // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +/// Create a copy of LegacySignUpViewState +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$LegacyAddressViewStateCopyWith<$Res> get address { + + return $LegacyAddressViewStateCopyWith<$Res>(_self.address, (value) { + return _then(_self.copyWith(address: value)); + }); +} +} + +// dart format on diff --git a/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/sign_up_builder.dart b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/sign_up_builder.dart new file mode 100644 index 00000000..cf49d51a --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/features/sign_up/sign_up_builder.dart @@ -0,0 +1,18 @@ +import 'package:legacy_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'; +import 'package:navigation/navigation.dart'; + +class LegacySignupBuilder { + const LegacySignupBuilder(); + + Page buildPage(BuildContext context, GoRouterState state) { + final NavigationContract navigationContract = GetIt.I(); + + return MaterialPage( + key: state.pageKey, + child: LegacySignupScreen(navigationContract: navigationContract), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/form_error_banner.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/form_error_banner.dart new file mode 100644 index 00000000..8c356c38 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/form_error_banner.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class LegacyFormErrorBanner extends StatelessWidget { + final String message; + + const LegacyFormErrorBanner({super.key, required this.message}); + + @override + Widget build(BuildContext context) { + if (message.trim().isEmpty) return const SizedBox.shrink(); + + return Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.red.withValues(alpha: 0.08), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.red.withValues(alpha: 0.35)), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Icon(Icons.error_outline, size: 18, color: Colors.red), + const SizedBox(width: 8), + Expanded( + child: Text( + message, + style: const TextStyle(fontSize: 14, height: 1.2), + ), + ), + ], + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart new file mode 100644 index 00000000..84439b8f --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/form_step_layout.dart @@ -0,0 +1,132 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class LegacyFormStepLayout extends ConsumerWidget { + final int currentStep; + final int numSteps; + final String? supertitle; + final String title; + final String? subtitle; + final List body; + final List? footer; + final VoidCallback nextStep; + final VoidCallback previousStep; + + const LegacyFormStepLayout({ + super.key, + required this.title, + this.subtitle, + this.supertitle, + required this.currentStep, + required this.numSteps, + required this.body, + this.footer, + required this.nextStep, + required this.previousStep, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: SafeArea( + child: SingleChildScrollView( + child: Container( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + padding: EdgeInsets.only(left: 24, right: 24), + child: Column( + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: StepIndicator( + total: numSteps, + current: currentStep, + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + ), + SizedBox(height: 16), + if (supertitle != null) + Text( + supertitle!, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + SizedBox(height: 10), + Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 16), + if (subtitle != null) + Text( + subtitle!, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + ], + ), + ...body, + SizedBox(height: 16), + if (footer == null) + navigationButtons( + currentStep, + numSteps, + nextStep, + previousStep, + theme, + ), + ...(footer ?? []), + ], + ), + ), + ), + ), + ); + } + + Widget navigationButtons( + int currentStep, + int numSteps, + VoidCallback nextStep, + VoidCallback previousStep, + ThemePort theme, + ) { + if (currentStep == numSteps) { + return PrimaryButton( + onPressed: nextStep, + text: "Continuar", + color: theme.getColorFor(ThemeCode.buttonPrimary), + ); + } else { + return Row( + spacing: 16, + children: [ + Expanded( + child: SecondaryButton( + onPressed: previousStep, + text: "Atrás", + size: 16, + ), + ), + Expanded( + child: PrimaryButton( + onPressed: nextStep, + text: "Siguiente", + size: 16, + color: theme.getColorFor(ThemeCode.buttonSecondary), + ), + ), + ], + ); + } + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart new file mode 100644 index 00000000..41523c10 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/layouts/sign_up_layout.dart @@ -0,0 +1,105 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; + +class LegacySignUpLayout extends StatelessWidget { + final ThemePort theme; + final String title; + final String subtitle; + final String supertitle; + final int currentStep; + final int numSteps; + + final Widget body; + + final VoidCallback onBackPressed; + final VoidCallback onNextPressed; + + const LegacySignUpLayout({ + super.key, + required this.theme, + required this.title, + required this.subtitle, + required this.supertitle, + required this.currentStep, + required this.numSteps, + required this.body, + required this.onBackPressed, + required this.onNextPressed, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: SafeArea( + child: Container( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + padding: const EdgeInsets.only(left: 24, right: 24), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: StepIndicator( + total: numSteps, + current: currentStep, + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + ), + const SizedBox(height: 8), + Text( + supertitle, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 18), + ), + const SizedBox(height: 10), + Text( + title, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 16), + Text( + subtitle, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 18), + ), + const SizedBox(height: 16), + + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.only(bottom: 16), + child: body, + ), + ), + + Row( + spacing: 16, + children: [ + Expanded( + child: SecondaryButton( + onPressed: onBackPressed, + text: "Atrás", + size: 16, + ), + ), + Expanded( + child: PrimaryButton( + onPressed: onNextPressed, + text: "Siguiente", + size: 16, + color: Color.fromRGBO(88, 142, 165, 1), + ), + ), + ], + ), + const SizedBox(height: 12), + ], + ), + ), + ), + ); + } +} diff --git a/modules/legacy/modules/legacy_auth/lib/src/widgets/steps.dart b/modules/legacy/modules/legacy_auth/lib/src/widgets/steps.dart new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/lib/src/widgets/steps.dart @@ -0,0 +1 @@ + diff --git a/modules/legacy/modules/legacy_auth/pubspec.yaml b/modules/legacy/modules/legacy_auth/pubspec.yaml new file mode 100644 index 00000000..50105912 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/pubspec.yaml @@ -0,0 +1,64 @@ +name: legacy_auth +description: "Legacy auth module for SaveFamily." +publish_to: 'none' +version: 0.0.1 +homepage: + +environment: + sdk: ^3.9.2 + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + #modules dependencies go here + home: + path: ../../../../modules/home + #packages dependencies go here + design_system: + path: ../../../../packages/design_system + navigation: + path: ../../../../packages/navigation + sf_localizations: + path: ../../../../packages/sf_localizations + sf_infrastructure: + path: ../../../../packages/sf_infrastructure + utils: + path: ../../../../packages/utils + sf_shared: + path: ../../../../packages/sf_shared + payments: + path: ../../../../packages/payments + fonts: + path: ../../../../packages/fonts + #dependencies go here + flutter_svg: ^2.2.1 + get_it: ^9.0.5 + go_router: ^17.0.0 + flutter_riverpod: ^3.0.3 + freezed_annotation: ^3.1.0 + freezed: ^3.2.3 + dio: ^5.9.0 + country_code_picker: ^3.4.1 + json_annotation: ^4.9.0 + json_serializable: ^6.11.2 + uuid: ^4.5.2 + mobile_scanner: ^7.1.4 + dio_cookie_manager: ^3.3.0 + cookie_jar: ^4.0.8 + path_provider: ^2.1.5 + shared_preferences: ^2.5.4 + l10n_countries: ^1.3.1 + sealed_countries: ^2.8.0 + flutter_map: ^8.2.2 + latlong2: ^0.9.1 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + riverpod_generator: ^3.0.3 + build_runner: ^2.7.1 + riverpod_lint: ^3.0.3 + +flutter: diff --git a/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml b/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml new file mode 100644 index 00000000..f391afc6 --- /dev/null +++ b/modules/legacy/modules/legacy_auth/pubspec_overrides.yaml @@ -0,0 +1,30 @@ +# melos_managed_dependency_overrides: activity,auth,design_system,flutter_treezor_entrust_sdk_bridge,fonts,home,navigation,notifications,payments,sca_treezor,sf_infrastructure,sf_localizations,sf_shared,utils +dependency_overrides: + activity: + path: ../../../activity + auth: + path: ../../../auth + design_system: + path: ../../../../packages/design_system + flutter_treezor_entrust_sdk_bridge: + path: ../../../../packages/flutter_treezor_entrust_sdk_bridge + fonts: + path: ../../../../packages/fonts + home: + path: ../../../home + navigation: + path: ../../../../packages/navigation + notifications: + path: ../../../notifications + payments: + path: ../../../../packages/payments + sca_treezor: + path: ../../../../packages/sca_treezor + sf_infrastructure: + path: ../../../../packages/sf_infrastructure + sf_localizations: + path: ../../../../packages/sf_localizations + sf_shared: + path: ../../../../packages/sf_shared + utils: + path: ../../../../packages/utils diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml index 230542be..aecb0213 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml @@ -7,6 +7,6 @@ 2.6.4 - 20260305000000 + 20260306000000 diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 index dd1e348e..26c72f5c 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.md5 @@ -1 +1 @@ -27520891f03eb1f306f15560957d864c \ No newline at end of file +9118b6cbe462c0b755ae39f29c647c7d \ No newline at end of file diff --git a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 index 4fb86c3b..354e4b68 100644 --- a/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 +++ b/packages/flutter_treezor_entrust_sdk_bridge/android/build/com/entrust/antelop/antelop/maven-metadata.xml.sha1 @@ -1 +1 @@ -5f03e9abcdee6116d89febb0fcdb64b2827d1f1a \ No newline at end of file +903dc88b372a947a02ddf473496fc4c33afe51c6 \ No newline at end of file diff --git a/packages/navigation/lib/app_routes.dart b/packages/navigation/lib/app_routes.dart index c2532849..a3c6863f 100644 --- a/packages/navigation/lib/app_routes.dart +++ b/packages/navigation/lib/app_routes.dart @@ -50,6 +50,14 @@ class AppRoutes { static const remoteConnection = '$deviceManagement/remote_connection'; static const locateDevice = '$deviceManagement/locate_device'; + static const legacyLogin = '$legacy/login'; + static const legacySignup = '$legacy/signup'; + static const legacyOnboarding = '$legacy/onboarding'; + static const legacyLinkPhone = '$legacy/request_link_phone'; + static const legacyPhoneCode = '$legacy/verify_link_phone_code'; + static const legacyDeviceSetup = '$legacy/device_setup'; + static const legacyRecoverPassword = '$legacy/recover_password'; + static const accountSettings = '$controlPanel/account_settings'; static const personalData = '$accountSettings/personal_data'; static const changePassword = '$accountSettings/change_password'; diff --git a/packages/sf_localizations/assets/l10n/de.json b/packages/sf_localizations/assets/l10n/de.json index b11c8d96..9aa28763 100644 --- a/packages/sf_localizations/assets/l10n/de.json +++ b/packages/sf_localizations/assets/l10n/de.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Bestätigungscode", "twoFactorCodeHint": "6-stelliger Code", "twoFactorVerify": "Bestätigen", + "twoFactorResend": "Code erneut senden", + "twoFactorCodeResent": "Code erfolgreich erneut gesendet", "close": "Schließen", "errorTwoFactorCodeRequired": "Der Bestätigungscode ist erforderlich.", "errorTwoFactorCodeInvalidLength": "Der Code muss 6-stellig sein.", "errorTwoFactorCodeInvalid": "Ungültiger Code. Bitte versuche es erneut.", + "errorTwoFactorNoMethods": "Keine 2FA-Methoden verfügbar.", + "errorTwoFactorResendFailed": "Fehler beim erneuten Senden des Codes.", + "loginSuccess": "Anmeldung erfolgreich", "stepUserContactSupertitle": "Benutzer und Kontakt", "stepUserContactTitle": "Erstelle dein Konto", "stepUserContactSubtitle": "Mit deiner E-Mail und deiner Telefonnummer können wir dich jederzeit informieren", diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index 5f10ae81..9356f274 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Verification code", "twoFactorCodeHint": "6-digit code", "twoFactorVerify": "Verify", + "twoFactorResend": "Resend code", + "twoFactorCodeResent": "Code resent successfully", "close": "Close", "errorTwoFactorCodeRequired": "The verification code is required.", "errorTwoFactorCodeInvalidLength": "The code must be 6 digits.", "errorTwoFactorCodeInvalid": "Invalid code. Please try again.", + "errorTwoFactorNoMethods": "No 2FA methods available.", + "errorTwoFactorResendFailed": "Error resending code.", + "loginSuccess": "Login successful", "stepUserContactSupertitle": "User & contact", "stepUserContactTitle": "Create your account", "stepUserContactSubtitle": "With your email and phone number we can keep you informed at all times", @@ -475,6 +480,7 @@ "deleteAccount": "Delete account", "logOut": "Log out", "loginEmail": "(Login email)", + "loginSuccess": "Login successful", "userNameLabel": "User name", "userPhoneLabel": "User phone number", "contactEmailLabel": "Contact email", diff --git a/packages/sf_localizations/assets/l10n/es.json b/packages/sf_localizations/assets/l10n/es.json index cc4f5ca3..8204e4aa 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Código de verificación", "twoFactorCodeHint": "Código de 6 dígitos", "twoFactorVerify": "Verificar", + "twoFactorResend": "Reenviar código", + "twoFactorCodeResent": "Código reenviado correctamente", "close": "Cerrar", "errorTwoFactorCodeRequired": "El código de verificación es obligatorio.", "errorTwoFactorCodeInvalidLength": "El código debe tener 6 dígitos.", "errorTwoFactorCodeInvalid": "Código incorrecto. Inténtalo de nuevo.", + "errorTwoFactorNoMethods": "No hay métodos 2FA disponibles.", + "errorTwoFactorResendFailed": "Error al reenviar el código.", + "loginSuccess": "Inicio de sesión exitoso", "stepUserContactSupertitle": "Usuario y contacto", "stepUserContactTitle": "Crea tu usuario", "stepUserContactSubtitle": "Con tu email y tu número podremos mantenerte siempre informado", diff --git a/packages/sf_localizations/assets/l10n/fr.json b/packages/sf_localizations/assets/l10n/fr.json index 4bd2bf8b..1504ea77 100644 --- a/packages/sf_localizations/assets/l10n/fr.json +++ b/packages/sf_localizations/assets/l10n/fr.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Code de vérification", "twoFactorCodeHint": "Code à 6 chiffres", "twoFactorVerify": "Vérifier", + "twoFactorResend": "Renvoyer le code", + "twoFactorCodeResent": "Code renvoyé avec succès", "close": "Fermer", "errorTwoFactorCodeRequired": "Le code de vérification est obligatoire.", "errorTwoFactorCodeInvalidLength": "Le code doit contenir 6 chiffres.", "errorTwoFactorCodeInvalid": "Code incorrect. Veuillez réessayer.", + "errorTwoFactorNoMethods": "Aucune méthode 2FA disponible.", + "errorTwoFactorResendFailed": "Erreur lors du renvoi du code.", + "loginSuccess": "Connexion réussie", "stepUserContactSupertitle": "Utilisateur et contact", "stepUserContactTitle": "Crée ton compte", "stepUserContactSubtitle": "Avec ton e-mail et ton numéro, nous pourrons te tenir informé à tout moment", diff --git a/packages/sf_localizations/assets/l10n/it.json b/packages/sf_localizations/assets/l10n/it.json index e2469855..1cf4b0d5 100644 --- a/packages/sf_localizations/assets/l10n/it.json +++ b/packages/sf_localizations/assets/l10n/it.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Codice di verifica", "twoFactorCodeHint": "Codice a 6 cifre", "twoFactorVerify": "Verifica", + "twoFactorResend": "Invia di nuovo il codice", + "twoFactorCodeResent": "Codice inviato di nuovo con successo", "close": "Chiudi", "errorTwoFactorCodeRequired": "Il codice di verifica è obbligatorio.", "errorTwoFactorCodeInvalidLength": "Il codice deve essere di 6 cifre.", "errorTwoFactorCodeInvalid": "Codice non valido. Riprova.", + "errorTwoFactorNoMethods": "Nessun metodo 2FA disponibile.", + "errorTwoFactorResendFailed": "Errore durante il reinvio del codice.", + "loginSuccess": "Accesso riuscito", "stepUserContactSupertitle": "Utente e contatti", "stepUserContactTitle": "Crea il tuo account", "stepUserContactSubtitle": "Con la tua email e il tuo numero potremo tenerti sempre informato", diff --git a/packages/sf_localizations/assets/l10n/pt.json b/packages/sf_localizations/assets/l10n/pt.json index 2a47da6f..70c15bf5 100644 --- a/packages/sf_localizations/assets/l10n/pt.json +++ b/packages/sf_localizations/assets/l10n/pt.json @@ -67,10 +67,15 @@ "twoFactorCodeLabel": "Código de verificação", "twoFactorCodeHint": "Código de 6 dígitos", "twoFactorVerify": "Verificar", + "twoFactorResend": "Reenviar código", + "twoFactorCodeResent": "Código reenviado com sucesso", "close": "Fechar", "errorTwoFactorCodeRequired": "O código de verificação é obrigatório.", "errorTwoFactorCodeInvalidLength": "O código deve ter 6 dígitos.", "errorTwoFactorCodeInvalid": "Código inválido. Tenta novamente.", + "errorTwoFactorNoMethods": "Nenhum método 2FA disponível.", + "errorTwoFactorResendFailed": "Erro ao reenviar o código.", + "loginSuccess": "Login realizado com sucesso", "stepUserContactSupertitle": "Utilizador e contacto", "stepUserContactTitle": "Cria a tua conta", "stepUserContactSubtitle": "Com o teu email e o teu número poderemos manter-te sempre informado", diff --git a/packages/sf_localizations/lib/src/generated/i18n.dart b/packages/sf_localizations/lib/src/generated/i18n.dart index f2e08144..fbf1b614 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -76,11 +76,16 @@ class I18n { static const String twoFactorCodeLabel = 'twoFactorCodeLabel'; static const String twoFactorCodeHint = 'twoFactorCodeHint'; static const String twoFactorVerify = 'twoFactorVerify'; + static const String twoFactorResend = 'twoFactorResend'; + static const String twoFactorCodeResent = 'twoFactorCodeResent'; static const String close = 'close'; static const String errorTwoFactorCodeRequired = 'errorTwoFactorCodeRequired'; static const String errorTwoFactorCodeInvalidLength = 'errorTwoFactorCodeInvalidLength'; static const String errorTwoFactorCodeInvalid = 'errorTwoFactorCodeInvalid'; + static const String errorTwoFactorNoMethods = 'errorTwoFactorNoMethods'; + static const String errorTwoFactorResendFailed = 'errorTwoFactorResendFailed'; + static const String loginSuccess = 'loginSuccess'; static const String stepUserContactSupertitle = 'stepUserContactSupertitle'; static const String stepUserContactTitle = 'stepUserContactTitle';