- created snackbar, step indicator, money text, text field and progress bar components.

- created wallet balance block, wallet item and kid line chart widgets.
- restructured onboarding, signup and device signup screens into layouts and main screens.
- updated signup and kid wallet screens to 17/11 design.
This commit is contained in:
2025-11-21 15:28:46 +01:00
parent 4225f7510b
commit 8201bff0a7
56 changed files with 1991 additions and 1491 deletions

View File

@@ -4,3 +4,4 @@ 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';

View File

@@ -1,8 +1,9 @@
import 'package:auth/src/device_sign_up/link_watch/create_profile_screen.dart';
import 'package:flutter/material.dart';
class AddKidScreen extends StatelessWidget {
const AddKidScreen({super.key});
final nextStep;
const AddKidScreen({super.key, required this.nextStep});
@override
Widget build(BuildContext context) {
@@ -13,7 +14,7 @@ class AddKidScreen extends StatelessWidget {
spacing: 15,
children: [
Spacer(flex: 6),
Text("Añade a tu peque"),
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",
),
@@ -32,7 +33,7 @@ class AddKidScreen extends StatelessWidget {
],
),
),
Text("¡Y todo listo para que tenga su dinero!"),
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(
"Si aún no lo tienes, puedes conseguirlo a través de nuestra web",
@@ -41,10 +42,7 @@ class AddKidScreen extends StatelessWidget {
Container(
width: double.infinity,
child: FilledButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => CreateProfileScreen()),
),
onPressed: nextStep,
child: Text("¡Empezar!"),
),
),

View File

@@ -1,3 +1,4 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
class ContactScreen extends StatelessWidget {
@@ -36,32 +37,22 @@ class ContactScreen extends StatelessWidget {
],
),
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: "Nombre",
hintText: "Nombre y apellidos",
border: OutlineInputBorder(),
),
child: CustomTextField(
label: "Nombre",
hint: "Nombre y apellidos",
),
),
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: "Correo electrónico",
hintText: "Correo electrónico",
border: OutlineInputBorder(),
),
child: CustomTextField(
label: "Correo electrónico",
hint: "Correo electrónico",
),
),
Expanded(
child: TextField(
minLines: 3,
maxLines: 3,
decoration: InputDecoration(
labelText: "Asunto del mensaje",
hintText: "Escribe tu mensaje",
border: OutlineInputBorder(),
),
child: CustomTextField(
lines: 3,
label: "Asunto del mensaje",
hint: "Escribe tu mensaje",
),
),
Expanded(

View File

@@ -0,0 +1,18 @@
import 'package:auth/src/device_sign_up/device_signup_screen.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:navigation/navigation.dart';
class DeviceSignupBuilder {
const DeviceSignupBuilder();
Page<void> buildPage(BuildContext context, GoRouterState state) {
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
return MaterialPage<void>(
key: state.pageKey,
child: DeviceSignupScreen(navigationContract: navigationContract),
);
}
}

View File

@@ -0,0 +1,101 @@
import 'package:auth/auth.dart';
import 'package:auth/src/device_sign_up/add_kid_screen.dart';
import 'package:auth/src/device_sign_up/link_watch/link_watch_screen.dart';
import 'package:auth/src/device_sign_up/link_watch/link_watch_previous_screen.dart';
import 'package:auth/src/sign_up/account_created_screen.dart';
import 'package:auth/src/widgets/layouts/form_step_layout.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:navigation/navigation.dart';
class DeviceSignupScreen extends ConsumerStatefulWidget{
final NavigationContract navigationContract;
const DeviceSignupScreen({super.key, required this.navigationContract});
@override
ConsumerState<DeviceSignupScreen> createState() => DeviceSignupScreenState(navigationContract);
}
class DeviceSignupScreenState extends ConsumerState<DeviceSignupScreen>{
late int currentStep;
final NavigationContract navigationContract;
DeviceSignupScreenState(this.navigationContract);
@override
void initState() {
currentStep = 0;
}
@override
Widget build(BuildContext context) {
return getSteps()[currentStep];
}
List<Widget> getSteps(){
final theme = ref.watch(themePortProvider);
final continueBtn = Container(
padding: EdgeInsets.all(24),
color: theme.getColorFor(ThemeCode.backgroundPrimary),
child: FilledButton(
onPressed: ()=>{setState(() {
currentStep++;
})},
child: Container(
width: double.infinity,
child: Expanded(child: Center(child: Text("Continuar"))))
)
);
return [
AddKidScreen(nextStep: ()=>{setState(() {
currentStep++;
})}),
FormStepLayout(
title: "Crea su perfil",
subtitle: "Necesitamos estos datos para crear su cuenta y gestionar sus pagos y gastos",
currentStep: 1,
numSteps: 3,
body: [CreateProfileScreen()],
footer: [Container(
padding: EdgeInsets.all(24),
color: theme.getColorFor(ThemeCode.backgroundPrimary),
child: continueBtn
)],
nextStep: ()=>{},
previousStep: ()=>{}
),
FormStepLayout(
title: "Vincula su correa y su reloj",
currentStep: 2,
numSteps: 3,
body: [LinkWatchPreviousScreen()],
footer: [continueBtn],
nextStep: ()=>{},
previousStep: ()=>{}
),
FormStepLayout(
title: "Vincula su correa\ny su reloj",
currentStep: 2,
numSteps: 3,
body: [LinkWatchScreen(step:1)],
footer: [continueBtn],
nextStep: ()=>{},
previousStep: ()=>{}
),
FormStepLayout(
title: "Vincula su correa\ny su reloj",
currentStep: 2,
numSteps: 3,
body: [LinkWatchScreen(step:2)],
footer: [continueBtn],
nextStep: ()=>{},
previousStep: ()=>{}
),
AccountCreatedScreen(navigationContract: navigationContract, kidAccount: true)
];
}
}

View File

@@ -1,87 +0,0 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:auth/src/device_sign_up/add_kid_screen.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class AccountCreatedKidScreen extends ConsumerWidget {
const AccountCreatedKidScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
final model = "SaveWatch Plus 2";
final id = "1106652524";
final fullName = "Carlos Pérez Cruz";
return Scaffold(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
body: Container(
margin: EdgeInsets.all(30),
child: Center(
child: Column(
spacing: 20,
children: [
Spacer(flex: 2),
Icon(
Icons.check,
color: theme.getColorFor(ThemeCode.backgroundPrimary),
size: 50,
),
Text(
"Cuenta creada",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Text.rich(
TextSpan(
text: "Has creado la cuenta para:\n",
children: [
TextSpan(
text: fullName,
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
),
Text("Reloj: $model"),
Text("ID del reloj: $id"),
Text(
"Ya puedes darle su primera paga paa que empiece a disfrutarla en su reloj",
style: TextStyle(fontWeight: FontWeight.bold),
),
Spacer(flex: 6),
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
topLeft: Radius.circular(20),
),
),
child: Column(
children: [
Expanded(
child: FilledButton(
onPressed: () => {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => AddKidScreen()),
),
},
child: Text("Dale su primera paga"),
),
),
TextButton(
onPressed: () => {},
child: Text("Añadir otro peque"),
),
],
),
),
],
),
),
),
);
}
}

