- created custom text block, dropdown,
- created extract, goals and block card screen. - generated tests for design system components. - updated restore password and home screens to 17/11 design.
This commit is contained in:
@@ -4,4 +4,5 @@ export 'src/login/link_phone_builder.dart';
|
||||
export 'src/login/phone_code_builder.dart';
|
||||
export 'src/login/login_builder.dart';
|
||||
export 'src/recover_password/recover_password_builder.dart';
|
||||
export 'src/device_sign_up/device_signup_builder.dart';
|
||||
export 'src/device_sign_up/device_signup_builder.dart';
|
||||
export 'src/sign_up/signup_builder.dart';
|
||||
@@ -1,13 +1,18 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class AddKidScreen extends StatelessWidget {
|
||||
class AddKidScreen extends ConsumerWidget {
|
||||
final nextStep;
|
||||
|
||||
const AddKidScreen({super.key, required this.nextStep});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
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: Column(
|
||||
@@ -17,13 +22,39 @@ class AddKidScreen extends StatelessWidget {
|
||||
Text("Añade a tu peque", style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
"Controla su gasto a la vez que aprende hábitos financieros responsables",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 30, horizontal: 50),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Column(children: [Text("1"), Text("2"), Text("3")]),
|
||||
Stack(
|
||||
children: [
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: List<Widget>.generate(3, (int index) =>
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: CircleBorder(),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: Center(child: Text(
|
||||
(index + 1).toString(),
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary)
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
),
|
||||
Divider(color: Colors.red, thickness: 4,),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text("Crea su perfil"),
|
||||
Text("Vincula su correa y su reloj"),
|
||||
@@ -33,18 +64,28 @@ class AddKidScreen extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("¡Y todo listo para que tenga su dinero!", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
Text("Recuerda que necesitas tener un Plan SaveFamily"),
|
||||
Text(
|
||||
"¡Y todo listo para que tenga su dinero!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0
|
||||
)
|
||||
),
|
||||
Text(
|
||||
"Recuerda que necesitas tener un Plan SaveFamily",
|
||||
textAlign: TextAlign.center
|
||||
),
|
||||
Text(
|
||||
"Si aún no lo tienes, puedes conseguirlo a través de nuestra web",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Spacer(flex: 8),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: nextStep,
|
||||
child: Text("¡Empezar!"),
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: nextStep,
|
||||
text: "¡Empezar!",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ContactScreen extends StatelessWidget {
|
||||
class ContactScreen extends ConsumerWidget {
|
||||
const ContactScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
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(
|
||||
|
||||
@@ -38,15 +38,13 @@ class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen>{
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final continueBtn = Container(
|
||||
padding: EdgeInsets.all(24),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
child: FilledButton(
|
||||
child: PrimaryButton(
|
||||
onPressed: ()=>{setState(() {
|
||||
currentStep++;
|
||||
})},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
child: Expanded(child: Center(child: Text("Continuar"))))
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
children: [
|
||||
Text(
|
||||
"Comienza con un peque; luego podrás agregar más",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, letterSpacing: 0),
|
||||
),
|
||||
CustomTextField(
|
||||
label: "Nombre",
|
||||
@@ -26,30 +27,41 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
label: "Apellidos",
|
||||
hint: "Apellidos",
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
label: "Fecha de nacimiento",
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"Fecha de nacimiento",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
numeric: true,
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -57,13 +69,15 @@ class CreateProfileScreen extends ConsumerWidget {
|
||||
label: "Dirección completa",
|
||||
hint: "Nombre de la calle",
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Text(
|
||||
"Cambiar dirección",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: theme.getColorFor(ThemeCode.textPrimary)),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: CustomTextButton(
|
||||
onPressed: () => {},
|
||||
text: "Cambiar dirección",
|
||||
size: 18,
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ class LinkWatchPreviousScreen extends ConsumerWidget{
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: CircleBorder(side: BorderSide(color: theme.getColorFor(ThemeCode.backgroundSecondary))),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary)
|
||||
shape: CircleBorder(side: BorderSide(color: theme.getColorFor(ThemeCode.backgroundSecondary))),
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary)
|
||||
),
|
||||
width: 48,
|
||||
height: 48,
|
||||
|
||||
@@ -21,13 +21,69 @@ class LinkWatchScreenState extends ConsumerState<LinkWatchScreen>{
|
||||
return Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Row(
|
||||
Stack(
|
||||
children: [
|
||||
Text("Escanea la correa"),
|
||||
Spacer(),
|
||||
Text("Escanea el reloj")
|
||||
Divider(
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
thickness: 4,
|
||||
indent: 93,
|
||||
endIndent: 93,
|
||||
height: 48,
|
||||
),
|
||||
if (widget.step==1)Divider(
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
thickness: 4,
|
||||
indent: 186,
|
||||
endIndent: 93,
|
||||
height: 48,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 69),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: CircleBorder(),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
width: 48,
|
||||
height: 48,
|
||||
child: Center(child: Text(
|
||||
"1",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
fontSize: 24
|
||||
)
|
||||
))
|
||||
),
|
||||
Spacer(),
|
||||
Container(
|
||||
decoration: ShapeDecoration(
|
||||
shape: CircleBorder(),
|
||||
color: theme.getColorFor(widget.step==1 ? ThemeCode.backgroundSecondary : ThemeCode.buttonPrimary)
|
||||
),
|
||||
width: 48,
|
||||
height: 48,
|
||||
child: Center(child: Text(
|
||||
"2",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(widget.step==1 ? ThemeCode.textPrimary : ThemeCode.backgroundSecondary),
|
||||
fontSize: 24
|
||||
)
|
||||
))
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(children: [
|
||||
Spacer(),
|
||||
Text("Escanea la correa"),
|
||||
Spacer(),
|
||||
Text("Escanea el reloj"),
|
||||
Spacer(),
|
||||
]),
|
||||
Container(
|
||||
padding: EdgeInsets.all(40),
|
||||
decoration: BoxDecoration(
|
||||
@@ -36,24 +92,36 @@ class LinkWatchScreenState extends ConsumerState<LinkWatchScreen>{
|
||||
),
|
||||
child: SvgPicture.asset("assets/images/ui/qr.svg")
|
||||
),
|
||||
if (widget.step == 2)Text("O inserta el código del reloj"),
|
||||
if (widget.step == 2)Row(
|
||||
if (widget.step == 2)Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "XXXXXXXXXX",
|
||||
)),
|
||||
Expanded(child: FilledButton(
|
||||
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonSecondary))),
|
||||
onPressed: ()=>{},
|
||||
child: Expanded(child: Center(child: Text(
|
||||
"Continuar con código",
|
||||
style: TextStyle(fontSize: 16, letterSpacing: 0))))
|
||||
))
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text("O inserta el código del reloj"),
|
||||
),
|
||||
Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "XXXXXXXXXX",
|
||||
)),
|
||||
Expanded(child: PrimaryButton(
|
||||
onPressed: ()=>{},
|
||||
text: "Continuar con código",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
||||
))
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Text("Si no consigues vincular su correa o reloj"),
|
||||
TextButton(onPressed: ()=>{}, child: Text("Contáctanos"))
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text("Si no consigues vincular su correa o reloj"),
|
||||
CustomTextButton(onPressed: ()=>{}, text: "Contáctanos", weight: FontWeight.w500, size: 18)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,62 +10,69 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
// TextEditingController phoneController = TextEditingController();
|
||||
// String? phone;
|
||||
|
||||
return Scaffold(body: SafeArea(
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"¡Nos alegra mucho tenerte por aquí!",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
"Para poder entrar de forma segura, te vamos a enviar un código al teléfono",
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
initialSelection: "es",
|
||||
dropdownMenuEntries: List<DropdownMenuEntry>.generate(3, (
|
||||
int index,
|
||||
) {
|
||||
return DropdownMenuEntry(
|
||||
labelWidget: Icon(Icons.outlined_flag),
|
||||
label: "es",
|
||||
value: "es",
|
||||
);
|
||||
}),
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
label: "Teléfono móvil",
|
||||
hint: "Teléfono",
|
||||
numeric: true
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => navigationContract.pushTo('/phone_code'),
|
||||
child: Text("Siguiente"),
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"¡Nos alegra mucho tenerte por aquí!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
Spacer(flex: 10)
|
||||
],
|
||||
Text(
|
||||
"Para poder entrar de forma segura, te vamos a enviar un código al teléfono",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 16, letterSpacing: 0),
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(alignment: Alignment.bottomLeft, child: Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
)),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
||||
onChanged: (value)=> {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
numeric: true
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () => navigationContract.pushTo('/phone_code'),
|
||||
text: "Siguiente",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Spacer(flex: 10)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,70 +12,140 @@ class LoginScreen extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
bool passwordVisible = true;
|
||||
return Scaffold(
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
|
||||
final content = [
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.check, color: theme.getColorFor(ThemeCode.buttonPrimary), size: 50),
|
||||
Text(
|
||||
"¡Te damos la bienvenida!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
CustomTextField(
|
||||
hint: "Nombre de usuario",
|
||||
label: "Nombre de usuario",
|
||||
),
|
||||
Column(
|
||||
spacing: 12,
|
||||
children: [
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Contraseña",
|
||||
hint: "********"
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: CustomTextButton(
|
||||
text: "¿Has olvidado la contraseña?",
|
||||
onPressed: () =>
|
||||
navigationContract.pushTo('/recover_password'),
|
||||
size: 16,
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () => navigationContract.goTo('/main/home'),
|
||||
text: "Iniciar sesión",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
spacing: 24,
|
||||
children: [
|
||||
Icon(Icons.check, color: Color(0xFF329e95), size: 50),
|
||||
Text(
|
||||
"¡Te damos la bienvenida!",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
CustomTextField(
|
||||
hint: "Nombre de usuario",
|
||||
label: "Nombre de usuario",
|
||||
),
|
||||
CustomTextField(
|
||||
showPassword: passwordVisible,
|
||||
label: "Contraseña",
|
||||
hint: "********"
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
navigationContract.pushTo('/recover_password'),
|
||||
child: Text("¿Has olvidado la contraseña?"),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => navigationContract.pushTo('/main/home'),
|
||||
child: Text("Iniciar sesión"),
|
||||
),
|
||||
Stack(children: [Divider(), Text("o continúa con")]),
|
||||
Stack(children: [
|
||||
Divider(endIndent: 74, indent: 74),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 14),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
child: Text("o continúa con"),
|
||||
)
|
||||
)
|
||||
]),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
OutlinedButton(
|
||||
Spacer(),
|
||||
SecondaryButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => LoadingGoogleScreen(),
|
||||
),
|
||||
),
|
||||
child: Text("Google", semanticsLabel: "Google"),
|
||||
radius: 16,
|
||||
padding: 44,
|
||||
text: "Google",
|
||||
label: "Google",
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: Icon(Icons.apple, semanticLabel: "Apple"),
|
||||
SecondaryButton(
|
||||
onPressed: ()=>{},
|
||||
radius: 16,
|
||||
padding: 44,
|
||||
icon: Icons.apple,
|
||||
label: "Apple",
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Text("¿No tienes cuenta?"),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => SignupScreen()),
|
||||
),
|
||||
child: Text("Crear una ahora"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
"¿No tienes cuenta?",
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0)
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => navigationContract.goTo('/signup'),
|
||||
child: Text(
|
||||
"Crear una ahora",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, letterSpacing: 0)
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: ListView.separated(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return content[index];
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(color: Colors.transparent, height: 48);
|
||||
},
|
||||
itemCount: content.length,
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
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';
|
||||
|
||||
@@ -15,64 +17,87 @@ class PhoneCodeScreen extends ConsumerWidget {
|
||||
|
||||
@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: 15,
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Conéctate",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Hemos enviado el código al ",
|
||||
children: [
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Text(
|
||||
"Conéctate",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
// text: widget.phone,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
text: "Hemos enviado el código al ",
|
||||
children: [
|
||||
TextSpan(
|
||||
// text: widget.phone,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Introduce el código aquí"),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: List<Widget>.generate(6, (int i) {
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
focusNode: focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
hintText: "0",
|
||||
counterText: "",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
maxLength: 1,
|
||||
onChanged: (String value) => {
|
||||
value != ""
|
||||
? focusNodes[i + 1].requestFocus()
|
||||
: focusNodes[i - 1].requestFocus(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text("Introduce el código aquí"),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: List<Widget>.generate(6, (int i) {
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
focusNode: focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: "0",
|
||||
counterText: "",
|
||||
border: OutlineInputBorder(),
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
PrimaryButton(
|
||||
onPressed: () => {navigationContract.pushTo('/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),
|
||||
),
|
||||
maxLength: 1,
|
||||
onChanged: (String value) => {
|
||||
value != ""
|
||||
? focusNodes[i + 1].requestFocus()
|
||||
: focusNodes[i - 1].requestFocus(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => {navigationContract.pushTo('/login')},
|
||||
child: Text("Entrar"),
|
||||
),
|
||||
Text("¿No lo has recibido?"),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Text(
|
||||
"Volver a intentarlo",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
CustomTextButton(
|
||||
onPressed: () => {},
|
||||
text: "Volver a intentarlo",
|
||||
size: 18,
|
||||
weight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
|
||||
@@ -31,8 +31,9 @@ class WelcomeScreenState extends ConsumerState{
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 48,
|
||||
@@ -42,7 +43,11 @@ class WelcomeScreenState extends ConsumerState{
|
||||
Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
StepIndicator(max: 3, current: currentStep+1, color: theme.getColorFor(ThemeCode.buttonSecondary)),
|
||||
StepIndicator(
|
||||
max: 3,
|
||||
current: currentStep+1,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
||||
),
|
||||
generateButtons(theme, 3, currentStep+1)
|
||||
]
|
||||
),
|
||||
@@ -56,29 +61,29 @@ class WelcomeScreenState extends ConsumerState{
|
||||
|
||||
Widget generateButtons(ThemePort theme, int max, int step){
|
||||
if (step==max) {
|
||||
return FilledButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonPrimary))
|
||||
),
|
||||
return PrimaryButton(
|
||||
onPressed: () => navigationContract.goTo('/link_phone'),
|
||||
child: Expanded(child: Center(child: Text('Continuar')))
|
||||
);
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
width: 324,
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
FilledButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonSecondary))
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: ()=>setState(() {
|
||||
currentStep++;
|
||||
}),
|
||||
child: Expanded(child: Center( child: Text("Siguiente")))
|
||||
text: "Siguiente",
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
width: 324,
|
||||
),
|
||||
TextButton(
|
||||
CustomTextButton(
|
||||
onPressed: ()=>navigationContract.goTo('/link_phone'),
|
||||
child: Text("Omitir")
|
||||
text: "Omitir",
|
||||
size: 18,
|
||||
weight: FontWeight.w500,
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -97,37 +102,57 @@ class WelcomeScreenState extends ConsumerState{
|
||||
Text(
|
||||
"Aprende a gestionar su dinero",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30)
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0)
|
||||
),
|
||||
Text(
|
||||
"Tu peque crea hábitos y se divierte mientras lo hace",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18)
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0)
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/ui/bienvenida_paso2.svg"),
|
||||
Text("Tranquilidad en cada pago que hacen",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30)),
|
||||
Text("Supervisa gastos, fija límites y acompáñalos en cada paso",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18)),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
"Tranquilidad en cada pago que hace",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0)
|
||||
),
|
||||
Text(
|
||||
"Supervisa sus gastos, fija límites y acompáñale en cada paso",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0)
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 48,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/ui/bienvenida_paso3.svg"),
|
||||
Text("Pagos fáciles y seguros en sus manos",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30)),
|
||||
Text("Podrá pagar desde su reloj.\n Sin móvil ni efectivo",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18)),
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Text(
|
||||
"Pagos fáciles y seguros, en sus manos",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0)
|
||||
),
|
||||
Text(
|
||||
"Podrá pagar desde su reloj.\n Sin móvil ni efectivo",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 18, letterSpacing: 0)
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import 'package:auth/src/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 EmailSentScreen extends ConsumerWidget {
|
||||
final String email;
|
||||
|
||||
const EmailSentScreen({super.key, required this.email});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Text(
|
||||
"Correo enviado correctamente",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
Text(
|
||||
"Revisa tu email y haz clic en el enlace para crear una nueva contraseña",
|
||||
),
|
||||
Text(
|
||||
"Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"",
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: Text("Reenviar correo"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () => {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (_) => NewPasswordScreen(),
|
||||
// ),
|
||||
// ),
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
child: Text("Continuar"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -42,104 +42,137 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 4),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
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;
|
||||
}),
|
||||
},
|
||||
),
|
||||
Row(
|
||||
Spacer(),
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
securityChecks["min"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
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),
|
||||
),
|
||||
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),
|
||||
),
|
||||
Text("Una mayúscula", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["number"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un número", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(securityChecks["special"]!
|
||||
? ThemeCode.buttonPrimary
|
||||
: ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un carácter especial", style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"Teléfono móvil",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Al menos 8 caracteres"),
|
||||
),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
||||
onChanged: (value)=> {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
numeric: true
|
||||
))
|
||||
]
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["capital"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Una mayúscula"),
|
||||
],
|
||||
PrimaryButton(
|
||||
onPressed: ()=>{navigationContract.goTo('/main/home')},
|
||||
text: "Aceptar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["number"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un número"),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["special"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un carácter especial"),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
FilledButton(
|
||||
onPressed: ()=>{navigationContract.pushTo('/main/home')},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text("Aceptar"),
|
||||
),
|
||||
),
|
||||
Spacer(flex: 4),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:auth/src/recover_password/presentation/email_sent_screen.dart';
|
||||
import 'package:auth/src/recover_password/presentation/sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
@@ -14,50 +14,85 @@ class RestorePasswordScreen extends ConsumerWidget {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 30,
|
||||
spacing: 48,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contaseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text(
|
||||
"Introduce tu email para enviarte un enlace de recuperación",
|
||||
),
|
||||
CustomTextField(
|
||||
label: "Correo electrónico",
|
||||
hint: "Correo electrónico",
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
Column(
|
||||
spacing: 32,
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
child: Text("Volver"),
|
||||
),
|
||||
Text(
|
||||
"Recuperar contaseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => EmailSentScreen(email: ""),
|
||||
),
|
||||
),
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
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),
|
||||
)
|
||||
),
|
||||
child: Text("Enviar"),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: [Icon(Icons.outlined_flag), Icon(Icons.outlined_flag), Icon(Icons.outlined_flag)],
|
||||
onChanged: (value)=> {},
|
||||
width: 80,
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
hint: "Teléfono",
|
||||
numeric: true
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Expanded( child: SecondaryButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
text: "Volver"
|
||||
)),
|
||||
Expanded( child: PrimaryButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => SentScreen(format: "email"),
|
||||
),
|
||||
),
|
||||
},
|
||||
text: "Enviar",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import 'package:auth/src/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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class AccountCreatedScreen extends ConsumerWidget {
|
||||
"Crea la cuenta de tu peque e ingresa su \nprimera paga para utilizarla con su reloj",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
FilledButton(
|
||||
PrimaryButton(
|
||||
onPressed: () => {
|
||||
if (kidAccount){
|
||||
navigationContract.goTo('/main/home')
|
||||
@@ -77,7 +77,8 @@ class AccountCreatedScreen extends ConsumerWidget {
|
||||
navigationContract.pushTo('/device_signup')
|
||||
}
|
||||
},
|
||||
child: Text("Continuar"),
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
),
|
||||
Spacer(flex: 8),
|
||||
],
|
||||
|
||||
@@ -1,52 +1,100 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class SignupAddressScreen extends StatelessWidget {
|
||||
class SignupAddressScreen extends ConsumerStatefulWidget {
|
||||
const SignupAddressScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<SignupAddressScreen> createState() => SignupAddressScreenState();
|
||||
|
||||
}
|
||||
|
||||
class SignupAddressScreenState extends ConsumerState<SignupAddressScreen>{
|
||||
|
||||
late String country;
|
||||
late int relation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
relation = 0;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Row(
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(child: CustomTextField(
|
||||
label: "Fecha de nacimiento",
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
Align(alignment: Alignment.bottomLeft, child: Text(
|
||||
"Fecha de nacimiento",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
numeric: true,
|
||||
)),
|
||||
]
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(child: CustomTextField(
|
||||
//label: "Fecha de nacimiento",
|
||||
hint: "DD",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "MM",
|
||||
length: 2,
|
||||
numeric: true,
|
||||
)),
|
||||
Expanded(child: CustomTextField(
|
||||
hint: "AAAA",
|
||||
length: 4,
|
||||
numeric: true,
|
||||
)),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
DropdownMenu(
|
||||
width: double.infinity,
|
||||
label: Text("¿Qué familiar eres?"),
|
||||
dropdownMenuEntries: [
|
||||
DropdownMenuEntry(label: "Padre", value: "Padre"),
|
||||
DropdownMenuEntry(label: "Madre", value: "Madre"),
|
||||
DropdownMenuEntry(label: "Tutor", value: "Tutor"),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"¿Qué familiar eres?",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
CustomDropdown(
|
||||
items: [Text("Padre"), Text("Madre"), Text("Tutor")],
|
||||
hint: "¿Qué familiar eres?",
|
||||
onChanged: (value)=>setState(() {
|
||||
relation = value;
|
||||
})
|
||||
),
|
||||
],
|
||||
),
|
||||
CustomTextField(label: "Dirección completa", hint: "Calle Gran Vía 30 6º, 28013"),
|
||||
CustomTextField(label: "Ciudad", hint: "Ciudad"),
|
||||
DropdownMenu(
|
||||
dropdownMenuEntries: List<DropdownMenuEntry>.generate(3, (int index) {
|
||||
return DropdownMenuEntry(value: "España", label: "España");
|
||||
}),
|
||||
hintText: "País",
|
||||
width: double.infinity,
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
"País",
|
||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
||||
),
|
||||
),
|
||||
CustomDropdown(
|
||||
items: [Text("España"), Text("Francia"), Text("Portugal")],
|
||||
hint: "País",
|
||||
onChanged: (value)=>setState(() {
|
||||
country = value;
|
||||
})
|
||||
),
|
||||
],
|
||||
),
|
||||
CustomTextField(label: "Nacionalidad", hint: "España"),
|
||||
],
|
||||
|
||||
18
modules/auth/lib/src/sign_up/signup_builder.dart
Normal file
18
modules/auth/lib/src/sign_up/signup_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/sign_up/signup_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 SignupBuilder {
|
||||
const SignupBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: SignupScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,19 +12,22 @@ class SignupPersonalScreen extends StatelessWidget{
|
||||
CustomTextField(label: "Nombre", hint: "Nombre"),
|
||||
CustomTextField(label: "Apellidos", hint: "Apellidos"),
|
||||
CustomTextField(label: "DNI", hint: "DNI"),
|
||||
Row(children: [
|
||||
DropdownMenu(
|
||||
initialSelection: "es",
|
||||
dropdownMenuEntries: List<DropdownMenuEntry>.generate(3, (int index){
|
||||
return DropdownMenuEntry(labelWidget: Icon(Icons.outlined_flag), label: "es", value: "es");
|
||||
})
|
||||
),
|
||||
Expanded(child: CustomTextField(
|
||||
label: "Teléfono móvil",
|
||||
hint: "123456789",
|
||||
numeric: true
|
||||
))
|
||||
]),
|
||||
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(
|
||||
label: "Teléfono móvil",
|
||||
hint: "123456789",
|
||||
numeric: true
|
||||
))
|
||||
]
|
||||
),
|
||||
CustomTextField(label: "Correo electrónico", hint: "Correo electrónico"),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:auth/src/sign_up/signup_address_screen.dart';
|
||||
import 'package:auth/src/sign_up/signup_personal_screen.dart';
|
||||
@@ -7,19 +8,31 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class SignupScreen extends ConsumerStatefulWidget {
|
||||
SignupScreen({super.key});
|
||||
import 'account_created_screen.dart';
|
||||
|
||||
ConsumerState<SignupScreen> createState() => SignupScreenState();
|
||||
class SignupScreen extends ConsumerStatefulWidget {
|
||||
NavigationContract navigationContract;
|
||||
|
||||
SignupScreen({
|
||||
super.key,
|
||||
required this.navigationContract
|
||||
});
|
||||
|
||||
ConsumerState<SignupScreen> createState() => SignupScreenState(navigationContract);
|
||||
}
|
||||
|
||||
class SignupScreenState extends ConsumerState<SignupScreen> {
|
||||
late int currentStep;
|
||||
late bool acceptTerms;
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
SignupScreenState(this.navigationContract);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
currentStep = 0;
|
||||
acceptTerms = false;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -28,14 +41,50 @@ class SignupScreenState extends ConsumerState<SignupScreen> {
|
||||
}
|
||||
|
||||
List<Widget> getSteps() {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return [
|
||||
FormStepLayout(
|
||||
title: "Crea tu usuario",
|
||||
subtitle: "Nos aseguraremos de que la cuenta esté a nombre del adulto responsable",
|
||||
supertitle: "Datos personales",
|
||||
subtitle: "Con tu email y tu número podremos mantenerte siempre informado",
|
||||
supertitle: "Usuario y contacto",
|
||||
currentStep: 1,
|
||||
numSteps: 3,
|
||||
body: [SignupPersonalScreen()],
|
||||
footer: [
|
||||
Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(child: SecondaryButton(
|
||||
onPressed: ()=>{},
|
||||
text: "Atrás",
|
||||
size: 16,
|
||||
)),
|
||||
Expanded(child: PrimaryButton(
|
||||
onPressed: ()=>{setState(() {
|
||||
currentStep++;
|
||||
})},
|
||||
text: "Siguiente",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
||||
))
|
||||
]
|
||||
),
|
||||
CheckboxListTile(
|
||||
value: acceptTerms,
|
||||
onChanged: (_) => setState(() {
|
||||
acceptTerms = !acceptTerms;
|
||||
}),
|
||||
title: Text(
|
||||
"Acepto los términos y condiciones",
|
||||
style: TextStyle(fontSize: 16, letterSpacing: 0),
|
||||
),
|
||||
checkboxScaleFactor: 1.5,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
)
|
||||
],
|
||||
nextStep: ()=>{setState(() {
|
||||
currentStep++;
|
||||
})},
|
||||
@@ -57,16 +106,19 @@ class SignupScreenState extends ConsumerState<SignupScreen> {
|
||||
),
|
||||
FormStepLayout(
|
||||
title: "Identifícate",
|
||||
subtitle: "Con tu email y tu número podremos mantenerte siempre informado",
|
||||
subtitle: "Contraseña mínima de 8 caracteres, con una mayúscula, un número y un carácter especial",
|
||||
supertitle: "Usuario y contacto",
|
||||
currentStep: 3,
|
||||
numSteps: 3,
|
||||
body: [SignupUserScreen()],
|
||||
nextStep: ()=>{GetIt.I<NavigationContract>().pushTo('/device_signup')},
|
||||
nextStep: ()=>{setState(() {
|
||||
currentStep++;
|
||||
})},
|
||||
previousStep: ()=>{setState(() {
|
||||
currentStep--;
|
||||
})},
|
||||
),
|
||||
AccountCreatedScreen(navigationContract: navigationContract, kidAccount: false)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ class FormStepLayout extends ConsumerWidget{
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: SafeArea(child: SingleChildScrollView(child: Container(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
padding: EdgeInsets.only(top: 40, left: 24, right: 24),
|
||||
@@ -66,23 +67,25 @@ class FormStepLayout extends ConsumerWidget{
|
||||
|
||||
Widget navigationButtons(int currentStep, int numSteps, VoidCallback nextStep, VoidCallback previousStep, ThemePort theme) {
|
||||
if (currentStep == numSteps){
|
||||
return FilledButton(
|
||||
return PrimaryButton(
|
||||
onPressed: nextStep,
|
||||
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonPrimary))),
|
||||
child: Expanded(child: Center(child: Text("Continuar")))
|
||||
text: "Continuar",
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary)
|
||||
);
|
||||
} else {
|
||||
return Row(
|
||||
spacing: 16,
|
||||
children: [
|
||||
Expanded(child: OutlinedButton(
|
||||
Expanded(child: SecondaryButton(
|
||||
onPressed: previousStep,
|
||||
child: Expanded(child: Center(child: Text("Atrás")))
|
||||
text: "Atrás",
|
||||
size: 16,
|
||||
)),
|
||||
Expanded(child: FilledButton(
|
||||
Expanded(child: PrimaryButton(
|
||||
onPressed: nextStep,
|
||||
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonSecondary))),
|
||||
child: Expanded(child: Center(child: Text("Siguiente")))
|
||||
text: "Siguiente",
|
||||
size: 16,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary)
|
||||
))
|
||||
]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user