From 0f30c7f422888f4bbdeafb4402767ff777cf8bb1 Mon Sep 17 00:00:00 2001 From: AlcalaJulian Date: Tue, 9 Dec 2025 10:08:36 +0100 Subject: [PATCH] added linkPhone use cases, auth repository providers and data folder --- .dart_tool/extension_discovery/README.md | 31 +++++ .dart_tool/extension_discovery/vs_code.json | 1 + apps/mobile_app/.env | 1 + apps/mobile_app/lib/config/env/env.dart | 1 + .../lib/config/env/questia_env_config.dart | 2 + .../mobile_app/lib/navigation/app_router.dart | 10 +- apps/mobile_app/pubspec.lock | 8 -- modules/auth/lib/auth.dart | 4 +- .../auth_remote_datasource_impl.dart | 7 +- .../use_cases/link_phone_use_case_impl.dart | 10 +- .../request_link_phone_builder.dart} | 8 +- .../request_link_phone_screen.dart} | 8 +- .../{ => state}/link_phone_view_model.dart | 78 +++++++++++- .../{ => state}/link_phone_view_state.dart | 1 + .../link_phone_view_state.freezed.dart | 39 +++--- .../verify_link_phone_code_builder.dart} | 8 +- .../verify_link_phone_code_screen.dart | 118 +++++++++++++++++ .../widgets/link_phone_code_input.dart | 86 +++++++++++++ .../login/presentation/phone_code_screen.dart | 119 ------------------ .../src/dropdowns/country_prefix_picker.dart | 4 +- .../lib/src/inputs/textfields.dart | 1 + .../.dart_tool/extension_discovery/README.md | 31 +++++ .../extension_discovery/vs_code.json | 1 + packages/navigation/lib/app_routes.dart | 4 +- .../lib/configure_dependencies.dart | 1 + .../lib/src/env/env_contract.dart | 1 + .../lib/src/network/dio_client.dart | 2 + packages/sf_localizations/assets/l10n/de.json | 10 +- packages/sf_localizations/assets/l10n/en.json | 10 +- packages/sf_localizations/assets/l10n/es.json | 10 +- packages/sf_localizations/assets/l10n/fr.json | 10 +- packages/sf_localizations/assets/l10n/it.json | 10 +- packages/sf_localizations/assets/l10n/pt.json | 10 +- .../lib/src/generated/i18n.dart | 8 ++ 34 files changed, 470 insertions(+), 183 deletions(-) create mode 100644 .dart_tool/extension_discovery/README.md create mode 100644 .dart_tool/extension_discovery/vs_code.json rename modules/auth/lib/src/features/link_phone/{link_phone_builder.dart => presentation/request_phone/request_link_phone_builder.dart} (60%) rename modules/auth/lib/src/features/link_phone/presentation/{link_phone_screen.dart => request_phone/request_link_phone_screen.dart} (92%) rename modules/auth/lib/src/features/link_phone/presentation/{ => state}/link_phone_view_model.dart (50%) rename modules/auth/lib/src/features/link_phone/presentation/{ => state}/link_phone_view_state.dart (91%) rename modules/auth/lib/src/features/link_phone/presentation/{ => state}/link_phone_view_state.freezed.dart (84%) rename modules/auth/lib/src/features/{login/phone_code_builder.dart => link_phone/presentation/verify_code/verify_link_phone_code_builder.dart} (59%) create mode 100644 modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart create mode 100644 modules/auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart delete mode 100644 modules/auth/lib/src/features/login/presentation/phone_code_screen.dart create mode 100644 packages/fonts/.dart_tool/extension_discovery/README.md create mode 100644 packages/fonts/.dart_tool/extension_discovery/vs_code.json diff --git a/.dart_tool/extension_discovery/README.md b/.dart_tool/extension_discovery/README.md new file mode 100644 index 00000000..9dc6757b --- /dev/null +++ b/.dart_tool/extension_discovery/README.md @@ -0,0 +1,31 @@ +Extension Discovery Cache +========================= + +This folder is used by `package:extension_discovery` to cache lists of +packages that contains extensions for other packages. + +DO NOT USE THIS FOLDER +---------------------- + + * Do not read (or rely) the contents of this folder. + * Do write to this folder. + +If you're interested in the lists of extensions stored in this folder use the +API offered by package `extension_discovery` to get this information. + +If this package doesn't work for your use-case, then don't try to read the +contents of this folder. It may change, and will not remain stable. + +Use package `extension_discovery` +--------------------------------- + +If you want to access information from this folder. + +Feel free to delete this folder +------------------------------- + +Files in this folder act as a cache, and the cache is discarded if the files +are older than the modification time of `.dart_tool/package_config.json`. + +Hence, it should never be necessary to clear this cache manually, if you find a +need to do please file a bug. diff --git a/.dart_tool/extension_discovery/vs_code.json b/.dart_tool/extension_discovery/vs_code.json new file mode 100644 index 00000000..ae1a36a6 --- /dev/null +++ b/.dart_tool/extension_discovery/vs_code.json @@ -0,0 +1 @@ +{"version":2,"entries":[{"package":"sf_app_platform_mono_repo","rootUri":"../","packageUri":"lib/"}]} \ No newline at end of file diff --git a/apps/mobile_app/.env b/apps/mobile_app/.env index f8131abf..b9c4372a 100644 --- a/apps/mobile_app/.env +++ b/apps/mobile_app/.env @@ -1 +1,2 @@ API_BASE_URL=https://api-neki-b2b.neki.es/gateway/api/ +API_ORIGIN =https://neki-b2b.neki.es \ No newline at end of file diff --git a/apps/mobile_app/lib/config/env/env.dart b/apps/mobile_app/lib/config/env/env.dart index adaf9578..5cd82ec3 100644 --- a/apps/mobile_app/lib/config/env/env.dart +++ b/apps/mobile_app/lib/config/env/env.dart @@ -2,6 +2,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; class Env { static String get apiBaseUrl => dotenv.env['API_BASE_URL'] ?? ''; + static String get apiOrigin => dotenv.env['API_ORIGIN'] ?? ''; // static String get apiKey => dotenv.env['API_KEY'] ?? ''; } diff --git a/apps/mobile_app/lib/config/env/questia_env_config.dart b/apps/mobile_app/lib/config/env/questia_env_config.dart index fee4026c..d461652f 100644 --- a/apps/mobile_app/lib/config/env/questia_env_config.dart +++ b/apps/mobile_app/lib/config/env/questia_env_config.dart @@ -4,6 +4,8 @@ import 'env.dart'; class QuestiaEnvConfig implements EnvConfig { @override String get apiBaseUrl => Env.apiBaseUrl; + @override + String get apiOrigin => Env.apiOrigin; // @override // String get apiKey => Env.apiKey; diff --git a/apps/mobile_app/lib/navigation/app_router.dart b/apps/mobile_app/lib/navigation/app_router.dart index 237198d5..e7ee4782 100644 --- a/apps/mobile_app/lib/navigation/app_router.dart +++ b/apps/mobile_app/lib/navigation/app_router.dart @@ -15,7 +15,7 @@ late final GoRouter appRouter; void configureAppRouter() { appRouter = GoRouter( navigatorKey: rootNavigatorKey, - initialLocation: AppRoutes.linkPhone, + initialLocation: AppRoutes.login, debugLogDiagnostics: true, routes: [ GoRoute( @@ -35,13 +35,13 @@ void configureAppRouter() { ), GoRoute( path: AppRoutes.linkPhone, - name: 'link_phone', - pageBuilder: LinkPhoneBuilder().buildPage, + name: 'request_link_phone', + pageBuilder: RequestLinkPhoneBuilder().buildPage, ), GoRoute( path: AppRoutes.phoneCode, - name: 'phone_code', - pageBuilder: PhoneCodeBuilder().buildPage, + name: 'Verify_link_phone_code', + pageBuilder: VerifyLinkPhoneCodeBuilder().buildPage, ), GoRoute( path: AppRoutes.recoverPassword, diff --git a/apps/mobile_app/pubspec.lock b/apps/mobile_app/pubspec.lock index a44e05e1..d43830a6 100644 --- a/apps/mobile_app/pubspec.lock +++ b/apps/mobile_app/pubspec.lock @@ -448,14 +448,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.2" - intl_phone_field_v2: - dependency: transitive - description: - name: intl_phone_field_v2 - sha256: b1e5077e31cc8705639a69b2e0410a8ecc858c3e518726d99b378b6c35adfefb - url: "https://pub.dev" - source: hosted - version: "4.0.5" io: dependency: transitive description: diff --git a/modules/auth/lib/auth.dart b/modules/auth/lib/auth.dart index e425af89..2991c63d 100644 --- a/modules/auth/lib/auth.dart +++ b/modules/auth/lib/auth.dart @@ -1,7 +1,7 @@ export 'src/features/device_sign_up/link_watch/create_profile_screen.dart'; export 'src/features/onboarding/onboarding_builder.dart'; -export 'src/features/link_phone/link_phone_builder.dart'; -export 'src/features/login/phone_code_builder.dart'; +export 'src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart'; +export 'src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart'; export 'src/features/login/login_builder.dart'; export 'src/features/recover_password/recover_password_builder.dart'; export 'src/features/device_sign_up/device_signup_builder.dart'; diff --git a/modules/auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart b/modules/auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart index 80b14c6d..1053f587 100644 --- a/modules/auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart +++ b/modules/auth/lib/src/core/data/datasource/auth_remote_datasource_impl.dart @@ -16,7 +16,10 @@ class AuthRemoteDatasourceImpl implements AuthRemoteDatasource { body: {'phone': phone}, ); } on DioException catch (error) { - throw _mapDioError(error, defaultMessage: 'Error al solicitar el código'); + throw _mapDioError( + error, + defaultMessage: error.response?.data ?? 'Error to request phone code', + ); } } @@ -31,7 +34,7 @@ class AuthRemoteDatasourceImpl implements AuthRemoteDatasource { body: {'phone': phone, 'code': code}, ); } on DioException catch (error) { - throw _mapDioError(error, defaultMessage: 'Error al verificar el código'); + throw _mapDioError(error, defaultMessage: 'Error in verification code'); } } diff --git a/modules/auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart b/modules/auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart index 18e3c34e..8ae00e74 100644 --- a/modules/auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart +++ b/modules/auth/lib/src/features/link_phone/domain/use_cases/link_phone_use_case_impl.dart @@ -7,12 +7,14 @@ class LinkPhoneUseCaseImpl implements LinkPhoneUseCase { final AuthRepository _repository; @override - Future requestCode({required String phone}) { - return _repository.requestPhoneCode(phone: phone); + 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}) { - return _repository.verifyPhoneCode(phone: phone, code: code); + 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/auth/lib/src/features/link_phone/link_phone_builder.dart b/modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart similarity index 60% rename from modules/auth/lib/src/features/link_phone/link_phone_builder.dart rename to modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart index 543f46e5..89af07b7 100644 --- a/modules/auth/lib/src/features/link_phone/link_phone_builder.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_builder.dart @@ -1,18 +1,18 @@ -import 'package:auth/src/features/link_phone/presentation/link_phone_screen.dart'; +import 'package:auth/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:get_it/get_it.dart'; import 'package:navigation/navigation.dart'; -class LinkPhoneBuilder { - const LinkPhoneBuilder(); +class RequestLinkPhoneBuilder { + const RequestLinkPhoneBuilder(); Page buildPage(BuildContext context, GoRouterState state) { final NavigationContract navigationContract = GetIt.I(); return MaterialPage( key: state.pageKey, - child: LinkPhoneScreen(navigationContract: navigationContract), + child: RequestLinkPhoneScreen(navigationContract: navigationContract), ); } } diff --git a/modules/auth/lib/src/features/link_phone/presentation/link_phone_screen.dart b/modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart similarity index 92% rename from modules/auth/lib/src/features/link_phone/presentation/link_phone_screen.dart rename to modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart index a6999e39..093aeda2 100644 --- a/modules/auth/lib/src/features/link_phone/presentation/link_phone_screen.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/request_phone/request_link_phone_screen.dart @@ -1,15 +1,14 @@ -import 'package:auth/src/features/link_phone/presentation/link_phone_view_model.dart'; -import 'package:design_system/src/dropdowns/country_prefix_picker.dart'; +import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_model.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; -class LinkPhoneScreen extends ConsumerWidget { +class RequestLinkPhoneScreen extends ConsumerWidget { final NavigationContract navigationContract; - const LinkPhoneScreen({super.key, required this.navigationContract}); + const RequestLinkPhoneScreen({super.key, required this.navigationContract}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -56,6 +55,7 @@ class LinkPhoneScreen extends ConsumerWidget { spacing: 10, children: [ CountryPrefixPicker( + headerText: context.translate(I18n.selectYourCountry), initialCountryCode: viewState.dialCode, onChanged: (country) { viewModel.updateDialCode( diff --git a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_model.dart b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart similarity index 50% rename from modules/auth/lib/src/features/link_phone/presentation/link_phone_view_model.dart rename to modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart index 8b5a616e..caca128f 100644 --- a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_model.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_model.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_case.dart'; -import 'package:auth/src/features/link_phone/presentation/link_phone_view_state.dart'; +import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_state.dart'; final linkPhoneViewModelProvider = NotifierProvider.autoDispose( @@ -13,6 +13,7 @@ final linkPhoneViewModelProvider = class LinkPhoneViewModel extends Notifier { late final LinkPhoneUseCase _linkPhoneUseCase; late final TextEditingController phoneNumberController; + late final TextEditingController codeController; @override LinkPhoneViewState build() { @@ -21,6 +22,8 @@ class LinkPhoneViewModel extends Notifier { phoneNumberController = TextEditingController(); phoneNumberController.addListener(_onPhoneNumberChanged); + codeController = TextEditingController(); + ref.onDispose(disposeControllers); return const LinkPhoneViewState(); @@ -28,18 +31,34 @@ class LinkPhoneViewModel extends Notifier { void _onPhoneNumberChanged() { final raw = phoneNumberController.text; - state = state.copyWith(phoneNumber: raw, errorMessage: ''); + state = state.copyWith( + phoneNumber: raw, + errorMessage: '', + codeVerified: false, + ); } void updateDialCode(String dialCode) { - state = state.copyWith(dialCode: dialCode, errorMessage: ''); + state = state.copyWith( + dialCode: dialCode, + errorMessage: '', + codeVerified: false, + ); + } + + void updateCode(String code) { + codeController.text = code; + state = state.copyWith(errorMessage: '', codeVerified: false); } Future requestCode() async { final trimmedNumber = state.phoneNumber.trim(); if (trimmedNumber.isEmpty) { - state = state.copyWith(errorMessage: 'El teléfono no puede estar vacío'); + state = state.copyWith( + errorMessage: 'errorMessagePhoneIsEmpty', + codeVerified: false, + ); return; } @@ -49,6 +68,7 @@ class LinkPhoneViewModel extends Notifier { isLoading: true, errorMessage: '', codeRequested: false, + codeVerified: false, ); try { @@ -67,6 +87,55 @@ class LinkPhoneViewModel extends Notifier { 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, ); } } @@ -74,5 +143,6 @@ class LinkPhoneViewModel extends Notifier { void disposeControllers() { phoneNumberController.removeListener(_onPhoneNumberChanged); phoneNumberController.dispose(); + codeController.dispose(); } } diff --git a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.dart b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart similarity index 91% rename from modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.dart rename to modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart index 328c4e72..0293d3e7 100644 --- a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.dart @@ -10,5 +10,6 @@ abstract class LinkPhoneViewState with _$LinkPhoneViewState { @Default('') String errorMessage, @Default(false) bool isLoading, @Default(false) bool codeRequested, + @Default(false) bool codeVerified, }) = _LinkPhoneViewState; } diff --git a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.freezed.dart b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart similarity index 84% rename from modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.freezed.dart rename to modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart index 393e0bc2..2ba641cb 100644 --- a/modules/auth/lib/src/features/link_phone/presentation/link_phone_view_state.freezed.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/state/link_phone_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$LinkPhoneViewState { - String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested; + String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested; bool get codeVerified; /// Create a copy of LinkPhoneViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $LinkPhoneViewStateCopyWith get copyWith => _$LinkPhoneViewS @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)&&(identical(other.codeVerified, codeVerified) || other.codeVerified == codeVerified)); } @override -int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested); +int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested,codeVerified); @override String toString() { - return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)'; + return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)'; } @@ -45,7 +45,7 @@ abstract mixin class $LinkPhoneViewStateCopyWith<$Res> { factory $LinkPhoneViewStateCopyWith(LinkPhoneViewState value, $Res Function(LinkPhoneViewState) _then) = _$LinkPhoneViewStateCopyWithImpl; @useResult $Res call({ - String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested + String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified }); @@ -62,13 +62,14 @@ class _$LinkPhoneViewStateCopyWithImpl<$Res> /// Create a copy of LinkPhoneViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,Object? codeVerified = null,}) { return _then(_self.copyWith( phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable +as bool,codeVerified: null == codeVerified ? _self.codeVerified : codeVerified // ignore: cast_nullable_to_non_nullable as bool, )); } @@ -154,10 +155,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,{required TResult orElse(),}) {final _that = this; +@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 _LinkPhoneViewState() when $default != null: -return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _: +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _: return orElse(); } @@ -175,10 +176,10 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified) $default,) {final _that = this; switch (_that) { case _LinkPhoneViewState(): -return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _: +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _: throw StateError('Unexpected subclass'); } @@ -195,10 +196,10 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified)? $default,) {final _that = this; switch (_that) { case _LinkPhoneViewState() when $default != null: -return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _: +return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested,_that.codeVerified);case _: return null; } @@ -210,7 +211,7 @@ return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoad class _LinkPhoneViewState implements LinkPhoneViewState { - const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false}); + const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false, this.codeVerified = false}); @override@JsonKey() final String phoneNumber; @@ -218,6 +219,7 @@ class _LinkPhoneViewState implements LinkPhoneViewState { @override@JsonKey() final String errorMessage; @override@JsonKey() final bool isLoading; @override@JsonKey() final bool codeRequested; +@override@JsonKey() final bool codeVerified; /// Create a copy of LinkPhoneViewState /// with the given fields replaced by the non-null parameter values. @@ -229,16 +231,16 @@ _$LinkPhoneViewStateCopyWith<_LinkPhoneViewState> get copyWith => __$LinkPhoneVi @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested)&&(identical(other.codeVerified, codeVerified) || other.codeVerified == codeVerified)); } @override -int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested); +int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested,codeVerified); @override String toString() { - return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)'; + return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested, codeVerified: $codeVerified)'; } @@ -249,7 +251,7 @@ abstract mixin class _$LinkPhoneViewStateCopyWith<$Res> implements $LinkPhoneVie factory _$LinkPhoneViewStateCopyWith(_LinkPhoneViewState value, $Res Function(_LinkPhoneViewState) _then) = __$LinkPhoneViewStateCopyWithImpl; @override @useResult $Res call({ - String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested + String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested, bool codeVerified }); @@ -266,13 +268,14 @@ class __$LinkPhoneViewStateCopyWithImpl<$Res> /// Create a copy of LinkPhoneViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,Object? codeVerified = null,}) { return _then(_LinkPhoneViewState( phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable +as bool,codeVerified: null == codeVerified ? _self.codeVerified : codeVerified // ignore: cast_nullable_to_non_nullable as bool, )); } diff --git a/modules/auth/lib/src/features/login/phone_code_builder.dart b/modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart similarity index 59% rename from modules/auth/lib/src/features/login/phone_code_builder.dart rename to modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart index e8a31e24..45e9cfae 100644 --- a/modules/auth/lib/src/features/login/phone_code_builder.dart +++ b/modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_builder.dart @@ -1,18 +1,18 @@ -import 'package:auth/src/features/login/presentation/phone_code_screen.dart'; +import 'package:auth/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:get_it/get_it.dart'; import 'package:navigation/navigation.dart'; -class PhoneCodeBuilder { - const PhoneCodeBuilder(); +class VerifyLinkPhoneCodeBuilder { + const VerifyLinkPhoneCodeBuilder(); Page buildPage(BuildContext context, GoRouterState state) { final NavigationContract navigationContract = GetIt.I(); return MaterialPage( key: state.pageKey, - child: PhoneCodeScreen(navigationContract: navigationContract), + child: VerifyLinkPhoneCodeScreen(navigationContract: navigationContract), ); } } diff --git a/modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart b/modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart new file mode 100644 index 00000000..44ea4c72 --- /dev/null +++ b/modules/auth/lib/src/features/link_phone/presentation/verify_code/verify_link_phone_code_screen.dart @@ -0,0 +1,118 @@ +import 'package:auth/src/features/link_phone/presentation/state/link_phone_view_model.dart'; +import 'package:auth/src/features/link_phone/presentation/widgets/link_phone_code_input.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:navigation/navigation.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class VerifyLinkPhoneCodeScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const VerifyLinkPhoneCodeScreen({ + super.key, + required this.navigationContract, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(linkPhoneViewModelProvider.notifier); + final viewState = ref.watch(linkPhoneViewModelProvider); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 48, + children: [ + Column( + children: [ + Text( + context.translate(I18n.connect), + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 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), + + LinkPhoneCodeInput( + length: 6, + onCodeChanged: viewModel.updateCode, + ), + + if (viewState.errorMessage.isNotEmpty) ...[ + const SizedBox(height: 8), + Text( + viewState.errorMessage, + textAlign: TextAlign.center, + style: const TextStyle( + color: Color.fromRGBO(239, 17, 17, 1), + fontSize: 12, + ), + ), + ], + ], + ), + Column( + children: [ + PrimaryButton( + onPressed: () async { + await viewModel.verifyCode(); + final updatedState = ref.read(linkPhoneViewModelProvider); + + if (updatedState.codeVerified) { + navigationContract.pushTo(AppRoutes.login); + } + }, + text: context.translate(I18n.enter), + color: theme.getColorFor(ThemeCode.buttonPrimary), + ), + 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/auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart b/modules/auth/lib/src/features/link_phone/presentation/widgets/link_phone_code_input.dart new file mode 100644 index 00000000..d54f41b2 --- /dev/null +++ b/modules/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 LinkPhoneCodeInput extends StatefulWidget { + const LinkPhoneCodeInput({ + super.key, + this.length = 6, + required this.onCodeChanged, + }); + + final int length; + final ValueChanged onCodeChanged; + + @override + State createState() => _LinkPhoneCodeInputState(); +} + +class _LinkPhoneCodeInputState 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/auth/lib/src/features/login/presentation/phone_code_screen.dart b/modules/auth/lib/src/features/login/presentation/phone_code_screen.dart deleted file mode 100644 index 5a8f4b71..00000000 --- a/modules/auth/lib/src/features/login/presentation/phone_code_screen.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:design_system/design_system.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:navigation/navigation.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -class PhoneCodeScreen extends ConsumerWidget { - final NavigationContract navigationContract; - - PhoneCodeScreen({super.key, required this.navigationContract}); - - final focusNodes = List.generate(6, (int i) { - return FocusNode(); - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.watch(themePortProvider); - - return Scaffold( - backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), - body: Container( - margin: EdgeInsets.all(30), - child: Expanded( - child: Center( - child: Column( - spacing: 48, - children: [ - Spacer(flex: 8), - Column( - spacing: 24, - children: [ - Text( - "Conéctate", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 30, - ), - ), - Text.rich( - TextSpan( - text: "Hemos enviado el código al ", - children: [ - TextSpan( - // text: widget.phone, - style: TextStyle(fontWeight: FontWeight.bold), - ), - ], - ), - ), - Text("Introduce el código aquí"), - Row( - spacing: 8, - children: List.generate(6, (int i) { - return Expanded( - child: TextField( - focusNode: focusNodes[i], - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: "0", - counterText: "", - border: OutlineInputBorder(), - ), - maxLength: 1, - onChanged: (String value) => { - value != "" - ? focusNodes[i + 1].requestFocus() - : focusNodes[i - 1].requestFocus(), - }, - ), - ); - }), - ), - ], - ), - Column( - spacing: 24, - children: [ - PrimaryButton( - onPressed: () => { - navigationContract.pushTo(AppRoutes.login), - }, - text: "Entrar", - color: theme.getColorFor(ThemeCode.buttonPrimary), - ), - Column( - spacing: 8, - children: [ - Text( - "¿No lo has recibido?", - style: TextStyle( - fontSize: 18, - letterSpacing: 0, - height: 1.5, - ), - ), - CustomTextButton( - onPressed: () => {}, - text: "Volver a intentarlo", - size: 18, - weight: FontWeight.w500, - ), - ], - ), - ], - ), - Spacer(flex: 10), - ], - ), - ), - ), - ), - ); - } -} diff --git a/packages/design_system/lib/src/dropdowns/country_prefix_picker.dart b/packages/design_system/lib/src/dropdowns/country_prefix_picker.dart index eaa2b0a3..7d5d3695 100644 --- a/packages/design_system/lib/src/dropdowns/country_prefix_picker.dart +++ b/packages/design_system/lib/src/dropdowns/country_prefix_picker.dart @@ -5,6 +5,7 @@ class CountryPrefixPicker extends StatelessWidget { const CountryPrefixPicker({ super.key, required this.onChanged, + required this.headerText, this.initialCountryCode = '+34', this.radius = 12, this.width = 90, @@ -15,7 +16,7 @@ class CountryPrefixPicker extends StatelessWidget { final ValueChanged onChanged; final String initialCountryCode; - + final String headerText; final double radius; final double width; final double height; @@ -28,6 +29,7 @@ class CountryPrefixPicker extends StatelessWidget { width: width, height: height, child: CountryCodePicker( + headerText: headerText, onChanged: onChanged, initialSelection: initialCountryCode, showFlag: false, diff --git a/packages/design_system/lib/src/inputs/textfields.dart b/packages/design_system/lib/src/inputs/textfields.dart index 581595fc..a665ff8d 100644 --- a/packages/design_system/lib/src/inputs/textfields.dart +++ b/packages/design_system/lib/src/inputs/textfields.dart @@ -49,6 +49,7 @@ class CustomTextFieldState extends State { ), ), TextFormField( + controller: widget.controller, keyboardType: widget.numeric ? TextInputType.number : TextInputType.text, diff --git a/packages/fonts/.dart_tool/extension_discovery/README.md b/packages/fonts/.dart_tool/extension_discovery/README.md new file mode 100644 index 00000000..9dc6757b --- /dev/null +++ b/packages/fonts/.dart_tool/extension_discovery/README.md @@ -0,0 +1,31 @@ +Extension Discovery Cache +========================= + +This folder is used by `package:extension_discovery` to cache lists of +packages that contains extensions for other packages. + +DO NOT USE THIS FOLDER +---------------------- + + * Do not read (or rely) the contents of this folder. + * Do write to this folder. + +If you're interested in the lists of extensions stored in this folder use the +API offered by package `extension_discovery` to get this information. + +If this package doesn't work for your use-case, then don't try to read the +contents of this folder. It may change, and will not remain stable. + +Use package `extension_discovery` +--------------------------------- + +If you want to access information from this folder. + +Feel free to delete this folder +------------------------------- + +Files in this folder act as a cache, and the cache is discarded if the files +are older than the modification time of `.dart_tool/package_config.json`. + +Hence, it should never be necessary to clear this cache manually, if you find a +need to do please file a bug. diff --git a/packages/fonts/.dart_tool/extension_discovery/vs_code.json b/packages/fonts/.dart_tool/extension_discovery/vs_code.json new file mode 100644 index 00000000..b7c85e78 --- /dev/null +++ b/packages/fonts/.dart_tool/extension_discovery/vs_code.json @@ -0,0 +1 @@ +{"version":2,"entries":[{"package":"fonts","rootUri":"../","packageUri":"lib/"}]} \ No newline at end of file diff --git a/packages/navigation/lib/app_routes.dart b/packages/navigation/lib/app_routes.dart index b441a68c..66904d7a 100644 --- a/packages/navigation/lib/app_routes.dart +++ b/packages/navigation/lib/app_routes.dart @@ -2,8 +2,8 @@ class AppRoutes { static const login = '/login'; static const signup = '/signup'; static const onboarding = '/onboarding'; - static const linkPhone = '/link_phone'; - static const phoneCode = '/phone_code'; + static const linkPhone = '/request_link_phone'; + static const phoneCode = '/verify_link_phone_code'; static const deviceSignup = '/device_signup'; static const recoverPassword = '/recover_password'; diff --git a/packages/sf_infrastructure/lib/configure_dependencies.dart b/packages/sf_infrastructure/lib/configure_dependencies.dart index 7f18f3cc..65497681 100644 --- a/packages/sf_infrastructure/lib/configure_dependencies.dart +++ b/packages/sf_infrastructure/lib/configure_dependencies.dart @@ -15,6 +15,7 @@ Future configureDependencies(EnvConfig env, {bool log = false}) async { getIt.registerLazySingleton( () => buildDioClient( baseUrl: env.apiBaseUrl, + origin: env.apiOrigin, // apiKey: env.apiKey, log: log, ), diff --git a/packages/sf_infrastructure/lib/src/env/env_contract.dart b/packages/sf_infrastructure/lib/src/env/env_contract.dart index a39a2c26..566b6fc7 100644 --- a/packages/sf_infrastructure/lib/src/env/env_contract.dart +++ b/packages/sf_infrastructure/lib/src/env/env_contract.dart @@ -1,4 +1,5 @@ abstract class EnvConfig { String get apiBaseUrl; + String get apiOrigin; // String get apiKey; } diff --git a/packages/sf_infrastructure/lib/src/network/dio_client.dart b/packages/sf_infrastructure/lib/src/network/dio_client.dart index c56f8963..125ba431 100644 --- a/packages/sf_infrastructure/lib/src/network/dio_client.dart +++ b/packages/sf_infrastructure/lib/src/network/dio_client.dart @@ -2,6 +2,7 @@ import 'package:dio/dio.dart'; Dio buildDioClient({ required String baseUrl, + required String origin, // required String apiKey, bool log = false, }) { @@ -15,6 +16,7 @@ Dio buildDioClient({ // if (apiKey.isNotEmpty) 'x-api-key': apiKey, 'accept': 'application/json', 'content-type': 'application/json', + 'origin': origin, }, ), ); diff --git a/packages/sf_localizations/assets/l10n/de.json b/packages/sf_localizations/assets/l10n/de.json index 932a19c9..447bc8b7 100644 --- a/packages/sf_localizations/assets/l10n/de.json +++ b/packages/sf_localizations/assets/l10n/de.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "Wir freuen uns sehr, dass du hier bist!", "linkPhoneSubtitle": "Um dich sicher anzumelden, senden wir dir einen Code an deine Telefonnummer", "mobilePhone": "Mobiltelefon", - "phoneNumber": "Telefonnummer" + "phoneNumber": "Telefonnummer", + "selectYourCountry": "Wähle dein Land", + "errorMessagePhoneIsEmpty": "Die Telefonnummer darf nicht leer sein", + "connect": "Verbinden", + "verificationCodeSentTo": "Wir haben den Code an ", + "enterCodeHere": "Gib den Code hier ein", + "enter": "Weiter", + "didNotReceiveIt": "Hast du es nicht erhalten?", + "tryAgain": "Erneut versuchen" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index 74e26676..15d42b73 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "We're really happy to have you here!", "linkPhoneSubtitle": "To sign in securely, we'll send a code to your phone number", "mobilePhone": "Mobile phone", - "phoneNumber": "Phone number" + "phoneNumber": "Phone number", + "selectYourCountry": "Select your country", + "errorMessagePhoneIsEmpty": "Phone number cannot be empty", + "connect": "Connect", + "verificationCodeSentTo": "We have sent the code to ", + "enterCodeHere": "Enter the code here", + "enter": "Enter", + "didNotReceiveIt": "Didn't receive it?", + "tryAgain": "Try again" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/es.json b/packages/sf_localizations/assets/l10n/es.json index 174f4f9a..f9acdf5a 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "¡Nos alegra mucho tenerte por aquí!", "linkPhoneSubtitle": "Para poder entrar de forma segura, te vamos a enviar un código al teléfono", "mobilePhone": "Teléfono móvil", - "phoneNumber": "Teléfono" + "phoneNumber": "Teléfono", + "selectYourCountry": "Selecciona tu país", + "errorMessagePhoneIsEmpty": "El número de teléfono no puede estar vacío", + "connect": "Conéctate", + "verificationCodeSentTo": "Hemos enviado el código al ", + "enterCodeHere": "Introduce el código aquí", + "enter": "enter", + "didNotReceiveIt": "¿No lo has recibido?", + "tryAgain": "Volver a intentarlo" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/fr.json b/packages/sf_localizations/assets/l10n/fr.json index 5cf274d5..557f92e8 100644 --- a/packages/sf_localizations/assets/l10n/fr.json +++ b/packages/sf_localizations/assets/l10n/fr.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "Nous sommes ravis de te compter parmi nous !", "linkPhoneSubtitle": "Pour te connecter en toute sécurité, nous allons envoyer un code sur ton téléphone", "mobilePhone": "Téléphone portable", - "phoneNumber": "Numéro de téléphone" + "phoneNumber": "Numéro de téléphone", + "selectYourCountry": "Sélectionne ton pays", + "errorMessagePhoneIsEmpty": "Le numéro de téléphone ne peut pas être vide", + "connect": "Connecter", + "verificationCodeSentTo": "Nous avons envoyé le code à ", + "enterCodeHere": "Saisissez le code ici", + "enter": "Entrer", + "didNotReceiveIt": "Tu ne l'as pas reçu ?", + "tryAgain": "Réessayer" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/it.json b/packages/sf_localizations/assets/l10n/it.json index f32a8895..b55a0679 100644 --- a/packages/sf_localizations/assets/l10n/it.json +++ b/packages/sf_localizations/assets/l10n/it.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "Siamo molto felici di averti qui!", "linkPhoneSubtitle": "Per accedere in modo sicuro, ti invieremo un codice al tuo telefono", "mobilePhone": "Telefono cellulare", - "phoneNumber": "Numero di telefono" + "phoneNumber": "Numero di telefono", + "selectYourCountry": "Seleziona il tuo paese", + "errorMessagePhoneIsEmpty": "Il numero di telefono non può essere vuoto", + "connect": "Collegare", + "verificationCodeSentTo": "Abbiamo inviato il codice a ", + "enterCodeHere": "Inserisci il codice qui", + "enter": "Entra", + "didNotReceiveIt": "Non lo hai ricevuto?", + "tryAgain": "Riprova" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/pt.json b/packages/sf_localizations/assets/l10n/pt.json index bcd5436b..2fff2b01 100644 --- a/packages/sf_localizations/assets/l10n/pt.json +++ b/packages/sf_localizations/assets/l10n/pt.json @@ -12,5 +12,13 @@ "linkPhoneTitle": "Ficamos muito felizes em ter você aqui!", "linkPhoneSubtitle": "Para entrar com segurança, vamos enviar um código para o seu telefone", "mobilePhone": "Telefone celular", - "phoneNumber": "Número de telefone" + "phoneNumber": "Número de telefone", + "selectYourCountry": "Selecione seu país", + "errorMessagePhoneIsEmpty": "O número de telefone não pode estar vazio", + "connect": "Conectar", + "verificationCodeSentTo": "Enviamos o código para ", + "enterCodeHere": "Insira o código aqui", + "enter": "Entrar", + "didNotReceiveIt": "Você não recebeu?", + "tryAgain": "Tentar novamente" } \ No newline at end of file diff --git a/packages/sf_localizations/lib/src/generated/i18n.dart b/packages/sf_localizations/lib/src/generated/i18n.dart index 3c7d3d1a..84ec6a23 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -17,4 +17,12 @@ class I18n { static const String linkPhoneSubtitle = 'linkPhoneSubtitle'; static const String mobilePhone = 'mobilePhone'; static const String phoneNumber = 'phoneNumber'; + static const String selectYourCountry = 'selectYourCountry'; + static const String errorMessagePhoneIsEmpty = 'errorMessagePhoneIsEmpty'; + static const String connect = "connect"; + static const String verificationCodeSentTo = "verificationCodeSentTo"; + static const String enterCodeHere = "enterCodeHere"; + static const String enter = "enter"; + static const String didNotReceiveIt = "didNotReceiveIt"; + static const String tryAgain = "tryAgain"; }