View File

@@ -1,304 +1,70 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
class CreateProfileScreen extends ConsumerWidget {
const CreateProfileScreen({super.key});
final int currentStep = 0;
final bool firstTime = false;
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
return Scaffold(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
body: Container(
margin: EdgeInsets.all(30),
child: Center(
child: Column(
spacing: 10,
children: [
Stepper(
type: StepperType.horizontal,
currentStep: currentStep,
onStepCancel: () => currentStep == 0,
// ? null
// :
// setState(() {
// currentStep -= 1;
// }),
controlsBuilder:
(BuildContext context, ControlsDetails controls) {
return FilledButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(
theme.getColorFor(ThemeCode.buttonPrimary),
),
),
onPressed: controls.onStepContinue,
child: const Text('Continuar'),
);
},
steps: [
Step(
state: currentStep > 0
? StepState.complete
: StepState.indexed,
isActive: currentStep >= 0,
stepStyle: currentStep >= 0
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.transparent,
boxShadow: BoxShadow(spreadRadius: 5),
indexStyle: TextStyle(color: Colors.transparent),
),
title: Text(""),
content: Column(
spacing: 10,
children: [
Text(
"Crea su perfil",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30,
),
),
Text(
"Necesitamos estos datos para crear su cuenta y gestionar sus pagas y gastos",
),
Text(
"Comienza con un peque; luego podrás agregar más",
style: TextStyle(fontWeight: FontWeight.bold),
),
TextField(
decoration: InputDecoration(
labelText: "Nombre",
hintText: "Nombre",
border: OutlineInputBorder(),
),
),
TextField(
decoration: InputDecoration(
labelText: "Apellidos",
hintText: "Apellidos",
border: OutlineInputBorder(),
),
),
Row(
spacing: 10,
children: [
Expanded(
child: TextField(
decoration: InputDecoration(
label: Text("Fecha de nacimiento"),
hintText: "DD",
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
),
),
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "MM",
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
),
),
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "AAAA",
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
),
),
],
),
TextField(
decoration: InputDecoration(
labelText: "Dirección completa",
hintText: "Nombre de la calle",
border: OutlineInputBorder(),
),
),
TextButton(
onPressed: () => {},
child: Text(
"Cambiar dirección",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
],
),
),
Step(
state: currentStep > 1
? StepState.complete
: StepState.indexed,
isActive: currentStep >= 1,
stepStyle: currentStep >= 1
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.transparent,
boxShadow: BoxShadow(spreadRadius: 5),
indexStyle: TextStyle(color: Colors.transparent),
),
title: Text(""),
content: Column(
spacing: 10,
children: [
Text(
"Vincula su correa y su reloj",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30,
),
),
SvgPicture.asset("assets/images/ui/formulario.svg"),
Row(
spacing: 10,
children: [
Text("1"),
Column(
children: [
Text("Escanea la correa"),
Text("El peque podrá realizar pagos"),
],
),
],
),
Row(
spacing: 10,
children: [
Text("2"),
Column(
children: [
Text("Escanea el reloj"),
Text("Visualizarás los gastos que se hagan"),
],
),
],
),
],
),
),
Step(
state: currentStep > 2
? StepState.complete
: StepState.indexed,
isActive: currentStep >= 2,
stepStyle: currentStep >= 2
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.transparent,
boxShadow: BoxShadow(spreadRadius: 5),
indexStyle: TextStyle(color: Colors.transparent),
),
title: Text(""),
content: Column(
spacing: 10,
children: [
Text(
"¡Dale su primera paga!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30,
),
),
Text(
"Enséñales a gestionar su dinero recargando su reloj",
),
TextField(
decoration: InputDecoration(
labelText: "Cantidad de dinero de la paga",
hintText: "0€",
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
),
Text("Cantidad mínima: 10€"),
Text(
"Por seguridad sólo se puede disponer de un máximo de 150€ por wallet",
),
Text("Método de ingreso"),
Row(
spacing: 20,
children: [
OutlinedButton(
onPressed: () => {},
child: SvgPicture.asset(
"assets/images/ui/visa.svg",
),
),
OutlinedButton(
onPressed: () => {},
child: SvgPicture.asset(
"assets/images/ui/paypal.svg",
),
),
OutlinedButton(
onPressed: () => {},
child: Row(
children: [
SvgPicture.asset(
"assets/images/ui/banco.svg",
),
Text("Transferencia"),
],
),
),
],
),
Row(
children: [
Icon(Icons.lock_outline),
Text(
"EL pago en esta app es seguro y cumple la normativa europea. Sólo se usará el dinero que decidas para las huchas de tus hijos.",
),
],
),
],
),
),
],
return Column(
spacing: 24,
children: [
Text(
"Comienza con un peque; luego podrás agregar más",
style: TextStyle(fontWeight: FontWeight.bold),
),
CustomTextField(
label: "Nombre",
hint: "Nombre",
),
CustomTextField(
label: "Apellidos",
hint: "Apellidos",
),
Row(
spacing: 10,
children: [
Expanded(
child: CustomTextField(
numeric: true,
label: "Fecha de nacimiento",
hint: "DD",
length: 2,
),
],
),
Expanded(
child: CustomTextField(
numeric: true,
hint: "MM",
length: 2,
),
),
Expanded(
child: CustomTextField(
numeric: true,
hint: "AAAA",
length: 4,
),
),
],
),
CustomTextField(
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)),
),
),
),
],
);
}
}

