Compare commits
12 Commits
auth-login
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 577a3709d3 | |||
| 69230c0dde | |||
| d7706bf639 | |||
| 2c56d9fcb2 | |||
| efbdae81d4 | |||
| 0d8cb4bd37 | |||
| 6a9d68e945 | |||
| ea6a9741ee | |||
| f6e07192dc | |||
| ce062ec6e8 | |||
| 2e3681d36d | |||
| 098217f47a |
@@ -9,6 +9,7 @@ import 'package:sf_app_platform/navigation/app_router.dart';
|
||||
import 'package:navigation/navigation_module.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
@@ -26,6 +27,8 @@ class PlatformApp extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
SizeUtils.init(context: context);
|
||||
|
||||
return MaterialApp.router(
|
||||
title: 'SaveFamily',
|
||||
theme: ThemeData(
|
||||
|
||||
@@ -46,7 +46,7 @@ void configureAppRouter() {
|
||||
GoRoute(
|
||||
path: AppRoutes.recoverPassword,
|
||||
name: 'recover_password',
|
||||
pageBuilder: RecoverPasswordBuilder().buildPage,
|
||||
pageBuilder: RequestRecoveryBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: AppRoutes.deviceSignup,
|
||||
|
||||
@@ -59,6 +59,8 @@ dependencies:
|
||||
path: ../../packages/fonts
|
||||
sf_infrastructure:
|
||||
path: ../../packages/sf_infrastructure
|
||||
utils:
|
||||
path: ../../packages/utils
|
||||
|
||||
#dependencies go here
|
||||
cupertino_icons: ^1.0.8
|
||||
|
||||
@@ -3,6 +3,6 @@ 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/recover_password_builder.dart';
|
||||
export 'src/features/recover_password/presentation/request_recovery/request_recovery_builder.dart';
|
||||
export 'src/features/device_sign_up/device_signup_builder.dart';
|
||||
export 'src/features/sign_up/sign_up_builder.dart';
|
||||
|
||||
@@ -9,7 +9,6 @@ abstract class AuthRemoteDatasource {
|
||||
Future<String> login({required String email, required String password});
|
||||
|
||||
Future<void> twoFALogin({required String token, required String code});
|
||||
|
||||
Future<String> signUp({required SignUpRequestEntity request});
|
||||
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token});
|
||||
@@ -17,4 +16,7 @@ abstract class AuthRemoteDatasource {
|
||||
required String token,
|
||||
required String code,
|
||||
});
|
||||
Future<String> requestPasswordReset({String? phone, String? email});
|
||||
|
||||
Future<void> recoverPassword({required newPassword, required token});
|
||||
}
|
||||
|
||||
@@ -167,6 +167,48 @@ class AuthRemoteDatasourceImpl implements AuthRemoteDatasource {
|
||||
throw _mapDioError(error, defaultMessage: 'Error in twoFaCodeSignUp');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestPasswordReset({
|
||||
String? phone,
|
||||
String? email
|
||||
}) async {
|
||||
try {
|
||||
if (phone == null && email == null) {
|
||||
throw FormatException("No phone or email address given");
|
||||
}
|
||||
|
||||
// late final Map<String, dynamic> body;
|
||||
if (email != null) {
|
||||
// body = {'email': email};
|
||||
return 'ec14b7e7-58dd-4a59-9f41-0da86eaabf14';
|
||||
} else {
|
||||
// body = {'phone': phone!};
|
||||
return 'ec14b7e7-58dd-4a59-9f41-0da86eaabf14';
|
||||
// throw Exception("reset by phone is not currently implemented");
|
||||
}
|
||||
/*final response = await _repository.put<Map<String, dynamic>>(
|
||||
'/auth/reset-password',
|
||||
body: body,
|
||||
);
|
||||
final token = response.data!['token'];
|
||||
return token;*/
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error to request password reset');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({required newPassword, required token}) async {
|
||||
try {
|
||||
await _repository.put<void>(
|
||||
'/auth/recovery-password',
|
||||
body: <String, dynamic>{'newPassword': newPassword, 'token': token},
|
||||
);
|
||||
} on DioException catch (error) {
|
||||
throw _mapDioError(error, defaultMessage: 'Error to request password recovery');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exception _mapDioError(DioException error, {required String defaultMessage}) {
|
||||
|
||||
@@ -45,4 +45,17 @@ class AuthRepositoryImpl implements AuthRepository {
|
||||
}) {
|
||||
return _remote.verifyTwoFACodeSignUp(token: token, code: code);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestPasswordReset({String? phone, String? email}) {
|
||||
return _remote.requestPasswordReset(phone: phone, email: email);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({
|
||||
required String newPassword,
|
||||
required String token,
|
||||
}) {
|
||||
return _remote.recoverPassword(newPassword: newPassword, token: token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,15 @@ abstract class AuthRepository {
|
||||
Future<void> verifyPhoneCode({required String phone, required String code});
|
||||
|
||||
Future<String> login({required String email, required String password});
|
||||
|
||||
Future<void> twoFactor({required String token, required String code});
|
||||
|
||||
Future<String> requestPasswordReset({String phone, String email});
|
||||
|
||||
Future<void> recoverPassword({
|
||||
required String newPassword,
|
||||
required String token,
|
||||
});
|
||||
|
||||
Future<String> signUp({required SignUpRequestEntity request});
|
||||
|
||||
Future<TwoFASecretEntity> generateTwoFASignUp({required String token});
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
abstract class RecoverPasswordUseCase {
|
||||
Future<String> requestEmail({required String email});
|
||||
|
||||
Future<String> requestSms({required String phone});
|
||||
|
||||
Future<void> recoverPassword({required String newPassword, required String token});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:auth/src/core/domain/repositories/auth_repository.dart';
|
||||
import 'package:auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart';
|
||||
|
||||
class RecoverPasswordUseCaseImpl implements RecoverPasswordUseCase {
|
||||
RecoverPasswordUseCaseImpl(this._repository);
|
||||
|
||||
final AuthRepository _repository;
|
||||
|
||||
@override
|
||||
Future<String> requestEmail({required String email}) async {
|
||||
return await _repository.requestPasswordReset(email: email);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> requestSms({required String phone}) async {
|
||||
return await _repository.requestPasswordReset(phone: phone);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> recoverPassword({required String newPassword, required String token}) async {
|
||||
await _repository.recoverPassword(newPassword: newPassword, token: token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password/new_password_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class NewPasswordBuilder {
|
||||
const NewPasswordBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: NewPasswordScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/state/recover_password_view_model.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class NewPasswordScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const NewPasswordScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordTitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 30, xl: 26),
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 42, big: 32)),
|
||||
CustomTextField(
|
||||
showPassword: viewState.passwordVisible,
|
||||
label: context.translate(I18n.newPassword),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
hint: '********',
|
||||
controller: viewModel.passwordController,
|
||||
// onVisibilityChanged: viewModel.togglePasswordVisible,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
CustomTextField(
|
||||
showPassword: viewState.passwordVisible,
|
||||
label: context.translate(I18n.repeatPassword),
|
||||
labelSize: SizeUtils.getByScreen(small: 14, big: 14, xl: 12),
|
||||
hint: '********',
|
||||
controller: viewModel.repeatedPasswordController,
|
||||
// onVisibilityChanged: viewModel.togglePasswordVisible,
|
||||
// color: viewState.equalPasswords ? const Color(0xFF4B4B4B) : const Color.fromRGBO(239, 17, 17, 1),
|
||||
),
|
||||
if (!viewState.equalPasswords) ...[
|
||||
SizedBox(height: 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(
|
||||
recoverPasswordViewModelProvider,
|
||||
);
|
||||
if (updatedState.passwordChanged) {
|
||||
navigationContract.goTo(AppRoutes.dashboardHome);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.accept),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class NewPasswordScreen extends ConsumerStatefulWidget {
|
||||
const NewPasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<NewPasswordScreen> createState() => NewPasswordScreenState();
|
||||
}
|
||||
|
||||
class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
|
||||
bool passwordVisible = false;
|
||||
bool equalPasswords = false;
|
||||
String password = '';
|
||||
|
||||
Map<String, bool> securityChecks = {
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
passwordVisible = false;
|
||||
equalPasswords = false;
|
||||
password = '';
|
||||
securityChecks = {
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: const EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
const Text(
|
||||
"Recuperar contraseña",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 30,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Nueva contraseña",
|
||||
hint: "********",
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
password = value;
|
||||
securityChecks = checkSecurity(value);
|
||||
}),
|
||||
},
|
||||
),
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Repetir contraseña",
|
||||
hint: "********",
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
equalPasswords = password == value;
|
||||
}),
|
||||
},
|
||||
),
|
||||
Column(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
securityChecks["min"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
"Al menos 8 caracteres",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
securityChecks["capital"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
"Una mayúscula",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
securityChecks["number"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
"Un número",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(
|
||||
securityChecks["special"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
"Un carácter especial",
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: const Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
],
|
||||
onChanged: (value) => {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () => {
|
||||
navigationContract.goTo(AppRoutes.dashboardHome),
|
||||
},
|
||||
text: "Aceptar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: Extraer de la vista
|
||||
Map<String, bool> checkSecurity(String value) {
|
||||
return {
|
||||
'min': value.length >= 8,
|
||||
'capital': RegExp(r'[A-Z]').hasMatch(value),
|
||||
'number': RegExp(r'[0-9]').hasMatch(value),
|
||||
'special': RegExp(r'[^A-Za-z0-9]').hasMatch(value),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:auth/src/core/providers/auth_repository_provider.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../domain/use_cases/recover_password_use_case.dart';
|
||||
import '../../domain/use_cases/recover_password_use_case_impl.dart';
|
||||
|
||||
final recoverPasswordUseCaseProvider = Provider.autoDispose<RecoverPasswordUseCase>((ref) {
|
||||
final authRepository = ref.read(authRepositoryProvider);
|
||||
return RecoverPasswordUseCaseImpl(authRepository);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class RequestRecoveryBuilder {
|
||||
const RequestRecoveryBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RequestRecoveryScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/sent/sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
import '../state/recover_password_view_model.dart';
|
||||
|
||||
class RequestRecoveryScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const RequestRecoveryScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.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),
|
||||
initialCountryCode: viewState.dialCode,
|
||||
onChanged: (country) {
|
||||
viewModel.updateDialCode(
|
||||
country.dialCode ?? viewState.dialCode,
|
||||
);
|
||||
},
|
||||
width: 80,
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6)),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
keyboardType: TextInputType.number,
|
||||
controller: viewModel.phoneNumberController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 40, big: 40, xl: 28)),
|
||||
if (viewState.errorMessage.isNotEmpty) ...[
|
||||
Text(
|
||||
context.translate(viewState.errorMessage),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40),
|
||||
],
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
text: context.translate(I18n.back),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 20, big: 20, xl: 10)),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () async {
|
||||
await viewModel.requestRecovery();
|
||||
final updatedState = ref.read(recoverPasswordViewModelProvider);
|
||||
if (updatedState.recoveryRequested) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SentScreen(navigationContract: navigationContract),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.send),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class RestorePasswordScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const RestorePasswordScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Text(
|
||||
"Recuperar contaseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text(
|
||||
"Introduce tu email para enviarte un enlace de recuperación",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 40,
|
||||
children: [
|
||||
CustomTextField(
|
||||
label: "Correo electrónico",
|
||||
hint: "Correo electrónico",
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
],
|
||||
onChanged: (value) => {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
text: "Volver",
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SentScreen(format: "email"),
|
||||
),
|
||||
),
|
||||
},
|
||||
text: "Enviar",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/sent/sent_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class SentBuilder {
|
||||
const SentBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: SentScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password/new_password_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
import '../state/recover_password_view_model.dart';
|
||||
|
||||
class SentScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const SentScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.read(recoverPasswordViewModelProvider.notifier);
|
||||
final viewState = ref.watch(recoverPasswordViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.recoverPasswordTitle),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: SizeUtils.getByScreen(small: 30, big: 30, xl: 26),
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6)),
|
||||
Text(
|
||||
viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.emailSent)
|
||||
: context.translate(I18n.smsSent),
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 18, xl: 15), fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40)),
|
||||
Text(
|
||||
viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.checkEmail1)
|
||||
: context.translate(I18n.checkSms1),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 17, big: 17, xl: 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();
|
||||
} else {
|
||||
viewModel.requestSms();
|
||||
}
|
||||
},
|
||||
text: viewState.recoveryFormat == "email"
|
||||
? context.translate(I18n.resendEmail)
|
||||
: context.translate(I18n.resendSms),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => NewPasswordScreen(navigationContract: navigationContract)),
|
||||
),
|
||||
text: context.translate(I18n.continueKey),
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
size: SizeUtils.getByScreen(small: 16, big: 16, xl: 14),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/new_password_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class SentScreen extends ConsumerWidget {
|
||||
final String format;
|
||||
|
||||
const SentScreen({super.key, required this.format});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 30,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Text(
|
||||
format == "email"
|
||||
? "Correo enviado correctamente"
|
||||
: "SMS enviado correctamente",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
format == "email"
|
||||
? "Revisa tu email y haz clic en el enlace para crear una nueva contraseña."
|
||||
: "Revisa tu móvil y sigue las instrucciones para crear una nueva contraseña.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0),
|
||||
),
|
||||
Text(
|
||||
format == "email"
|
||||
? "Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"."
|
||||
: "Si no recibes el SMS en unos minutos, asegúrate de tener cobertura o pulsa \"Reenviar SMS \".",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
onPressed: () => {},
|
||||
text: format == "email"
|
||||
? "Reenviar correo"
|
||||
: "Reenviar SMS",
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => NewPasswordScreen()),
|
||||
),
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
import 'package:auth/src/features/recover_password/domain/use_cases/recover_password_use_case.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/state/recover_password_view_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../providers/recover_password_provider.dart';
|
||||
|
||||
final recoverPasswordViewModelProvider =
|
||||
NotifierProvider.autoDispose<RecoverPasswordViewModel, RecoverPasswordViewState>(
|
||||
RecoverPasswordViewModel.new,
|
||||
);
|
||||
|
||||
class RecoverPasswordViewModel extends Notifier<RecoverPasswordViewState> {
|
||||
late final RecoverPasswordUseCase _recoverPasswordUseCase;
|
||||
late final TextEditingController phoneNumberController;
|
||||
late final TextEditingController emailController;
|
||||
late final TextEditingController passwordController;
|
||||
late final TextEditingController repeatedPasswordController;
|
||||
late final TextEditingController newPhoneNumberController;
|
||||
|
||||
@override
|
||||
RecoverPasswordViewState build() {
|
||||
_recoverPasswordUseCase = ref.read(recoverPasswordUseCaseProvider);
|
||||
|
||||
phoneNumberController = TextEditingController();
|
||||
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||
|
||||
emailController = TextEditingController();
|
||||
emailController.addListener(_onEmailChanged);
|
||||
|
||||
passwordController = TextEditingController();
|
||||
passwordController.addListener(_onPasswordChanged);
|
||||
|
||||
repeatedPasswordController = TextEditingController();
|
||||
repeatedPasswordController.addListener(_onRepeatedPasswordChanged);
|
||||
|
||||
newPhoneNumberController = TextEditingController();
|
||||
newPhoneNumberController.addListener(_onNewPhoneNumberChanged);
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return const RecoverPasswordViewState();
|
||||
}
|
||||
|
||||
void _onPhoneNumberChanged() {
|
||||
final String raw = phoneNumberController.text;
|
||||
state = state.copyWith(
|
||||
phoneNumber: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onNewPhoneNumberChanged() {
|
||||
final String raw = newPhoneNumberController.text;
|
||||
state = state.copyWith(
|
||||
newPhoneNumber: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onEmailChanged() {
|
||||
final String raw = emailController.text;
|
||||
state = state.copyWith(
|
||||
email: raw,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
}
|
||||
|
||||
void _onPasswordChanged() {
|
||||
final String raw = passwordController.text;
|
||||
final bool equalPasswords = raw == repeatedPasswordController.text;
|
||||
|
||||
final bool minCheck = raw.length >= 8;
|
||||
final bool capitalCheck = RegExp(r'[A-Z]').hasMatch(raw);
|
||||
final bool numberCheck = RegExp(r'[0-9]').hasMatch(raw);
|
||||
final bool specialCheck = RegExp(r'[^A-Za-z0-9]').hasMatch(raw);
|
||||
|
||||
final Map<String, bool> security = {
|
||||
'min': minCheck,
|
||||
'capital': capitalCheck,
|
||||
'number': numberCheck,
|
||||
'special': specialCheck,
|
||||
};
|
||||
|
||||
state = state.copyWith(
|
||||
password: raw,
|
||||
errorMessage: '',
|
||||
equalPasswords: equalPasswords,
|
||||
securityChecks: security,
|
||||
);
|
||||
}
|
||||
|
||||
void _onRepeatedPasswordChanged() {
|
||||
final String raw = repeatedPasswordController.text;
|
||||
final bool equalPasswords = raw == passwordController.text;
|
||||
state = state.copyWith(
|
||||
repeatedPassword: raw,
|
||||
errorMessage: '',
|
||||
equalPasswords: equalPasswords,
|
||||
);
|
||||
}
|
||||
|
||||
void updateDialCode(String dialCode) {
|
||||
state = state.copyWith(
|
||||
dialCode: dialCode,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void updateNewDialCode(String dialCode) {
|
||||
state = state.copyWith(
|
||||
newDialCode: dialCode,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
void togglePasswordVisible(){
|
||||
state = state.copyWith(
|
||||
passwordVisible: !state.passwordVisible,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> requestRecovery() async {
|
||||
final trimmedNumber = state.phoneNumber.trim();
|
||||
final email = state.email.trim();
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
recoveryRequested: false,
|
||||
);
|
||||
|
||||
if (email.isNotEmpty) {
|
||||
await requestEmail();
|
||||
} else if (trimmedNumber.isNotEmpty) {
|
||||
await requestSms();
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'errorMessageContactIsEmpty',
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestEmail() async {
|
||||
final email = state.email.trim();
|
||||
|
||||
try {
|
||||
final String token = await _recoverPasswordUseCase.requestEmail(email: email);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
recoveryRequested: true,
|
||||
token: token,
|
||||
recoveryFormat: 'email',
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
recoveryRequested: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestSms() async {
|
||||
final trimmedNumber = state.phoneNumber.trim();
|
||||
|
||||
final fullPhone = '${state.dialCode}$trimmedNumber';
|
||||
|
||||
try {
|
||||
final String token = await _recoverPasswordUseCase.requestSms(phone: fullPhone);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
recoveryRequested: true,
|
||||
token: token,
|
||||
recoveryFormat: 'sms'
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
recoveryRequested: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> recoverPassword() async {
|
||||
//final String fullPhone = state.newDialCode + state.newPhoneNumber;
|
||||
final String password = state.password;
|
||||
|
||||
if (!state.equalPasswords) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessageUnequalPasswords',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['min']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordTooShort',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['capital']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoCapitals',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['number']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoNumbers',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.securityChecks['special']!) {
|
||||
state = state.copyWith(
|
||||
errorMessage: 'errorMessagePasswordNoSpecialChars',
|
||||
passwordChanged: false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
passwordChanged: false,
|
||||
);
|
||||
try {
|
||||
await _recoverPasswordUseCase.recoverPassword(
|
||||
newPassword: password, token: state.token);
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
passwordChanged: true,
|
||||
);
|
||||
} catch (error) {
|
||||
state = state.copyWith(
|
||||
errorMessage: error.toString(),
|
||||
isLoading: false,
|
||||
passwordChanged: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
phoneNumberController.removeListener(_onPhoneNumberChanged);
|
||||
phoneNumberController.dispose();
|
||||
emailController.removeListener(_onPhoneNumberChanged);
|
||||
emailController.dispose();
|
||||
passwordController.removeListener(_onPasswordChanged);
|
||||
passwordController.dispose();
|
||||
repeatedPasswordController.removeListener(_onRepeatedPasswordChanged);
|
||||
repeatedPasswordController.dispose();
|
||||
newPhoneNumberController.removeListener(_onNewPhoneNumberChanged);
|
||||
newPhoneNumberController.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recover_password_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class RecoverPasswordViewState with _$RecoverPasswordViewState {
|
||||
const factory RecoverPasswordViewState({
|
||||
@Default('') String phoneNumber,
|
||||
@Default('+34') String dialCode,
|
||||
@Default('') String email,
|
||||
@Default('') String errorMessage,
|
||||
@Default('') String recoveryFormat,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool recoveryRequested,
|
||||
@Default(false) bool passwordChanged,
|
||||
@Default('') String token,
|
||||
@Default('') String password,
|
||||
@Default('') String repeatedPassword,
|
||||
@Default(false) bool passwordVisible,
|
||||
@Default(true) bool equalPasswords,
|
||||
@Default('+34') String newDialCode,
|
||||
@Default('') String newPhoneNumber,
|
||||
@Default({
|
||||
'min': false,
|
||||
'capital': false,
|
||||
'number': false,
|
||||
'special': false,
|
||||
}) Map<String, bool> securityChecks,
|
||||
}) = _RecoverPasswordViewState;
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'recover_password_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$RecoverPasswordViewState {
|
||||
|
||||
String get phoneNumber; String get dialCode; String get email; String get errorMessage; String get recoveryFormat; bool get isLoading; bool get recoveryRequested; bool get passwordChanged; String get token; String get password; String get repeatedPassword; bool get passwordVisible; bool get equalPasswords; String get newDialCode; String get newPhoneNumber; Map<String, bool> get securityChecks;
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$RecoverPasswordViewStateCopyWith<RecoverPasswordViewState> get copyWith => _$RecoverPasswordViewStateCopyWithImpl<RecoverPasswordViewState>(this as RecoverPasswordViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is RecoverPasswordViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.email, email) || other.email == email)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.recoveryFormat, recoveryFormat) || other.recoveryFormat == recoveryFormat)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.recoveryRequested, recoveryRequested) || other.recoveryRequested == recoveryRequested)&&(identical(other.passwordChanged, passwordChanged) || other.passwordChanged == passwordChanged)&&(identical(other.token, token) || other.token == token)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatedPassword, repeatedPassword) || other.repeatedPassword == repeatedPassword)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.equalPasswords, equalPasswords) || other.equalPasswords == equalPasswords)&&(identical(other.newDialCode, newDialCode) || other.newDialCode == newDialCode)&&(identical(other.newPhoneNumber, newPhoneNumber) || other.newPhoneNumber == newPhoneNumber)&&const DeepCollectionEquality().equals(other.securityChecks, securityChecks));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,email,errorMessage,recoveryFormat,isLoading,recoveryRequested,passwordChanged,token,password,repeatedPassword,passwordVisible,equalPasswords,newDialCode,newPhoneNumber,const DeepCollectionEquality().hash(securityChecks));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecoverPasswordViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, email: $email, errorMessage: $errorMessage, recoveryFormat: $recoveryFormat, isLoading: $isLoading, recoveryRequested: $recoveryRequested, passwordChanged: $passwordChanged, token: $token, password: $password, repeatedPassword: $repeatedPassword, passwordVisible: $passwordVisible, equalPasswords: $equalPasswords, newDialCode: $newDialCode, newPhoneNumber: $newPhoneNumber, securityChecks: $securityChecks)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
factory $RecoverPasswordViewStateCopyWith(RecoverPasswordViewState value, $Res Function(RecoverPasswordViewState) _then) = _$RecoverPasswordViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$RecoverPasswordViewStateCopyWithImpl<$Res>
|
||||
implements $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
_$RecoverPasswordViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final RecoverPasswordViewState _self;
|
||||
final $Res Function(RecoverPasswordViewState) _then;
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? email = null,Object? errorMessage = null,Object? recoveryFormat = null,Object? isLoading = null,Object? recoveryRequested = null,Object? passwordChanged = null,Object? token = null,Object? password = null,Object? repeatedPassword = null,Object? passwordVisible = null,Object? equalPasswords = null,Object? newDialCode = null,Object? newPhoneNumber = null,Object? securityChecks = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,recoveryFormat: null == recoveryFormat ? _self.recoveryFormat : recoveryFormat // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,recoveryRequested: null == recoveryRequested ? _self.recoveryRequested : recoveryRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,passwordChanged: null == passwordChanged ? _self.passwordChanged : passwordChanged // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatedPassword: null == repeatedPassword ? _self.repeatedPassword : repeatedPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,equalPasswords: null == equalPasswords ? _self.equalPasswords : equalPasswords // ignore: cast_nullable_to_non_nullable
|
||||
as bool,newDialCode: null == newDialCode ? _self.newDialCode : newDialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPhoneNumber: null == newPhoneNumber ? _self.newPhoneNumber : newPhoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,securityChecks: null == securityChecks ? _self.securityChecks : securityChecks // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, bool>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [RecoverPasswordViewState].
|
||||
extension RecoverPasswordViewStatePatterns on RecoverPasswordViewState {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _RecoverPasswordViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _RecoverPasswordViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _RecoverPasswordViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState():
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RecoverPasswordViewState() when $default != null:
|
||||
return $default(_that.phoneNumber,_that.dialCode,_that.email,_that.errorMessage,_that.recoveryFormat,_that.isLoading,_that.recoveryRequested,_that.passwordChanged,_that.token,_that.password,_that.repeatedPassword,_that.passwordVisible,_that.equalPasswords,_that.newDialCode,_that.newPhoneNumber,_that.securityChecks);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _RecoverPasswordViewState implements RecoverPasswordViewState {
|
||||
const _RecoverPasswordViewState({this.phoneNumber = '', this.dialCode = '+34', this.email = '', this.errorMessage = '', this.recoveryFormat = '', this.isLoading = false, this.recoveryRequested = false, this.passwordChanged = false, this.token = '', this.password = '', this.repeatedPassword = '', this.passwordVisible = false, this.equalPasswords = true, this.newDialCode = '+34', this.newPhoneNumber = '', final Map<String, bool> securityChecks = const {'min' : false, 'capital' : false, 'number' : false, 'special' : false}}): _securityChecks = securityChecks;
|
||||
|
||||
|
||||
@override@JsonKey() final String phoneNumber;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override@JsonKey() final String email;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final String recoveryFormat;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool recoveryRequested;
|
||||
@override@JsonKey() final bool passwordChanged;
|
||||
@override@JsonKey() final String token;
|
||||
@override@JsonKey() final String password;
|
||||
@override@JsonKey() final String repeatedPassword;
|
||||
@override@JsonKey() final bool passwordVisible;
|
||||
@override@JsonKey() final bool equalPasswords;
|
||||
@override@JsonKey() final String newDialCode;
|
||||
@override@JsonKey() final String newPhoneNumber;
|
||||
final Map<String, bool> _securityChecks;
|
||||
@override@JsonKey() Map<String, bool> get securityChecks {
|
||||
if (_securityChecks is EqualUnmodifiableMapView) return _securityChecks;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_securityChecks);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$RecoverPasswordViewStateCopyWith<_RecoverPasswordViewState> get copyWith => __$RecoverPasswordViewStateCopyWithImpl<_RecoverPasswordViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RecoverPasswordViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.email, email) || other.email == email)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.recoveryFormat, recoveryFormat) || other.recoveryFormat == recoveryFormat)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.recoveryRequested, recoveryRequested) || other.recoveryRequested == recoveryRequested)&&(identical(other.passwordChanged, passwordChanged) || other.passwordChanged == passwordChanged)&&(identical(other.token, token) || other.token == token)&&(identical(other.password, password) || other.password == password)&&(identical(other.repeatedPassword, repeatedPassword) || other.repeatedPassword == repeatedPassword)&&(identical(other.passwordVisible, passwordVisible) || other.passwordVisible == passwordVisible)&&(identical(other.equalPasswords, equalPasswords) || other.equalPasswords == equalPasswords)&&(identical(other.newDialCode, newDialCode) || other.newDialCode == newDialCode)&&(identical(other.newPhoneNumber, newPhoneNumber) || other.newPhoneNumber == newPhoneNumber)&&const DeepCollectionEquality().equals(other._securityChecks, _securityChecks));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,email,errorMessage,recoveryFormat,isLoading,recoveryRequested,passwordChanged,token,password,repeatedPassword,passwordVisible,equalPasswords,newDialCode,newPhoneNumber,const DeepCollectionEquality().hash(_securityChecks));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecoverPasswordViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, email: $email, errorMessage: $errorMessage, recoveryFormat: $recoveryFormat, isLoading: $isLoading, recoveryRequested: $recoveryRequested, passwordChanged: $passwordChanged, token: $token, password: $password, repeatedPassword: $repeatedPassword, passwordVisible: $passwordVisible, equalPasswords: $equalPasswords, newDialCode: $newDialCode, newPhoneNumber: $newPhoneNumber, securityChecks: $securityChecks)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$RecoverPasswordViewStateCopyWith<$Res> implements $RecoverPasswordViewStateCopyWith<$Res> {
|
||||
factory _$RecoverPasswordViewStateCopyWith(_RecoverPasswordViewState value, $Res Function(_RecoverPasswordViewState) _then) = __$RecoverPasswordViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String phoneNumber, String dialCode, String email, String errorMessage, String recoveryFormat, bool isLoading, bool recoveryRequested, bool passwordChanged, String token, String password, String repeatedPassword, bool passwordVisible, bool equalPasswords, String newDialCode, String newPhoneNumber, Map<String, bool> securityChecks
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$RecoverPasswordViewStateCopyWithImpl<$Res>
|
||||
implements _$RecoverPasswordViewStateCopyWith<$Res> {
|
||||
__$RecoverPasswordViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _RecoverPasswordViewState _self;
|
||||
final $Res Function(_RecoverPasswordViewState) _then;
|
||||
|
||||
/// Create a copy of RecoverPasswordViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? email = null,Object? errorMessage = null,Object? recoveryFormat = null,Object? isLoading = null,Object? recoveryRequested = null,Object? passwordChanged = null,Object? token = null,Object? password = null,Object? repeatedPassword = null,Object? passwordVisible = null,Object? equalPasswords = null,Object? newDialCode = null,Object? newPhoneNumber = null,Object? securityChecks = null,}) {
|
||||
return _then(_RecoverPasswordViewState(
|
||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,recoveryFormat: null == recoveryFormat ? _self.recoveryFormat : recoveryFormat // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,recoveryRequested: null == recoveryRequested ? _self.recoveryRequested : recoveryRequested // ignore: cast_nullable_to_non_nullable
|
||||
as bool,passwordChanged: null == passwordChanged ? _self.passwordChanged : passwordChanged // ignore: cast_nullable_to_non_nullable
|
||||
as bool,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||
as String,repeatedPassword: null == repeatedPassword ? _self.repeatedPassword : repeatedPassword // ignore: cast_nullable_to_non_nullable
|
||||
as String,passwordVisible: null == passwordVisible ? _self.passwordVisible : passwordVisible // ignore: cast_nullable_to_non_nullable
|
||||
as bool,equalPasswords: null == equalPasswords ? _self.equalPasswords : equalPasswords // ignore: cast_nullable_to_non_nullable
|
||||
as bool,newDialCode: null == newDialCode ? _self.newDialCode : newDialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPhoneNumber: null == newPhoneNumber ? _self.newPhoneNumber : newPhoneNumber // ignore: cast_nullable_to_non_nullable
|
||||
as String,securityChecks: null == securityChecks ? _self._securityChecks : securityChecks // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, bool>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:auth/src/features/recover_password/presentation/restore_password_screen.dart';
|
||||
import 'package:auth/src/features/recover_password/presentation/request_recovery/request_recovery_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
@@ -12,7 +12,7 @@ class RecoverPasswordBuilder {
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RestorePasswordScreen(navigationContract: navigationContract),
|
||||
child: RequestRecoveryScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ dependencies:
|
||||
navigation:
|
||||
path: ../../packages/navigation
|
||||
sf_localizations:
|
||||
path: ../../packages/sf_localizations
|
||||
path: ../../packages/sf_localizations
|
||||
sf_infrastructure:
|
||||
path: ../../packages/sf_infrastructure
|
||||
utils:
|
||||
path: ../../packages/utils
|
||||
#dependencies go here
|
||||
flutter_svg: ^2.2.1
|
||||
get_it: ^9.0.5
|
||||
|
||||
@@ -5,8 +5,10 @@ class CustomTextField extends StatefulWidget {
|
||||
final TextInputType keyboardType;
|
||||
final TextInputAction? textInputAction;
|
||||
final ValueChanged<String>? onSubmitted;
|
||||
final VoidCallback? onVisibilityChanged;
|
||||
final String hint;
|
||||
final String label;
|
||||
final double labelSize;
|
||||
final int? lines;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final bool readOnly;
|
||||
@@ -19,8 +21,10 @@ class CustomTextField extends StatefulWidget {
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.textInputAction,
|
||||
this.onSubmitted,
|
||||
this.onVisibilityChanged,
|
||||
this.hint = '',
|
||||
this.label = '',
|
||||
this.labelSize = 14,
|
||||
this.lines,
|
||||
this.length,
|
||||
this.onChanged,
|
||||
@@ -50,7 +54,7 @@ class CustomTextFieldState extends State<CustomTextField> {
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
widget.label,
|
||||
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
style: TextStyle(fontSize: widget.labelSize, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
TextFormField(
|
||||
@@ -81,6 +85,7 @@ class CustomTextFieldState extends State<CustomTextField> {
|
||||
_showPassword = !_showPassword;
|
||||
});
|
||||
},
|
||||
//onpressed: widget.onVisibilityChanged,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "Du hast noch kein Konto?",
|
||||
"createOneNow": "Jetzt eines erstellen",
|
||||
"recoverPasswordTitle": "Passwort wiederherstellen",
|
||||
"recoverPasswordSubtitle": "Geben Sie Ihre E-Mail-Adresse ein, um Ihnen einen Wiederherstellungslink zu senden",
|
||||
"send": "Schicken",
|
||||
"back": "Zurückkehren",
|
||||
"email": "E-Mail",
|
||||
"errorMessageContactIsEmpty": "Geben Sie eine E-Mail-Adresse oder Telefonnummer ein",
|
||||
"emailSent": "E-Mail erfolgreich gesendet",
|
||||
"smsSent": "SMS erfolgreich gesendet",
|
||||
"checkEmail1": "Überprüfen Sie Ihre E-Mails und klicken Sie auf den Link, um ein neues Passwort zu erstellen.",
|
||||
"checkSms1": "Überprüfen Sie Ihr Telefon und befolgen Sie die Anweisungen, um ein neues Passwort zu erstellen",
|
||||
"checkEmail2": "Wenn Sie die E-Mail nicht innerhalb weniger Minuten erhalten, überprüfen Sie Ihren Spam-Ordner oder klicken Sie auf „E-Mail erneut senden“.",
|
||||
"checkSms2": "Wenn Sie die SMS nicht innerhalb weniger Minuten erhalten, stellen Sie sicher, dass Sie erreichbar sind, oder klicken Sie auf „SMS erneut senden“.",
|
||||
"resendEmail": "E-Mail weiterleiten",
|
||||
"resendSms": "SMS weiterleiten",
|
||||
"continueKey": "Weitermachen",
|
||||
"newPassword": "Neues Passwort",
|
||||
"repeatPassword": "Passwort wiederholen",
|
||||
"passwordLength": "Mindestens 8 Zeichen",
|
||||
"passwordCapital": "ein Großbuchstabe",
|
||||
"passwordNumber": "eine Zahl",
|
||||
"passwordSpecial": "Ein Sonderzeichen enthalten",
|
||||
"accept": "Akzeptieren",
|
||||
"errorMessageUnequalPasswords": "Passwörter stimmen nicht überein. versuchen Sie es erneut",
|
||||
"errorMessagePasswordTooShort": "Das Passwort muss mindestens 8 Zeichen lang sein",
|
||||
"errorMessagePasswordNoCapitals": "Das Passwort muss mindestens einen Großbuchstaben enthalten",
|
||||
"errorMessagePasswordNoNumbers": "Das Passwort muss mindestens eine Zahl enthalten",
|
||||
"errorMessagePasswordNoSpecialChars": "Das Passwort muss mindestens ein Sonderzeichen enthalten",
|
||||
"errorEmailRequired": "E-Mail ist erforderlich.",
|
||||
"errorEmailInvalid": "Bitte gib eine gültige E-Mail-Adresse ein.",
|
||||
"errorPasswordRequired": "Passwort ist erforderlich.",
|
||||
|
||||
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "Don't have an account?",
|
||||
"createOneNow": "Create one now",
|
||||
"recoverPasswordTitle": "Recover password",
|
||||
"recoverPasswordSubtitle": "Insert your email to send you a recovery link",
|
||||
"send": "Send",
|
||||
"back": "Back",
|
||||
"email": "Email",
|
||||
"errorMessageContactIsEmpty": "Insert an email or phone number",
|
||||
"emailSent": "Email sent correctly",
|
||||
"smsSent": "SMS sent correctly",
|
||||
"checkEmail1": "Check your email and click the link to create a new password.",
|
||||
"checkSms1": "Check your phone and follow the instructions to create a new password.",
|
||||
"checkEmail2": "If you don't receive the email in some minutes, check your spam folder or press \"Resend email\".",
|
||||
"checkSms2": "If you don't receive the SMS in some minutes, make sure you have signal or press \"Resend SMS\".",
|
||||
"resendEmail": "Resend email",
|
||||
"resendSms": "Resend SMS",
|
||||
"continueKey": "Continue",
|
||||
"newPassword": "New password",
|
||||
"repeatPassword": "Repeat password",
|
||||
"passwordLength": "At least 8 characters",
|
||||
"passwordCapital": "One capital letter",
|
||||
"passwordNumber": "One number",
|
||||
"passwordSpecial": "One special character",
|
||||
"accept": "Accept",
|
||||
"errorMessageUnequalPasswords": "Passwords don't match. Try again",
|
||||
"errorMessagePasswordTooShort": "Password must include at least 8 characters",
|
||||
"errorMessagePasswordNoCapitals": "Password must include at least one capital letter",
|
||||
"errorMessagePasswordNoNumbers": "Password must include at least one number",
|
||||
"errorMessagePasswordNoSpecialChars": "Password must include at least one special character",
|
||||
"errorEmailRequired": "Email is required.",
|
||||
"errorEmailInvalid": "Please enter a valid email address.",
|
||||
"errorPasswordRequired": "Password is required.",
|
||||
|
||||
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "¿No tienes cuenta?",
|
||||
"createOneNow": "Crear una ahora",
|
||||
"recoverPasswordTitle": "Recuperar contraseña",
|
||||
"recoverPasswordSubtitle": "Introduce tu email para enviarte un enlace de recuperación",
|
||||
"send": "Enviar",
|
||||
"back": "Volver",
|
||||
"email": "Correo electrónico",
|
||||
"errorMessageContactIsEmpty": "Introduce un correo electrónico o un número de teléfono",
|
||||
"emailSent": "Correo enviado correctamente",
|
||||
"smsSent": "SMS enviado correctamente",
|
||||
"checkEmail1": "Revisa tu email y haz clic en el enlace para crear una nueva contraseña.",
|
||||
"checkSms1": "Revisa tu móvil y sigue las instrucciones para crear una nueva contraseña.",
|
||||
"checkEmail2": "Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\".",
|
||||
"checkSms2": "Si no recibes el SMS en unos minutos, asegúrate de tener cobertura o pulsa \"Reenviar SMS\".",
|
||||
"resendEmail": "Reenviar correo",
|
||||
"resendSms": "Reenviar SMS",
|
||||
"continueKey": "Continuar",
|
||||
"newPassword": "Nueva contraseña",
|
||||
"repeatPassword": "Repetir contraseña",
|
||||
"passwordLength": "Al menos 8 caracteres",
|
||||
"passwordCapital": "Una mayúscula",
|
||||
"passwordNumber": "Un número",
|
||||
"passwordSpecial": "Una carácter especial",
|
||||
"accept": "Aceptar",
|
||||
"errorMessageUnequalPasswords": "Las contraseñas no coinciden. Inténtalo de nuevo",
|
||||
"errorMessagePasswordTooShort": "La contraseña debe tener al menos 8 caracteres",
|
||||
"errorMessagePasswordNoCapitals": "La contraseña debe tener al menos una mayúscula",
|
||||
"errorMessagePasswordNoNumbers": "La contraseña debe tener al menos un número",
|
||||
"errorMessagePasswordNoSpecialChars": "La contraseña debe tener al menos un carácter especial",
|
||||
"errorEmailRequired": "El email es obligatorio.",
|
||||
"errorEmailInvalid": "Introduce un email válido.",
|
||||
"errorPasswordRequired": "La contraseña es obligatoria.",
|
||||
|
||||
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "Tu n'as pas de compte ?",
|
||||
"createOneNow": "Crée-en un maintenant",
|
||||
"recoverPasswordTitle": "Récupérer le mot de passe",
|
||||
"recoverPasswordSubtitle": "Entrez votre email pour vous envoyer un lien de récupération",
|
||||
"send": "Envoyer",
|
||||
"back": "Retour",
|
||||
"email": "E-mail",
|
||||
"errorMessageContactIsEmpty": "Entrez un e-mail ou un numéro de téléphone",
|
||||
"emailSent": "Mail envoyé avec succès",
|
||||
"smsSent": "SMS envoyé avec succès",
|
||||
"checkEmail1": "Vérifiez votre courrier électronique et cliquez sur le lien pour créer un nouveau mot de passe.",
|
||||
"checkSms1": "Vérifiez votre téléphone et suivez les instructions pour créer un nouveau mot de passe",
|
||||
"checkEmail2": "Si vous ne recevez pas l'e-mail au bout de quelques minutes, vérifiez votre dossier spam ou appuyez sur « Renvoyer l'e-mail ».",
|
||||
"checkSms2": "Si vous ne recevez pas le SMS au bout de quelques minutes, assurez-vous d'être couvert ou appuyez sur \"Renvoyer le SMS\".",
|
||||
"resendEmail": "Transférer le courrier",
|
||||
"resendSms": "Transférer des SMS",
|
||||
"continueKey": "Continuer",
|
||||
"newPassword": "Nouveau mot de passe",
|
||||
"repeatPassword": "Répéter le mot de passe",
|
||||
"passwordLength": "Au moins 8 caractères",
|
||||
"passwordCapital": "une majuscule",
|
||||
"passwordNumber": "un numéro",
|
||||
"passwordSpecial": "Un caractère particulier",
|
||||
"accept": "Accepter",
|
||||
"errorMessageUnequalPasswords": "Les mots de passe ne correspondent pas. essayer à nouveau",
|
||||
"errorMessagePasswordTooShort": "Le mot de passe doit contenir au moins 8 caractères",
|
||||
"errorMessagePasswordNoCapitals": "Le mot de passe doit contenir au moins une lettre majuscule",
|
||||
"errorMessagePasswordNoNumbers": "Le mot de passe doit contenir au moins un chiffre",
|
||||
"errorMessagePasswordNoSpecialChars": "Le mot de passe doit contenir au moins un caractère spécial",
|
||||
"errorEmailRequired": "L'e-mail est obligatoire.",
|
||||
"errorEmailInvalid": "Veuillez saisir une adresse e-mail valide.",
|
||||
"errorPasswordRequired": "Le mot de passe est obligatoire.",
|
||||
|
||||
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "Non hai un account?",
|
||||
"createOneNow": "Creane uno adesso",
|
||||
"recoverPasswordTitle": "Recupera la password",
|
||||
"recoverPasswordSubtitle": "Inserisci la tua email per inviarti un collegamento di recupero",
|
||||
"send": "Inviare",
|
||||
"back": "Ritorno",
|
||||
"email": "E-mail",
|
||||
"errorMessageContactIsEmpty": "Inserisci un'e-mail o un numero di telefono",
|
||||
"emailSent": "Mail inviata con successo",
|
||||
"smsSent": "SMS inviato con successo",
|
||||
"checkEmail1": "Controlla la tua email e fai clic sul collegamento per creare una nuova password.",
|
||||
"checkSms1": "Controlla il tuo telefono e segui le istruzioni per creare una nuova password",
|
||||
"checkEmail2": "Se non ricevi l'e-mail entro pochi minuti, controlla la cartella spam o premi \"Invia nuovamente e-mail\".",
|
||||
"checkSms2": "Se non ricevi l'SMS entro pochi minuti, assicurati di avere copertura oppure premi \"Rinvia SMS\".",
|
||||
"resendEmail": "Inoltra la posta",
|
||||
"resendSms": "Inoltra SMS",
|
||||
"continueKey": "Continuare",
|
||||
"newPassword": "Nuova password",
|
||||
"repeatPassword": "Ripeti la password",
|
||||
"passwordLength": "Almeno 8 caratteri",
|
||||
"passwordCapital": "una lettera maiuscola",
|
||||
"passwordNumber": "un numero",
|
||||
"passwordSpecial": "Un carattere speciale",
|
||||
"accept": "Accettare",
|
||||
"errorMessageUnequalPasswords": "Le password non corrispondono. riprova",
|
||||
"errorMessagePasswordTooShort": "La password deve contenere almeno 8 caratteri",
|
||||
"errorMessagePasswordNoCapitals": "La password deve contenere almeno una lettera maiuscola",
|
||||
"errorMessagePasswordNoNumbers": "La password deve contenere almeno un numero",
|
||||
"errorMessagePasswordNoSpecialChars": "La password deve contenere almeno un carattere speciale",
|
||||
"errorEmailRequired": "L'email è obbligatoria.",
|
||||
"errorEmailInvalid": "Inserisci un'email valida.",
|
||||
"errorPasswordRequired": "La password è obbligatoria.",
|
||||
|
||||
@@ -31,6 +31,33 @@
|
||||
"apple": "Apple",
|
||||
"dontHaveAccount": "Não tem conta?",
|
||||
"createOneNow": "Criar uma agora",
|
||||
"recoverPasswordTitle": "Recuperar senha",
|
||||
"recoverPasswordSubtitle": "Insira seu e-mail para enviar um link de recuperação",
|
||||
"send": "Enviar",
|
||||
"back": "Voltar",
|
||||
"email": "Correio eletrônico",
|
||||
"errorMessageContactIsEmpty": "Introduzir um correio eletrônico ou um número de telefone",
|
||||
"emailSent": "Correo enviado corretamente",
|
||||
"smsSent": "SMS enviado corretamente",
|
||||
"checkEmail1": "Revise seu e-mail e clique no link para criar uma nova senha.",
|
||||
"checkSms1": "Revise seu celular e siga as instruções para criar uma nova senha",
|
||||
"checkEmail2": "Se você não receber a correspondência em alguns minutos, revise sua pasta de spam ou pressione \"Reenviar correspondência\".",
|
||||
"checkSms2": "Se você não receber o SMS em alguns minutos, certifique-se de ter cobertura ou pressione \"Reenviar SMS\".",
|
||||
"resendEmail": "Reenviar correio",
|
||||
"resendSms": "Reenviar SMS",
|
||||
"continueKey": "Continuar",
|
||||
"newPassword": "Nova contrasenha",
|
||||
"repeatPassword": "Repetir contraseña",
|
||||
"passwordLength": "Pelo menos 8 caracteres",
|
||||
"passwordCapital": "Una mayúscula",
|
||||
"passwordNumber": "Um número",
|
||||
"passwordSpecial": "Um caráter especial",
|
||||
"accept": "Aceitar",
|
||||
"errorMessageUnequalPasswords": "Las contraseñas não é coincidência.",
|
||||
"errorMessagePasswordTooShort": "A senha deve ter pelo menos 8 caracteres",
|
||||
"errorMessagePasswordNoCapitals": "A senha deve ter pelo menos uma maioscula",
|
||||
"errorMessagePasswordNoNumbers": "A senha deve ter pelo menos um número",
|
||||
"errorMessagePasswordNoSpecialChars": "A senha deve ter menos caráter especial",
|
||||
"errorEmailRequired": "O e-mail é obrigatório.",
|
||||
"errorEmailInvalid": "Introduz um e-mail válido.",
|
||||
"errorPasswordRequired": "A palavra-passe é obrigatória.",
|
||||
|
||||
@@ -3,4 +3,4 @@ export 'src/generated/i18n.dart';
|
||||
export 'src/utils/constants.dart';
|
||||
export 'src/utils/context_extension.dart';
|
||||
export 'src/utils/string_extension.dart';
|
||||
export 'src/utils/locale_extension.dart';
|
||||
export 'src/utils/locale_extension.dart';
|
||||
@@ -35,6 +35,38 @@ class I18n {
|
||||
static const String apple = "apple";
|
||||
static const String dontHaveAccount = "dontHaveAccount";
|
||||
static const String createOneNow = "createOneNow";
|
||||
static const String recoverPasswordTitle = 'recoverPasswordTitle';
|
||||
static const String recoverPasswordSubtitle = 'recoverPasswordSubtitle';
|
||||
static const String send = 'send';
|
||||
static const String back = 'back';
|
||||
static const String email = 'email';
|
||||
static const String errorMessageContactIsEmpty = 'errorMessageContactIsEmpty';
|
||||
static const String emailSent = 'emailSent';
|
||||
static const String smsSent = 'smsSent';
|
||||
static const String checkEmail1 = 'checkEmail1';
|
||||
static const String checkSms1 = 'checkSms1';
|
||||
static const String checkEmail2 = 'checkEmail2';
|
||||
static const String checkSms2 = 'checkSms2';
|
||||
static const String resendEmail = 'resendEmail';
|
||||
static const String resendSms = 'resendSms';
|
||||
static const String continueKey = 'continueKey';
|
||||
static const String newPassword = 'newPassword';
|
||||
static const String repeatPassword = 'repeatPassword';
|
||||
static const String passwordLength = 'passwordLength';
|
||||
static const String passwordCapital = 'passwordCapital';
|
||||
static const String passwordNumber = 'passwordNumber';
|
||||
static const String passwordSpecial = 'passwordSpecial';
|
||||
static const String accept = 'accept';
|
||||
static const String errorMessageUnequalPasswords =
|
||||
'errorMessageUnequalPasswords';
|
||||
static const String errorMessagePasswordTooShort =
|
||||
'errorMessagePasswordTooShort';
|
||||
static const String errorMessagePasswordNoCapitals =
|
||||
'errorMessagePasswordNoCapitals';
|
||||
static const String errorMessagePasswordNoNumbers =
|
||||
'errorMessagePasswordNoNumbers';
|
||||
static const String errorMessagePasswordNoSpecialChars =
|
||||
'errorMessagePasswordNoSpecialChars';
|
||||
static const String errorEmailRequired = 'errorEmailRequired';
|
||||
static const String errorEmailInvalid = 'errorEmailInvalid';
|
||||
static const String errorPasswordRequired = 'errorPasswordRequired';
|
||||
|
||||
@@ -69,7 +69,9 @@ class SizeUtils {
|
||||
|
||||
static bool get isMediumScreen => physicalAspectRatioHeight <= 18.0;
|
||||
|
||||
static bool get isXLScreen => physicalAspectRatioHeight >= 20.0;
|
||||
static bool get isBigScreen => physicalAspectRatioHeight <= 20.0;
|
||||
|
||||
static bool get isXLScreen => physicalAspectRatioHeight >= 21.5;
|
||||
|
||||
static Size get screenSize => Size(width, height);
|
||||
|
||||
@@ -81,7 +83,8 @@ class SizeUtils {
|
||||
}) {
|
||||
if (isSmallerScreen) return small;
|
||||
if (isMediumScreen) return medium ?? small;
|
||||
if (isXLScreen && xl != null) return xl;
|
||||
if (isBigScreen) return big;
|
||||
if (isXLScreen) return xl ?? big;
|
||||
return big;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user