diff --git a/assets/images/ui/connection_error.svg b/assets/images/ui/connection_error.svg new file mode 100644 index 00000000..6a86f662 --- /dev/null +++ b/assets/images/ui/connection_error.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/formulario.svg b/assets/images/ui/formulario.svg new file mode 100644 index 00000000..24ca3859 --- /dev/null +++ b/assets/images/ui/formulario.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/logo_sf.svg b/assets/images/ui/logo_sf.svg new file mode 100644 index 00000000..12a32907 --- /dev/null +++ b/assets/images/ui/logo_sf.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/qr.svg b/assets/images/ui/qr.svg new file mode 100644 index 00000000..8b323a79 --- /dev/null +++ b/assets/images/ui/qr.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index d30d4095..92b8d830 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,20 @@ import 'package:flutter/material.dart'; import 'package:sf_app_platform/payments/apps/di_container.dart'; -import 'package:sf_app_platform/payments/domain/entities/kid.dart'; import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; import 'package:provider/provider.dart'; import 'package:sf_app_platform/payments/view/screens/account_created_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/add_kid_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/alert_screen.dart'; import 'package:sf_app_platform/payments/view/screens/dashboard_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/errors/connection_error_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/errors/no_plan_error_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/errors/server_error_screen.dart'; import 'package:sf_app_platform/payments/view/screens/kid_wallet_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/link_phone_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/loading_google_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/loading_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/restore_password/restore_password_screen.dart'; import 'package:sf_app_platform/payments/view/screens/welcome_screen.dart'; Future main() async { diff --git a/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart b/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart index 245d1a1b..818f1220 100644 --- a/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart +++ b/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart @@ -15,7 +15,7 @@ class ThemeSfAdapter extends ThemePort{ ThemeCode.text_primary: Color(0xFF4B4B4B), ThemeCode.text_secondary: Color(0xFFE0E0E0), ThemeCode.button_primary: Color(0xFF329e95), - ThemeCode.button_secondary: Color(0x4D329E95) + ThemeCode.button_secondary: Color(0xFF4B4B4B) } ); diff --git a/lib/payments/view/screens/add_kid_screen.dart b/lib/payments/view/screens/add_kid_screen.dart new file mode 100644 index 00000000..44747d55 --- /dev/null +++ b/lib/payments/view/screens/add_kid_screen.dart @@ -0,0 +1,53 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_app_platform/payments/view/screens/dashboard_screen.dart'; + +class AddKidScreen extends StatelessWidget{ + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Column( + spacing: 15, + children: [ + Spacer(flex: 6), + Text("Añade a tu peque"), + Text("Controla su gasto a la vez que aprende hábitos financieros responsables"), + Container( + margin: EdgeInsets.symmetric(vertical: 30, horizontal: 50), + child: Row( + children: [ + Column( + children: [ + Text("1"), + Text("2"), + Text("3") + ], + ), + Column( + children: [ + Text("Crea su perfil"), + Text("Vincula su correa y su reloj"), + Text("Carga su hucha") + ], + ) + ], + ), + ), + Text("¡Y todo listo para que tenga su dinero!"), + Text("Recuerda que necesitas tener un Plan SaveFamily"), + Text("Si aún no lo tienes, puedes conseguirlo a través de nuestra web"), + Spacer(flex: 8), + Container( + width: double.infinity, + child: FilledButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>DashboardScreen())), child: Text("¡Empezar!")) + ) + ], + ) + ) + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/alert_screen.dart b/lib/payments/view/screens/alert_screen.dart new file mode 100644 index 00000000..8129da5c --- /dev/null +++ b/lib/payments/view/screens/alert_screen.dart @@ -0,0 +1,95 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; + +class AlertScreen extends StatefulWidget { + const AlertScreen({super.key}); + + @override + State createState() => AlertScreenState(); +} + +class AlertScreenState extends State{ + + final activity = [{"type": "goal"}, {"type": "wage", "amount": 5}, {"type": "lock"}, {"type": "lock"}]; + bool edit = false; + + @override + void initState() { + edit = false; + super.initState(); + } + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), + body: Container( + margin: EdgeInsets.all(30), + child: Column( + children: [ + Row( + children: [ + Text("Alertas"), + Spacer(), + TextButton(onPressed: ()=>setState((){edit = !edit;}), child: Text("Editar")) + ], + ), + Column( + spacing: 20, + children: buildActivity(context, activity, edit) + ), + ], + ), + ), + ); + } + + List buildActivity(BuildContext context, List activity, bool edit){ + ThemePort theme = context.read(); + + final colors = [Colors.cyan, Colors.pinkAccent, Colors.deepOrangeAccent, Colors.red]; + final icons = {"wage": Icons.wallet, "goal": Icons.emoji_events_outlined, "lock": Icons.lock_outline}; + + return List.generate(activity.length, (int index) { + + var logItem = Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + border: BoxBorder.fromLTRB(left: BorderSide(color: colors[index%colors.length], width: 5)) + ), + child: Column( + children: [ + Row( + children: [ + Icon(icons[activity[index]["type"]], color: colors[index%colors.length]), + Text("Entrega de paga", style: TextStyle(fontWeight: FontWeight.bold)), + //Spacer(), + Text("14/01/2005") + ] + ), + Text("Ana tiene ya su paga de 5€ en el reloj") + ] + ) + ); + + if(edit){ + return Row(children: [ + Checkbox( + value: true, + onChanged: (value)=>{}, + activeColor: theme.getColorFor(ThemeCode.button_primary), + semanticLabel: "Eliminar"), + logItem + ]); + } else { + return logItem; + } + }); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/dashboard_screen.dart b/lib/payments/view/screens/dashboard_screen.dart index ec735efe..d91d2f77 100644 --- a/lib/payments/view/screens/dashboard_screen.dart +++ b/lib/payments/view/screens/dashboard_screen.dart @@ -21,10 +21,10 @@ class _DashboardScreenState extends State{ final String name = "Juan"; final double total = 100; final List kids = [ - Kid(name:"Ana", balance:25), - Kid(name:"Carlos", balance:25), + Kid(name:"Carlos", balance:25.47), + Kid(name:"Ana", balance:25.47), ]; - late final double available = kids.fold(total, (t, e) => t - e.balance); + late final double available = double.parse(kids.fold(total, (t, e) => t - e.balance).toStringAsFixed(2)); @override Widget build(BuildContext context) { @@ -45,72 +45,86 @@ class _DashboardScreenState extends State{ NavigationDestination(icon: Icon(Icons.notifications_outlined), label: "Alertas"), ],), body: [ - Container( + SingleChildScrollView( child: Container( margin: EdgeInsets.all(30), child: Column( - children: [ - Text.rich( - TextSpan( - text: 'Hola, ', - style: TextStyle(), - children: [ - TextSpan(text: name, style: TextStyle(fontWeight: FontWeight.bold)), - ], - ), + children: [ + Text.rich( + TextSpan( + text: 'Hola, ', + style: TextStyle(), + children: [ + TextSpan(text: name, style: TextStyle(fontWeight: FontWeight.bold)), + ], ), - walletsList(context, kids), - TextButton(onPressed: ()=>{}, child: Text("+ Añdir otro peque", style: TextStyle(fontWeight: FontWeight.bold))), - Container( - padding: EdgeInsets.all(20), - decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), - child: Column( - children: [ - Row( - children: [ - Text("Wallet", style: TextStyle(fontWeight: FontWeight.bold),), - Spacer(), - Text("$total€ total") - ] - ), - Stack( - children: [ - LinearProgressIndicator( - value: available/total, - minHeight: 70, - borderRadius: BorderRadius.all(Radius.circular(16)), - ), - Center(child: Text(available.toString())), - ], - ), - Center(child: Text("Disponible")) - ], - ), + ), + walletsList(context, kids), + TextButton(onPressed: ()=>{}, child: Text("+ Añdir otro peque", style: TextStyle(fontWeight: FontWeight.bold))), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), + child: Column( + children: [ + Row( + children: [ + Text("Wallet", style: TextStyle(fontWeight: FontWeight.bold),), + Spacer(), + Text("$total€ total") + ] + ), + Stack( + children: [ + LinearProgressIndicator( + value: available/total, + minHeight: 70, + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + FractionallySizedBox( + widthFactor: available/total, + child: Container( + padding: EdgeInsets.symmetric(vertical: 20), + child: Center( + child: Text( + "$available€", + style: TextStyle(color: Colors.white, fontSize: 20) + ) + ) + ) + ), + ], + ), + Center(child: Text("Disponible")) + ], ), - Container( - padding: EdgeInsets.all(20), - child: Column( - children: [ - Text("Ingresar dinero en la cuenta"), - TextField( - decoration: InputDecoration(labelText: "Cantidad", hintText: "0€"), - keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly - ], - ), - Row( - children: [ - - FilledButton(onPressed: ()=>{}, child: Text("Ingresar")) - ], - ), - Text("Máximo que puedes añadir: ${150 - total}€"), - ], - ), - ) - ] + ), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), + margin: EdgeInsets.only(top: 10), + child: Column( + children: [ + Text("Ingresar dinero en el wallets", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Row( + children: [ + Expanded( + child: TextField( + decoration: InputDecoration(labelText: "Cantidad", hintText: "0€", border: OutlineInputBorder()), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ] + ) + ), + FilledButton(onPressed: ()=>{}, child: Text("Ingresar")) + ], + ), + Text("Máximo que puedes añadir: ${150 - total}€"), + ], + ), + ) + ] ), - ), + )), Expanded( child: Center( child: Text("Perfil") @@ -131,6 +145,8 @@ class _DashboardScreenState extends State{ } Widget walletsList(BuildContext context, List kids) { + final theme = context.read(); + return Column( spacing: 20, children: List.generate(kids.length, (int index) { @@ -141,20 +157,22 @@ class _DashboardScreenState extends State{ borderRadius: const BorderRadius.all(Radius.circular(16.0)), child: Container( padding: EdgeInsets.fromLTRB(20, 20, 20, 5), - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, - colors: [ - Color(0xFFFA5C9F), - Color(0xFFEB2579), - Color(0xFFE60866), - ] + colors: theme.getCardColorFor(index) ) ), child: Column( children: [ - Text(kids[index].name, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25, color: Colors.white)), + Text(kids[index].name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + color: Colors.white + ) + ), Row( spacing: 10, children: [ @@ -180,16 +198,33 @@ class _DashboardScreenState extends State{ ), Row( children: [ - TextButton(onPressed: ()=>{}, + TextButton( + onPressed: ()=>showDialog( + context: context, + builder: (BuildContext context) => Dialog( + child: Container(height: 100, width: double.infinity, child: Column( + children: [ + FilledButton(onPressed: ()=>{}, child: Text("Cámara")), + OutlinedButton(onPressed: ()=>{}, child: Text("Galería de fotos")) + ], + )), + ) + ), child: Row( + spacing: 10, children: [ - Icon(Icons.edit), - Text("Editar") + Icon(Icons.edit, color: theme.getColorFor(ThemeCode.text_secondary)), + Text("Editar", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))) ] ) ), Spacer(), - FilledButton(onPressed: ()=>{}, child: Text("+ Añadir dinero")) + FilledButton( + onPressed: ()=>{}, + style: ButtonStyle( + ), + child: Text("+ Añadir dinero") + ) ], ) ] diff --git a/lib/payments/view/screens/errors/connection_error_screen.dart b/lib/payments/view/screens/errors/connection_error_screen.dart new file mode 100644 index 00000000..28eceffd --- /dev/null +++ b/lib/payments/view/screens/errors/connection_error_screen.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class ConnectionErrorScreen extends StatelessWidget{ + + const ConnectionErrorScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + spacing: 15, + children: [ + Spacer(flex: 2), + SvgPicture.asset("assets/images/ui/connection_error.svg"), + Text("Sin conexión a internet", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25) + ), + Text("Necesitas conectividad para usar SaveFamily"), + Text("Puedes continuar en modo offline pero algunas funciones no estaràn disponibles"), + Spacer(flex: 1), + FilledButton( + onPressed: ()=>{}, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(20), + child: Text("Modo offline") + ) + ), + TextButton(onPressed: ()=>{}, child: Text("Reintentar")), + Spacer(flex: 2) + ] + ), + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/errors/no_plan_error_screen.dart b/lib/payments/view/screens/errors/no_plan_error_screen.dart new file mode 100644 index 00000000..3fbbc4cf --- /dev/null +++ b/lib/payments/view/screens/errors/no_plan_error_screen.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; + +class NoPlanErrorScreen extends StatelessWidget{ + + const NoPlanErrorScreen({super.key}); + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + children: [ + Spacer(flex: 3), + Text("Estamos mejorando el servicio", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25) + ), + Text("Asocia tu reloj a SaveFamily y ayuda a tus peques a aprender a usar el dinero con responsabilidad"), + Container( + margin: EdgeInsets.symmetric(vertical: 20), + child: Column( + children: [ + Row(children: [ + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)), + Text("Desarrollarán hábitos financieros sanos") + ]), + Row(children: [ + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)), + Text("Gestiona sus gastos") + ]), + ], + ), + ), + Text("Selecciona tu plan en nuestra web y empieza a enseñar a los peques a entender el valor del dinero"), + Spacer(flex: 1), + FilledButton( + onPressed: ()=>{}, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(20), + child: Text("Seleccionar plan") + ) + ), + Spacer(flex: 3) + ] + ), + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/server_error_screen.dart b/lib/payments/view/screens/errors/server_error_screen.dart similarity index 62% rename from lib/payments/view/screens/server_error_screen.dart rename to lib/payments/view/screens/errors/server_error_screen.dart index 70eac68b..ab2f4db0 100644 --- a/lib/payments/view/screens/server_error_screen.dart +++ b/lib/payments/view/screens/errors/server_error_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; class ServerErrorScreen extends StatelessWidget{ @@ -10,21 +11,18 @@ class ServerErrorScreen extends StatelessWidget{ //backgroundColor: , body: Center( child: Column( + spacing: 20, children: [ - Spacer(), - Text.rich( - TextSpan( - text: "Estamos mejorando el servicio", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25) - ) + Spacer(flex: 2), + Text("Estamos mejorando el servicio", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25) ), - Spacer(), - Image.asset("assets/images/ui/server_error.jpg"), + SvgPicture.asset("assets/images/ui/server_error.svg"), Text("El sistema está en mantenimiento. \nInténtalo de nuevo en unos minutos"), - Spacer(), + Spacer(flex: 1), FilledButton(onPressed: ()=>{}, child: Text("Notificarme")), TextButton(onPressed: ()=>{}, child: Text("Reintentar")), - Spacer() + Spacer(flex: 2) ] ), ) diff --git a/lib/payments/view/screens/kid_wallet_screen.dart b/lib/payments/view/screens/kid_wallet_screen.dart index a50baad5..084460f6 100644 --- a/lib/payments/view/screens/kid_wallet_screen.dart +++ b/lib/payments/view/screens/kid_wallet_screen.dart @@ -23,7 +23,7 @@ class _KidWalletScreenState extends State { final theme = context.read(); return Scaffold( - backgroundColor: Color(0xE6FFFFFF), + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), body: Stack( children: [ DecoratedBox( @@ -47,26 +47,27 @@ class _KidWalletScreenState extends State { children: [ IconButton( onPressed: ()=>Navigator.pop(context), - icon: Icon(Icons.arrow_back_ios_new_outlined, color: Color(0xFFFFFFFF),) + icon: Icon(Icons.arrow_back_ios_new_outlined, color: theme.getColorFor(ThemeCode.background_primary),) ), SizedBox(height: 50, child: SvgPicture.asset("assets/images/ui/face.svg")), Text(widget.kid.name, style: TextStyle( - color: Color(0xFFFFFFFF), + color: theme.getColorFor(ThemeCode.background_primary), fontWeight: FontWeight.bold, fontSize: 20 ) ), - Spacer() + Spacer(), + SizedBox(height: 30, child: SvgPicture.asset("assets/images/ui/face.svg")), ], ), Text("${widget.kid.balance.toString()}€", - style: TextStyle(color: Color(0xFFFFFFFF), fontSize: 35, fontWeight: FontWeight.bold)), - Text("Saldo disponible", style: TextStyle(color: Color(0xFFFFFFFF))), + style: TextStyle(color: theme.getColorFor(ThemeCode.background_primary), fontSize: 35, fontWeight: FontWeight.bold)), + Text("Saldo disponible", style: TextStyle(color: theme.getColorFor(ThemeCode.background_primary))), LinearProgressIndicator( value: 0.7, - color: Color(0xFFFFFFFF), - backgroundColor: Color(0xFFFFFFFF).withAlpha(0x4C), + color: theme.getColorFor(ThemeCode.background_primary), + backgroundColor: theme.getColorFor(ThemeCode.background_primary).withAlpha(0x4C), minHeight: 10, borderRadius: BorderRadius.all(Radius.circular(5)), ), @@ -74,61 +75,63 @@ class _KidWalletScreenState extends State { Center( child: Container( padding: EdgeInsets.all(8), margin: EdgeInsets.only(top: 30), - decoration: const BoxDecoration( - color: Colors.white, + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20)), - ), child: Row( - spacing: 10, - children: [ - TextButton(onPressed: ()=>{}, - child: Column( - spacing: 10, - children: [ - Icon(Icons.add_circle_outline), - Text("Añadir") - ] + ), + child: Row( + spacing: 10, + children: [ + TextButton(onPressed: ()=>{}, + child: Column( + spacing: 10, + children: [ + Icon(Icons.add_circle_outline), + Text("Añadir") + ] + ) + ), + TextButton(onPressed: ()=>{}, + child: Column( + spacing: 10, + children: [ + Icon(Icons.account_balance_wallet_outlined), + Text("Paga") + ] + ) + ), + TextButton(onPressed: ()=>{}, + child: Column( + spacing: 10, + children: [ + Icon(Icons.list_alt_outlined), + Text("Límites") + ] + ) + ), + TextButton(onPressed: ()=>{}, + child: Column( + spacing: 10, + children: [ + Icon(Icons.emoji_events_outlined), + Text("Metas") + ] + ) ) - ), - TextButton(onPressed: ()=>{}, - child: Column( - spacing: 10, - children: [ - Icon(Icons.account_balance_wallet_outlined), - Text("Paga") - ] - ) - ), - TextButton(onPressed: ()=>{}, - child: Column( - spacing: 10, - children: [ - Icon(Icons.list_alt_outlined), - Text("Límites") - ] - ) - ), - TextButton(onPressed: ()=>{}, - child: Column( - spacing: 10, - children: [ - Icon(Icons.emoji_events_outlined), - Text("Metas") - ] - ) - ) - ], - )) + ], + ) + ) ), Container( padding: EdgeInsets.all(15), height: 400, - decoration: const BoxDecoration( - color: Colors.white, + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20)), ), child: Column( children: [ Text("Últimos movimientos"), - activityList(), + activityList(context), TextButton(onPressed: ()=>{}, child: Text("Ver todos")) ], ) @@ -137,12 +140,15 @@ class _KidWalletScreenState extends State { ) ) ], - ), + ), ); } - Widget activityList(){ - final activity = [{"date": "10/05", "payments": [1, 2, 3]}, {"date": "10/04", "payments":[1, 2]}, {"date": "10/02", "payments":[1]}]; + Widget activityList(BuildContext context){ + + final theme = context.read(); + + final activity = [{"date": "10/05", "payments": [1, 2, 3]}, {"date": "10/04", "payments":[1, 2]}, {"date": "10/02", "payments":[1, 2, 3, 4]}]; return Align(alignment: Alignment.topLeft, child: SingleChildScrollView(child: Column( children: List.generate(activity.length, (int index) { @@ -159,8 +165,8 @@ class _KidWalletScreenState extends State { children: [ Container( padding: EdgeInsets.all(9), - color: Color(0xFF329e95).withAlpha(0x1A), - child: Icon(Icons.local_pizza_outlined, color: Color(0xFF329e95)), + color: theme.getColorFor(ThemeCode.button_primary).withAlpha(0x1A), + child: Icon(Icons.local_pizza_outlined, color: theme.getColorFor(ThemeCode.button_primary)), ), Column( children: [ diff --git a/lib/payments/view/screens/link_phone_screen.dart b/lib/payments/view/screens/link_phone_screen.dart index 91f1962d..3116ccde 100644 --- a/lib/payments/view/screens/link_phone_screen.dart +++ b/lib/payments/view/screens/link_phone_screen.dart @@ -11,33 +11,43 @@ class LinkPhoneScreen extends StatelessWidget{ return Scaffold( body: Container( - margin: EdgeInsets.symmetric(horizontal: 20), - child: Center(child: Expanded( + margin: EdgeInsets.all(30), + child: Expanded(child: Center( child: Column( spacing: 10, children: [ 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(children: [ - DropdownMenu( - initialSelection: "es", - dropdownMenuEntries: List.generate(3, (int index){ - return DropdownMenuEntry(labelWidget: Icon(Icons.outlined_flag), label: "es", value: "es"); - }) - ), - Expanded(child: TextField( - onSubmitted: (String value){phone=value;}, - controller: phoneController, - decoration: InputDecoration(labelText: "Teléfono móvil", hintText: "Teléfono"), - keyboardType: TextInputType.number) + Row( + spacing: 10, + children: [ + DropdownMenu( + initialSelection: "es", + dropdownMenuEntries: List.generate(3, (int index){ + return DropdownMenuEntry( + labelWidget: Icon(Icons.outlined_flag), + label: "es", + value: "es", + ); + }) + ), + 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) + ) + ] + ), + SizedBox( + width: double.infinity, + child: FilledButton( + onPressed: ()=>{ + if (phone != null) + Navigator.push(context, MaterialPageRoute(builder: (_)=>PhoneCodeScreen(phone: phone!))) + }, + child: Text("Siguiente") ) - ]), - FilledButton( - onPressed: ()=>{ - if (phone != null) - Navigator.push(context, MaterialPageRoute(builder: (_)=>PhoneCodeScreen(phone: phone!))) - }, - child: Text("Siguiente") ) ] ) diff --git a/lib/payments/view/screens/loading_google_screen.dart b/lib/payments/view/screens/loading_google_screen.dart new file mode 100644 index 00000000..f21edf97 --- /dev/null +++ b/lib/payments/view/screens/loading_google_screen.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class LoadingGoogleScreen extends StatelessWidget{ + const LoadingGoogleScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Expanded( + child: Center( + child: Column( + spacing: 50, + children: [ + Spacer(flex: 8), + Text("Continuar con Google", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)), + CircularProgressIndicator(), + Text("Redirigiendo a Google"), + Spacer(flex: 10) + ], + ), + ) + ), + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/loading_screen.dart b/lib/payments/view/screens/loading_screen.dart index 2fe20cf5..bff86fc7 100644 --- a/lib/payments/view/screens/loading_screen.dart +++ b/lib/payments/view/screens/loading_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; class LoadingScreen extends StatelessWidget{ const LoadingScreen({super.key}); @@ -11,8 +12,10 @@ class LoadingScreen extends StatelessWidget{ child: Column( spacing: 50, children: [ - Image.asset("assets/images/ui/logo.jpg"), - CircularProgressIndicator() + Spacer(flex: 8), + SvgPicture.asset("assets/images/ui/logo_sf.svg"), + CircularProgressIndicator(), + Spacer(flex: 10) ], ), ) diff --git a/lib/payments/view/screens/login_screen.dart b/lib/payments/view/screens/login_screen.dart new file mode 100644 index 00000000..2bf5efe5 --- /dev/null +++ b/lib/payments/view/screens/login_screen.dart @@ -0,0 +1,98 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:sf_app_platform/payments/view/screens/dashboard_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/loading_google_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/restore_password/restore_password_screen.dart'; + +class LoginScreen extends StatefulWidget { + + @override + State createState() => LoginScreenState(); + +} + +class LoginScreenState extends State{ + + bool passwordVisible = false; + + @override + void initState(){ + super.initState(); + passwordVisible = true; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Expanded(child: Center( + child: Container( + margin: EdgeInsets.all(30), + child: Column( + spacing: 10, + children: [ + Icon(Icons.check, color: Color(0xFF329e95), size: 50), + Text("¡Te damos la bienvenida!", style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),), + TextField( + decoration: InputDecoration( + hintText: "Nombre de usuario", + labelText: "Nombre de usuario", + border: OutlineInputBorder(), + ), + ), + 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; + }); + }, + ), + ) + ), + TextButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>RestorePasswordScreen())), + child: Text("¿Has olvidado la contraseña?") + ), + FilledButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>DashboardScreen())), + child: Text("Iniciar sesión") + ), + Stack( + children: [ + Divider(), + Text("o continúa con"), + ], + ), + Row( + spacing: 20, + children: [ + OutlinedButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>LoadingGoogleScreen())), + child: Text("Google", semanticsLabel: "Google") + ), + OutlinedButton( + onPressed: ()=>{}, + child: Icon(Icons.apple, semanticLabel: "Apple") + ) + ], + ), + Text("¿No tienes cuenta?"), + TextButton(onPressed: ()=>{}, child: Text("Crear una ahora")) + ], + ), + ), + )), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/logs/log_screen.dart b/lib/payments/view/screens/logs/log_screen.dart deleted file mode 100644 index c7e94692..00000000 --- a/lib/payments/view/screens/logs/log_screen.dart +++ /dev/null @@ -1,3 +0,0 @@ -abstract class LogScreen { - -} \ No newline at end of file diff --git a/lib/payments/view/screens/phone_code_screen.dart b/lib/payments/view/screens/phone_code_screen.dart index 889a45cd..b745bb81 100644 --- a/lib/payments/view/screens/phone_code_screen.dart +++ b/lib/payments/view/screens/phone_code_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:sf_app_platform/payments/view/screens/dashboard_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/login_screen.dart'; class PhoneCodeScreen extends StatefulWidget { final String phone; @@ -20,35 +21,41 @@ class PhoneCodeScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: Expanded(child: Center( - child: Column( - spacing: 15, - children: [ - Text("Conéctate", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)), - Text.rich(TextSpan(text: "Hemos enviado el código al ", - children: [TextSpan( - text: widget.phone, style: TextStyle(fontWeight: FontWeight.bold))] - )), - Text("Introduce el código aquí"), - Row( - children: List.generate(6, (int i){ - return Expanded(child: TextField( - focusNode: focusNodes[i], - keyboardType: TextInputType.number, - decoration: InputDecoration(hintText: "0"), - maxLength: 1, - onChanged: (String value)=>{value!="" ? focusNodes[i+1].requestFocus() : focusNodes[i-1].requestFocus()}, - )); - }), - ), - FilledButton(onPressed: ()=>{Navigator.pushReplacement(context, MaterialPageRoute(builder: (_)=>DashboardScreen()))}, child: Text("Entrar")), - Text("¿No lo has recibido?"), - TextButton(onPressed: ()=>{}, - child: Text("Volver a intentarlo", style: TextStyle(fontWeight: FontWeight.bold)) - ) - ] - ), - )), + body: Container( + margin: EdgeInsets.all(30), + child: Expanded(child: Center( + child: Column( + spacing: 15, + 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: [TextSpan( + text: widget.phone, style: TextStyle(fontWeight: FontWeight.bold))] + )), + Text("Introduce el código aquí"), + Row( + spacing: 20, + children: List.generate(6, (int i){ + return Expanded(child: TextField( + focusNode: focusNodes[i], + keyboardType: TextInputType.number, + decoration: InputDecoration(hintText: "0", counterText: "", border: OutlineInputBorder()), + maxLength: 1, + onChanged: (String value)=>{value!="" ? focusNodes[i+1].requestFocus() : focusNodes[i-1].requestFocus()}, + )); + }), + ), + FilledButton(onPressed: ()=>{Navigator.pushReplacement(context, MaterialPageRoute(builder: (_)=>LoginScreen()))}, child: Text("Entrar")), + Text("¿No lo has recibido?"), + TextButton(onPressed: ()=>{}, + child: Text("Volver a intentarlo", style: TextStyle(fontWeight: FontWeight.bold)) + ), + Spacer(flex:10) + ] + ), + )), + ) ); } diff --git a/lib/payments/view/screens/restore_password/email_sent_screen.dart b/lib/payments/view/screens/restore_password/email_sent_screen.dart new file mode 100644 index 00000000..20729edd --- /dev/null +++ b/lib/payments/view/screens/restore_password/email_sent_screen.dart @@ -0,0 +1,62 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; +import 'package:sf_app_platform/payments/view/screens/restore_password/new_password_screen.dart'; + +class EmailSentScreen extends StatefulWidget{ + final String email; + + const EmailSentScreen({super.key, required this.email}); + + @override + State createState() => EmailSentScreenState(); + +} + +class EmailSentScreenState extends State { + + @override + Widget build(BuildContext context) { + final theme = context.read(); + + 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.button_primary)), + 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(theme.getColorFor(ThemeCode.button_secondary))), + child: Text("Continuar") + ) + ) + ]), + Spacer(flex: 10) + ], + ), + ), + ), + ); + } +} + diff --git a/lib/payments/view/screens/restore_password/new_password_screen.dart b/lib/payments/view/screens/restore_password/new_password_screen.dart new file mode 100644 index 00000000..1277e3a5 --- /dev/null +++ b/lib/payments/view/screens/restore_password/new_password_screen.dart @@ -0,0 +1,146 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class NewPasswordScreen extends StatefulWidget{ + const NewPasswordScreen({super.key}); + + @override + State createState() => NewPasswordScreenState(); + +} + +class NewPasswordScreenState extends State { + + bool passwordVisible = false; + bool equalPasswords = false; + String password = ""; + var securityChecks = {"min": false, "capital": false, "number": false, "special": false}; + + @override + void initState() { + passwordVisible = false; + equalPasswords = false; + String password = ""; + securityChecks = {"min": false, "capital": false, "number": false, "special": false}; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final theme = context.read(); + + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + spacing: 10, + children: [ + Spacer(flex: 4), + Text("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; + }); + }, + ), + ), + onChanged: (value)=>{ + setState(() { + password = value; + securityChecks = checkSecurity(value); + }) + }, + ), + 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; + }); + }, + ), + ), + onChanged: (value)=>{setState(() { + equalPasswords = password == value; + })}, + ), + Row(children: [ + securityChecks["min"]! ? + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)) : + Icon(Icons.cancel_outlined, color: theme.getColorFor(ThemeCode.button_secondary)), + Text("Al menos 8 caracteres") + ]), + Row(children: [ + securityChecks["capital"]! ? + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)) : + Icon(Icons.cancel_outlined, color: theme.getColorFor(ThemeCode.button_secondary)), + Text("Una mayúscula") + ]), + Row(children: [ + securityChecks["number"]! ? + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)) : + Icon(Icons.cancel_outlined, color: theme.getColorFor(ThemeCode.button_secondary)), + Text("Un número") + ]), + Row(children: [ + securityChecks["special"]! ? + Icon(Icons.check, color: theme.getColorFor(ThemeCode.button_primary)) : + Icon(Icons.cancel_outlined, color: theme.getColorFor(ThemeCode.button_secondary)), + Text("Un carácter especial") + ]), + Spacer(flex: 1), + FilledButton( + onPressed: ()=>{}, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(20), + child: Text("Aceptar") + ) + ), + Spacer(flex: 4) + ], + ), + ), + ), + ); + } + + //TODO: Extraer de la vista + Map checkSecurity(String value) { + Map checks = {}; + + checks["min"] = value.length >= 8; + checks["capital"] = RegExp(r'[A-Z]').hasMatch(value); + checks["number"] = RegExp(r'[0-9]').hasMatch(value); + checks["special"] = RegExp(r'[^A-Za-z0-9]').hasMatch(value); + + return checks; + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/restore_password/restore_password_screen.dart b/lib/payments/view/screens/restore_password/restore_password_screen.dart new file mode 100644 index 00000000..26ecb231 --- /dev/null +++ b/lib/payments/view/screens/restore_password/restore_password_screen.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; +import 'package:sf_app_platform/payments/view/screens/restore_password/email_sent_screen.dart'; + +class RestorePasswordScreen extends StatelessWidget{ + const RestorePasswordScreen({super.key}); + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Center(child: + Column( + spacing: 30, + 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"), + TextField(decoration: InputDecoration(labelText: "Correo electrónico", hintText: "Correo electrónico", border: OutlineInputBorder())), + Row( + spacing: 20, + children: [ + Expanded(child: OutlinedButton(onPressed: ()=>{Navigator.pop(context)}, child: Text("Volver"))), + Expanded(child: FilledButton( + onPressed: ()=>{Navigator.push(context, MaterialPageRoute(builder: (_)=>EmailSentScreen(email: "")))}, + style: ButtonStyle(backgroundColor: WidgetStatePropertyAll(theme.getColorFor(ThemeCode.button_secondary))), + child: Text("Enviar") + )) + ], + ), + Spacer(flex: 10) + ], + ) + ), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup_screen.dart b/lib/payments/view/screens/signup_screen.dart index 8eabbb71..bde99726 100644 --- a/lib/payments/view/screens/signup_screen.dart +++ b/lib/payments/view/screens/signup_screen.dart @@ -79,22 +79,22 @@ class _SignupScreenState extends State { Text("Datos personales"), Text("Identifícate"), Text("Nos aseguraremos de que la cuenta está a nombre del adulto responsable"), - TextField(decoration: InputDecoration(labelText: "Nombre", hintText: "Nombre")), - TextField(decoration: InputDecoration(labelText: "Apellidos", hintText: "Apellidos")), + 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"), + decoration: InputDecoration(label: Text("Fecha de nacimiento"), hintText: "DD", border: OutlineInputBorder()), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], )), Expanded( child: TextField( - decoration: InputDecoration(hintText: "MM"), + decoration: InputDecoration(hintText: "MM", border: OutlineInputBorder()), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], )), Expanded( child: TextField( - decoration: InputDecoration(hintText: "AAAA"), + decoration: InputDecoration(hintText: "AAAA", border: OutlineInputBorder()), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], )), @@ -123,8 +123,8 @@ class _SignupScreenState extends State { Text("Domicilio"), Text("Tu dirección", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), Text("Tu dirección nos ayuda a verificar y mantener la seguridad de tu cuenta"), - TextField(decoration: InputDecoration(hintText: "Dirección completa")), - TextField(decoration: InputDecoration(hintText: "Ciudad")), + TextField(decoration: InputDecoration(hintText: "Dirección completa", border: OutlineInputBorder())), + TextField(decoration: InputDecoration(hintText: "Ciudad", border: OutlineInputBorder())), DropdownMenu( dropdownMenuEntries: List.generate(3, (int index) { return DropdownMenuEntry(value: "España", label: "España"); @@ -132,7 +132,7 @@ class _SignupScreenState extends State { hintText: "País", width: double.infinity, ), - TextField(decoration: InputDecoration(hintText: "Nacionalidad")) + TextField(decoration: InputDecoration(hintText: "Nacionalidad", border: OutlineInputBorder())) ], ), ), @@ -147,7 +147,7 @@ class _SignupScreenState extends State { Text("Usuario y contacto"), Text("Crea tu usuario", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), Text("Con tu email y tu número podremos mantenerte siempre informado"), - TextField(decoration: InputDecoration(labelText: "Correo electrónico", hintText: "Correo electrónico")), + TextField(decoration: InputDecoration(labelText: "Correo electrónico", hintText: "Correo electrónico", border: OutlineInputBorder())), Row(children: [ DropdownMenu( initialSelection: "es", @@ -156,7 +156,7 @@ class _SignupScreenState extends State { }) ), Expanded(child: TextField( - decoration: InputDecoration(labelText: "Teléfono móvil", hintText: "Teléfono"), + decoration: InputDecoration(labelText: "Teléfono móvil", hintText: "Teléfono", border: OutlineInputBorder()), keyboardType: TextInputType.number) ) ], @@ -168,6 +168,7 @@ class _SignupScreenState extends State { decoration: InputDecoration( labelText: "Contraseña", hintText: "********", + border: OutlineInputBorder(), suffixIcon: IconButton( icon: Icon(passwordVisible ? Icons.visibility @@ -186,6 +187,7 @@ class _SignupScreenState extends State { decoration: InputDecoration( labelText: "Repetir contraseña", hintText: "*******", + border: OutlineInputBorder(), suffixIcon: IconButton( icon: Icon(passwordVisible ? Icons.visibility diff --git a/lib/payments/view/screens/wallet_management_screen.dart b/lib/payments/view/screens/wallet_management_screen.dart new file mode 100644 index 00000000..8e185e8f --- /dev/null +++ b/lib/payments/view/screens/wallet_management_screen.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../domain/ports/theme_port.dart'; + +class WalletManagementScreen extends StatefulWidget { + final List children; + + const WalletManagementScreen({super.key, required this.children}); + + @override + State createState() => WalletManagementScreenState(); + +} + +class WalletManagementScreenState extends State{ + + @override + Widget build(BuildContext context) { + final theme = context.read(); + + return Scaffold( + body: Stack(children: [ + DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(30)), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: theme.getCardColorFor(0) + ), + ), + child: SizedBox(width: double.infinity, height: 300), + ), + Container( + margin: EdgeInsets.all(30), + child: Column( + spacing: 15, + children: [ + Row( + spacing: 10, + children: [ + IconButton(onPressed: ()=>Navigator.pop(context), icon: Icon(Icons.arrow_back_ios_outlined)), + Center(child: Column(children: [ + //Text(widget.kid.name), + Text.rich(TextSpan( + text: "Sueldo disponible: ", + children: [ + + ])) + ])) + ], + ), + ...widget.children + ], + ) + ) + ]) + ); + } + +} \ No newline at end of file