View File

@@ -0,0 +1,58 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
class LinkWatchPreviousScreen extends ConsumerWidget{
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
return Column(
spacing: 10,
children: [
SvgPicture.asset("assets/images/ui/formulario.svg"),
Row(
spacing: 16,
children: [
Container(
decoration: ShapeDecoration(
shape: CircleBorder(side: BorderSide(color: theme.getColorFor(ThemeCode.backgroundSecondary))),
color: theme.getColorFor(ThemeCode.backgroundSecondary)
),
width: 48,
height: 48,
child: Center(child: Text("1", style: TextStyle(fontSize: 24))),
),
Column(
children: [
Text("Escanea la correa", textAlign: TextAlign.left, style: TextStyle(fontSize: 24)),
Text("El peque podrá realizar pagos"),
],
),
],
),
Row(
spacing: 16,
children: [
Container(
decoration: ShapeDecoration(
shape: CircleBorder(side: BorderSide(color: theme.getColorFor(ThemeCode.backgroundSecondary))),
color: theme.getColorFor(ThemeCode.backgroundSecondary)
),
width: 48,
height: 48,
child: Center(child: Text("2", style: TextStyle(fontSize: 24))),
),
Column(
children: [
Text("Escanea el reloj", textAlign: TextAlign.left, style: TextStyle(fontSize: 24)),
Text("Visualizarás los gastos que se hagan"),
]
)
],
),
],
);
}
}

View File

@@ -0,0 +1,60 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
class LinkWatchScreen extends ConsumerStatefulWidget{
final int step;
const LinkWatchScreen({super.key, required this.step});
@override
ConsumerState<LinkWatchScreen> createState() => LinkWatchScreenState();
}
class LinkWatchScreenState extends ConsumerState<LinkWatchScreen>{
@override
Widget build(BuildContext context) {
final theme = ref.watch(themePortProvider);
return Column(
spacing: 32,
children: [
Row(
children: [
Text("Escanea la correa"),
Spacer(),
Text("Escanea el reloj")
],
),
Container(
padding: EdgeInsets.all(40),
decoration: BoxDecoration(
border: Border.all(color: theme.getColorFor(ThemeCode.textPrimary)),
borderRadius: BorderRadius.all(Radius.circular(16))
),
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(
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))))
))
],
),
Text("Si no consigues vincular su correa o reloj"),
TextButton(onPressed: ()=>{}, child: Text("Contáctanos"))
],
);
}
}

View File

@@ -1,3 +1,4 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:navigation/navigation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -9,17 +10,18 @@ class LinkPhoneScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
TextEditingController phoneController = TextEditingController();
// TextEditingController phoneController = TextEditingController();
// String? phone;
return Scaffold(
body: Container(
margin: EdgeInsets.all(30),
return Scaffold(body: SafeArea(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 24),
child: Expanded(
child: Center(
child: Column(
spacing: 10,
spacing: 48,
children: [
Spacer(flex: 8),
Text(
"¡Nos alegra mucho tenerte por aquí!",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
@@ -43,18 +45,11 @@ class LinkPhoneScreen extends ConsumerWidget {
}),
),
Expanded(
child: TextField(
onSubmitted: (String value) {
// phone = value;
},
controller: phoneController,
decoration: InputDecoration(
labelText: "Teléfono móvil",
hintText: "Teléfono",
border: OutlineInputBorder(),
),
keyboardType: TextInputType.number,
),
child: CustomTextField(
label: "Teléfono móvil",
hint: "Teléfono",
numeric: true
)
),
],
),
@@ -65,11 +60,12 @@ class LinkPhoneScreen extends ConsumerWidget {
child: Text("Siguiente"),
),
),
Spacer(flex: 10)
],
),
),
),
),
);
));
}
}

View File

@@ -1,5 +1,6 @@
import 'package:auth/src/login/presentation/loading_google_screen.dart';
import 'package:auth/src/sign_up/signup_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';
@@ -25,34 +26,14 @@ class LoginScreen extends ConsumerWidget {
"¡Te damos la bienvenida!",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
TextField(
decoration: InputDecoration(
hintText: "Nombre de usuario",
labelText: "Nombre de usuario",
border: OutlineInputBorder(),
),
CustomTextField(
hint: "Nombre de usuario",
label: "Nombre de usuario",
),
TextField(
obscureText: passwordVisible,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Contraseña",
hintText: "********",
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(
passwordVisible
? Icons.visibility
: Icons.visibility_off,
),
onPressed: () {
// setState(() {
// passwordVisible = !passwordVisible;
// });
},
),
),
CustomTextField(
showPassword: passwordVisible,
label: "Contraseña",
hint: "********"
),
TextButton(
onPressed: () =>

View File

@@ -1,15 +1,12 @@
import 'package:flutter/material.dart';
import 'package:navigation/navigation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:sf_app_platform/payments/view/screens/core/dashboard_screen.dart';
// import 'package:sf_app_platform/payments/view/screens/login_screen.dart';
class PhoneCodeScreen extends ConsumerWidget {
// final String phone;
final NavigationContract navigationContract;
PhoneCodeScreen({super.key, required this.navigationContract});
// const PhoneCodeScreen({super.key, required this.phone});
// class PhoneCodeScreenState extends State<PhoneCodeScreen> {
final focusNodes = List<FocusNode>.generate(6, (int i) {

View File

@@ -1,75 +1,135 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:navigation/navigation.dart';
class WelcomeScreen extends ConsumerWidget {
class WelcomeScreen extends ConsumerStatefulWidget {
final NavigationContract navigationContract;
const WelcomeScreen({super.key, required this.navigationContract});
@override
Widget build(BuildContext context, WidgetRef ref) {
ConsumerState<ConsumerStatefulWidget> createState() => WelcomeScreenState(navigationContract: navigationContract);
}
class WelcomeScreenState extends ConsumerState{
late int currentStep;
final NavigationContract navigationContract;
WelcomeScreenState({required this.navigationContract});
@override
void initState() {
super.initState();
currentStep = 0;
}
@override
Widget build(BuildContext context) {
final theme = ref.watch(themePortProvider);
return Scaffold(
body: Center(
child: Column(
children: [
Spacer(),
Expanded(
child: CarouselView(
scrollDirection: Axis.horizontal,
itemExtent: double.infinity,
itemSnapping: true,
shrinkExtent: 400,
children: generateSteps(),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Center(
child: Column(
spacing: 48,
children: [
Spacer(),
generateSteps()[currentStep],
Column(
spacing: 24,
children: [
StepIndicator(max: 3, current: currentStep+1, color: theme.getColorFor(ThemeCode.buttonSecondary)),
generateButtons(theme, 3, currentStep+1)
]
),
),
FilledButton(
onPressed: () => navigationContract.goTo('/link_phone'),
child: const Text('Continuar'),
),
Spacer(),
],
),
),
Spacer()
]
)
)
)
);
}
void jumpToNext(BuildContext context) {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(builder: (_) => LinkPhoneScreen()),
// );
return;
Widget generateButtons(ThemePort theme, int max, int step){
if (step==max) {
return FilledButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonPrimary))
),
onPressed: () => navigationContract.goTo('/link_phone'),
child: Expanded(child: Center(child: Text('Continuar')))
);
} else {
return Column(
spacing: 16,
children: [
FilledButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonSecondary))
),
onPressed: ()=>setState(() {
currentStep++;
}),
child: Expanded(child: Center( child: Text("Siguiente")))
),
TextButton(
onPressed: ()=>navigationContract.goTo('/link_phone'),
child: Text("Omitir")
)
],
);
}
}
List<Widget> generateSteps() {
return [
Column(
spacing: 30,
spacing: 48,
children: [
SvgPicture.asset("assets/images/ui/bienvenida_paso1.svg"),
Text(
"Aprende a gestionar su dinero",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
Text("Tu peque crea hábitos y se divierte mientras lo hace"),
],
Column(
spacing: 16,
children: [
Text(
"Aprende a gestionar su dinero",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 30)
),
Text(
"Tu peque crea hábitos y se divierte mientras lo hace",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18)
)
]
)
]
),
Column(
children: [
SvgPicture.asset("assets/images/ui/bienvenida_paso2.svg"),
Text("Tranquilidad en cada pago que hacen"),
Text("Supervisa gastos, fija límites y acompáñalos en cada paso"),
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(
children: [
SvgPicture.asset("assets/images/ui/bienvenida_paso3.svg"),
Text("Pagos fáciles y seguros en sus manos"),
Text("Podrá pagar desde su reloj.\n Sin móvil ni efectivo"),
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)),
],
),
];
}
}
}

View File

@@ -1,3 +1,4 @@
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';
@@ -8,7 +9,7 @@ class EmailSentScreen extends ConsumerWidget {
const EmailSentScreen({super.key, required this.email});
@override
Widget build(BuildContext contex, WidgetRef ref) {
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
return Scaffold(

View File

@@ -1,6 +1,8 @@
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});
@@ -24,7 +26,7 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
void initState() {
passwordVisible = false;
equalPasswords = false;
String password = "";
password = "";
securityChecks = {
"min": false,
"capital": false,
@@ -36,6 +38,7 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
@override
Widget build(BuildContext context) {
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
final theme = ref.watch(themePortProvider);
return Scaffold(
@@ -50,25 +53,10 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
"Recuperar contraseña",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
),
TextField(
obscureText: passwordVisible,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Nueva contraseña",
hintText: "********",
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(
passwordVisible ? Icons.visibility : Icons.visibility_off,
),
onPressed: () {
setState(() {
passwordVisible = !passwordVisible;
});
},
),
),
CustomTextField(
showPassword: passwordVisible,
label: "Nueva contraseña",
hint: "********",
onChanged: (value) => {
setState(() {
password = value;
@@ -76,25 +64,10 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
}),
},
),
TextField(
obscureText: passwordVisible,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Repetir contraseña",
hintText: "********",
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(
passwordVisible ? Icons.visibility : Icons.visibility_off,
),
onPressed: () {
setState(() {
passwordVisible = !passwordVisible;
});
},
),
),
CustomTextField(
showPassword: passwordVisible,
label: "Repetir contraseña",
hint: "********",
onChanged: (value) => {
setState(() {
equalPasswords = password == value;
@@ -159,7 +132,7 @@ class NewPasswordScreenState extends ConsumerState<NewPasswordScreen> {
),
Spacer(flex: 1),
FilledButton(
onPressed: () => {},
onPressed: ()=>{navigationContract.pushTo('/main/home')},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(20),

View File

@@ -28,12 +28,9 @@ class RestorePasswordScreen extends ConsumerWidget {
Text(
"Introduce tu email para enviarte un enlace de recuperación",
),
TextField(
decoration: InputDecoration(
labelText: "Correo electrónico",
hintText: "Correo electrónico",
border: OutlineInputBorder(),
),
CustomTextField(
label: "Correo electrónico",
hint: "Correo electrónico",
),
Row(
spacing: 20,

View File

@@ -1,10 +1,17 @@
import 'package:auth/src/device_sign_up/add_kid_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';
class AccountCreatedScreen extends ConsumerWidget {
const AccountCreatedScreen({super.key});
final bool kidAccount;
final NavigationContract navigationContract;
const AccountCreatedScreen({
super.key,
required this.kidAccount,
required this.navigationContract,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -12,6 +19,8 @@ class AccountCreatedScreen extends ConsumerWidget {
final email = "usuario@example.com";
final fullName = "Carlos Pérez Cruz";
final model = "SaveWatch Plus 2";
final id = "1106652524";
return Scaffold(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
@@ -24,7 +33,7 @@ class AccountCreatedScreen extends ConsumerWidget {
Spacer(flex: 10),
Icon(
Icons.check,
color: theme.getColorFor(ThemeCode.backgroundPrimary),
color: theme.getColorFor(ThemeCode.buttonPrimary),
size: 50,
),
Text(
@@ -32,6 +41,7 @@ class AccountCreatedScreen extends ConsumerWidget {
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Text.rich(
textAlign: TextAlign.center,
TextSpan(
text: "Has creado la cuenta para:\n",
children: [
@@ -42,7 +52,8 @@ class AccountCreatedScreen extends ConsumerWidget {
],
),
),
Text.rich(
if (!kidAccount) Text.rich(
textAlign: TextAlign.center,
TextSpan(
text: "Hemos enviado un email de verificación a:\n",
children: [
@@ -53,15 +64,18 @@ class AccountCreatedScreen extends ConsumerWidget {
],
),
),
if (kidAccount) Text("Reloj: $model\nID del reloj: $id"),
Text(
"Crea la cuenta de tu peque e ingresa su \nprimera paga para utilizarla con su reloj",
textAlign: TextAlign.center,
),
FilledButton(
onPressed: () => {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => AddKidScreen()),
),
if (kidAccount){
navigationContract.goTo('/main/home')
} else {
navigationContract.pushTo('/device_signup')
}
},
child: Text("Continuar"),
),

View File

@@ -1,3 +1,4 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
class SignupAddressScreen extends StatelessWidget {
@@ -6,28 +7,40 @@ class SignupAddressScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
spacing: 30,
spacing: 24,
children: [
Text("Domicilio"),
Text(
"Tu dirección",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
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,
)),
]
),
Text(
"Tu dirección nos ayuda a verificar y mantener la seguridad de tu cuenta",
),
TextField(
decoration: InputDecoration(
hintText: "Dirección completa",
border: OutlineInputBorder(),
),
),
TextField(
decoration: InputDecoration(
hintText: "Ciudad",
border: OutlineInputBorder(),
),
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"),
],
),
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");
@@ -35,12 +48,7 @@ class SignupAddressScreen extends StatelessWidget {
hintText: "País",
width: double.infinity,
),
TextField(
decoration: InputDecoration(
hintText: "Nacionalidad",
border: OutlineInputBorder(),
),
),
CustomTextField(label: "Nacionalidad", hint: "España"),
],
);
}

View File

@@ -1,5 +1,5 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class SignupPersonalScreen extends StatelessWidget{
const SignupPersonalScreen({super.key});
@@ -7,41 +7,25 @@ class SignupPersonalScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Column(
spacing: 30,
spacing: 24,
children: [
Text("Datos personales"),
Text("Identifícate", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)),
Text("Nos aseguraremos de que la cuenta está a nombre del adulto responsable"),
TextField(decoration: InputDecoration(labelText: "Nombre", hintText: "Nombre", border: OutlineInputBorder())),
TextField(decoration: InputDecoration(labelText: "Apellidos", hintText: "Apellidos", border: OutlineInputBorder())),
Row(
children: [
Expanded( child: TextField(
decoration: InputDecoration(label: Text("Fecha de nacimiento"), hintText: "DD", border: OutlineInputBorder()),
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
)),
Expanded( child: TextField(
decoration: InputDecoration(hintText: "MM", border: OutlineInputBorder()),
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
)),
Expanded( child: TextField(
decoration: InputDecoration(hintText: "AAAA", border: OutlineInputBorder()),
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
)),
],
),
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"),
],
),
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
))
]),
CustomTextField(label: "Correo electrónico", hint: "Correo electrónico"),
],
);
}

View File

@@ -1,136 +1,71 @@
import 'package:auth/src/sign_up/account_created_screen.dart';
import 'package:design_system/design_system.dart';
import 'package:auth/src/widgets/layouts/form_step_layout.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';
import 'package:auth/src/sign_up/signup_user_screen.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get_it/get_it.dart';
import 'package:navigation/navigation.dart';
class SignupScreen extends ConsumerWidget {
class SignupScreen extends ConsumerStatefulWidget {
SignupScreen({super.key});
int currentStep = 0;
ConsumerState<SignupScreen> createState() => SignupScreenState();
}
class SignupScreenState extends ConsumerState<SignupScreen> {
late int currentStep;
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
return MaterialApp(
home: Scaffold(
body: Center(
child: Container(
color: theme.getColorFor(ThemeCode.backgroundPrimary),
padding: const EdgeInsets.all(20),
child: SizedBox(
child: Stepper(
controlsBuilder:
(BuildContext context, ControlsDetails controls) {
return Row(
children: <Widget>[
Expanded(
child: OutlinedButton(
onPressed: controls.onStepCancel,
child: const Text('Atrás'),
),
),
Expanded(
child: FilledButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll<Color>(
theme.getColorFor(ThemeCode.buttonSecondary),
),
),
onPressed: controls.onStepContinue,
child: const Text('Siguiente'),
),
),
],
);
},
type: StepperType.horizontal,
currentStep: currentStep,
onStepCancel: () => currentStep == 0,
// ? null
// : setState(() {
// currentStep -= 1;
// }),
onStepContinue: () {
bool isLastStep = (currentStep == getSteps().length - 1);
if (isLastStep) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => AccountCreatedScreen()),
);
} else {
// setState(() {
// currentStep += 1;
// });
}
},
steps: getSteps(),
),
),
),
),
),
);
void initState() {
super.initState();
currentStep = 0;
}
List<Step> getSteps() {
return <Step>[
Step(
state: currentStep > 0 ? StepState.complete : StepState.indexed,
isActive: currentStep >= 0,
stepStyle: currentStep >= 0
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.transparent,
boxShadow: BoxShadow(spreadRadius: 5),
indexStyle: TextStyle(color: Colors.transparent),
),
title: const Text(""),
content: SignupPersonalScreen(),
@override
Widget build(BuildContext context) {
return getSteps()[currentStep];
}
List<Widget> getSteps() {
return [
FormStepLayout(
title: "Crea tu usuario",
subtitle: "Nos aseguraremos de que la cuenta esté a nombre del adulto responsable",
supertitle: "Datos personales",
currentStep: 1,
numSteps: 3,
body: [SignupPersonalScreen()],
nextStep: ()=>{setState(() {
currentStep++;
})},
previousStep: ()=>{},
),
Step(
state: currentStep > 1 ? StepState.complete : StepState.indexed,
isActive: currentStep >= 1,
stepStyle: currentStep >= 1
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.white,
boxShadow: BoxShadow(spreadRadius: 1),
indexStyle: TextStyle(color: Colors.transparent),
),
title: const Text(""),
content: SignupAddressScreen(),
FormStepLayout(
title: "Tu dirección",
subtitle: "Tu dirección nos ayudará a verificar y mantener la seguridad de tu cuenta",
supertitle: "Domicilio",
currentStep: 2,
numSteps: 3,
body: [SignupAddressScreen()],
nextStep: ()=>{setState(() {
currentStep++;
})},
previousStep: ()=>{setState(() {
currentStep--;
})},
),
Step(
state: currentStep > 2 ? StepState.complete : StepState.indexed,
isActive: currentStep >= 2,
stepStyle: currentStep >= 2
? StepStyle(
connectorThickness: 0,
color: Color(0xFF329e95),
indexStyle: TextStyle(color: Colors.transparent),
)
: StepStyle(
connectorThickness: 0,
color: Colors.white,
boxShadow: BoxShadow(spreadRadius: 1),
indexStyle: TextStyle(color: Colors.transparent),
),
title: const Text(""),
content: SignupUserScreen(),
FormStepLayout(
title: "Identifícate",
subtitle: "Con tu email y tu número podremos mantenerte siempre informado",
supertitle: "Usuario y contacto",
currentStep: 3,
numSteps: 3,
body: [SignupUserScreen()],
nextStep: ()=>{GetIt.I<NavigationContract>().pushTo('/device_signup')},
previousStep: ()=>{setState(() {
currentStep--;
})},
),
];
}

View File

@@ -1,3 +1,4 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
class SignupUserScreen extends StatefulWidget{
@@ -13,62 +14,17 @@ class SignupUserScreenState extends State<SignupUserScreen>{
@override
Widget build(BuildContext context) {
return Column(
spacing: 30,
spacing: 24,
children: [
Text("Usuario y contacto"),
Text("Crea tu usuario", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)),
Text("Con tu email y tu número podremos mantenerte siempre informado"),
TextField(decoration: InputDecoration(labelText: "Correo electrónico", hintText: "Correo electrónico", border: OutlineInputBorder())),
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: TextField(
decoration: InputDecoration(labelText: "Teléfono móvil", hintText: "Teléfono", border: OutlineInputBorder()),
keyboardType: TextInputType.number)
)
]),
TextField(
obscureText: passwordVisible,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Contraseña",
hintText: "********",
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(passwordVisible
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(() {
passwordVisible = !passwordVisible;
});
},
),
)
CustomTextField(
showPassword: passwordVisible,
label: "Contraseña",
hint: "********"
),
TextField(obscureText: passwordVisible,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Repetir contraseña",
hintText: "*******",
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(passwordVisible
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(() {
passwordVisible = !passwordVisible;
});
},
),
)
CustomTextField(
showPassword: passwordVisible,
label: "Repetir contraseña",
hint: "*******"
),
],
);

View File

@@ -0,0 +1,91 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class FormStepLayout extends ConsumerWidget{
final int currentStep;
final int numSteps;
final String? supertitle;
final String title;
final String? subtitle;
final List<Widget> body;
final List<Widget>? footer;
final VoidCallback nextStep;
final VoidCallback previousStep;
const FormStepLayout({
super.key,
required this.title,
this.subtitle,
this.supertitle,
required this.currentStep,
required this.numSteps,
required this.body,
this.footer,
required this.nextStep,
required this.previousStep
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
return Scaffold(
body: SafeArea(child: SingleChildScrollView(child: Container(
color: theme.getColorFor(ThemeCode.backgroundPrimary),
padding: EdgeInsets.only(top: 40, left: 24, right: 24),
child: Column(
spacing: 32,
children: [
Column(
spacing: 24,
children: [
StepIndicator(
max: numSteps,
current: currentStep,
color: theme.getColorFor(ThemeCode.buttonPrimary)
),
if (supertitle!=null) Text(supertitle!, textAlign: TextAlign.center, style: TextStyle(fontSize: 18)),
Text(title, textAlign: TextAlign.center, style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold)),
if (subtitle!=null) Text(subtitle!, textAlign: TextAlign.center, style: TextStyle(fontSize: 18)),
]
),
Column(
spacing: 40,
children: [
...body,
if (footer==null) navigationButtons(currentStep, numSteps, nextStep, previousStep, theme),
...(footer?? [])
]
)
]
)
)))
);
}
Widget navigationButtons(int currentStep, int numSteps, VoidCallback nextStep, VoidCallback previousStep, ThemePort theme) {
if (currentStep == numSteps){
return FilledButton(
onPressed: nextStep,
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonPrimary))),
child: Expanded(child: Center(child: Text("Continuar")))
);
} else {
return Row(
spacing: 16,
children: [
Expanded(child: OutlinedButton(
onPressed: previousStep,
child: Expanded(child: Center(child: Text("Atrás")))
)),
Expanded(child: FilledButton(
onPressed: nextStep,
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll<Color>(theme.getColorFor(ThemeCode.buttonSecondary))),
child: Expanded(child: Center(child: Text("Siguiente")))
))
]
);
}
}
}