From 75beafd77197f878caee7b7c8bca4d4a107a5bd0 Mon Sep 17 00:00:00 2001 From: aitorarana Date: Mon, 10 Nov 2025 12:03:32 +0100 Subject: [PATCH] =?UTF-8?q?Creaci=C3=B3n=20de=20pantallas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/images/ui/ahorros.svg | 34 +++ assets/images/ui/banco.svg | 3 + assets/images/ui/paypal.svg | 8 + assets/images/ui/tareas.svg | 28 ++ assets/images/ui/visa.svg | 7 + lib/main.dart | 11 +- lib/payments/domain/ports/theme_port.dart | 2 + .../theme_adapter/theme_sf_adapter.dart | 6 +- .../view/screens/account_created_screen.dart | 52 ++-- .../view/screens/activity_screen.dart | 56 ++++ lib/payments/view/screens/add_kid_screen.dart | 5 +- lib/payments/view/screens/alert_screen.dart | 64 +--- lib/payments/view/screens/contact_screen.dart | 63 ++++ .../view/screens/core/activity_list.dart | 87 ++++++ .../view/screens/core/dashboard_screen.dart | 53 ++++ .../view/screens/core/deposit_block.dart | 51 ++++ .../view/screens/core/line_graph.dart | 169 ++++++++++ .../view/screens/core/money_text.dart | 35 +++ .../core/wallet_management_layout.dart | 70 +++++ .../view/screens/dashboard_screen.dart | 238 --------------- lib/payments/view/screens/deposit_screen.dart | 183 +++++++++++ lib/payments/view/screens/home_screen.dart | 210 +++++++++++++ .../view/screens/kid_wallet_screen.dart | 121 ++++---- lib/payments/view/screens/limits_screen.dart | 109 +++++++ .../view/screens/link_phone_screen.dart | 1 - .../account_created_kid_screen.dart | 55 ++++ .../link_watch/create_profile_screen.dart | 168 ++++++++++ lib/payments/view/screens/login_screen.dart | 8 +- .../view/screens/phone_code_screen.dart | 2 +- lib/payments/view/screens/profile_screen.dart | 115 +++++++ .../view/screens/settings_screen.dart | 231 ++++++++++++++ .../screens/signup/signup_address_screen.dart | 27 ++ .../signup/signup_personal_screen.dart | 49 +++ .../view/screens/signup/signup_screen.dart | 100 ++++++ .../screens/signup/signup_user_screen.dart | 77 +++++ lib/payments/view/screens/signup_screen.dart | 208 ------------- lib/payments/view/screens/wage_screen.dart | 197 ++++++++++++ .../screens/wallet_management_screen.dart | 63 ---- lib/payments/view/screens/welcome_screen.dart | 4 +- pubspec.lock | 288 ++++++++++++++++++ pubspec.yaml | 2 + 41 files changed, 2612 insertions(+), 648 deletions(-) create mode 100644 assets/images/ui/ahorros.svg create mode 100644 assets/images/ui/banco.svg create mode 100644 assets/images/ui/paypal.svg create mode 100644 assets/images/ui/tareas.svg create mode 100644 assets/images/ui/visa.svg create mode 100644 lib/payments/view/screens/activity_screen.dart create mode 100644 lib/payments/view/screens/contact_screen.dart create mode 100644 lib/payments/view/screens/core/activity_list.dart create mode 100644 lib/payments/view/screens/core/dashboard_screen.dart create mode 100644 lib/payments/view/screens/core/deposit_block.dart create mode 100644 lib/payments/view/screens/core/line_graph.dart create mode 100644 lib/payments/view/screens/core/money_text.dart create mode 100644 lib/payments/view/screens/core/wallet_management_layout.dart delete mode 100644 lib/payments/view/screens/dashboard_screen.dart create mode 100644 lib/payments/view/screens/deposit_screen.dart create mode 100644 lib/payments/view/screens/home_screen.dart create mode 100644 lib/payments/view/screens/limits_screen.dart create mode 100644 lib/payments/view/screens/link_watch/account_created_kid_screen.dart create mode 100644 lib/payments/view/screens/link_watch/create_profile_screen.dart create mode 100644 lib/payments/view/screens/profile_screen.dart create mode 100644 lib/payments/view/screens/settings_screen.dart create mode 100644 lib/payments/view/screens/signup/signup_address_screen.dart create mode 100644 lib/payments/view/screens/signup/signup_personal_screen.dart create mode 100644 lib/payments/view/screens/signup/signup_screen.dart create mode 100644 lib/payments/view/screens/signup/signup_user_screen.dart delete mode 100644 lib/payments/view/screens/signup_screen.dart create mode 100644 lib/payments/view/screens/wage_screen.dart delete mode 100644 lib/payments/view/screens/wallet_management_screen.dart diff --git a/assets/images/ui/ahorros.svg b/assets/images/ui/ahorros.svg new file mode 100644 index 00000000..ca93ab53 --- /dev/null +++ b/assets/images/ui/ahorros.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/banco.svg b/assets/images/ui/banco.svg new file mode 100644 index 00000000..4b859e80 --- /dev/null +++ b/assets/images/ui/banco.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/images/ui/paypal.svg b/assets/images/ui/paypal.svg new file mode 100644 index 00000000..fa8267f3 --- /dev/null +++ b/assets/images/ui/paypal.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/tareas.svg b/assets/images/ui/tareas.svg new file mode 100644 index 00000000..61b7eda7 --- /dev/null +++ b/assets/images/ui/tareas.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/ui/visa.svg b/assets/images/ui/visa.svg new file mode 100644 index 00000000..00c167ca --- /dev/null +++ b/assets/images/ui/visa.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 92b8d830..8bf97999 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; import 'package:sf_app_platform/payments/apps/di_container.dart'; import 'package:sf_app_platform/payments/domain/ports/theme_port.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart' hide Provider; 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/core/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'; @@ -15,6 +16,8 @@ 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/settings_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/signup/signup_screen.dart'; import 'package:sf_app_platform/payments/view/screens/welcome_screen.dart'; Future main() async { @@ -36,7 +39,7 @@ class PlatformApp extends StatelessWidget { // Puertos (desde DI) Provider.value(value: di.theme) ], - child: MaterialApp( + child: ProviderScope(child: MaterialApp( title: 'SaveFamily', theme: ThemeData( // This is the theme of your application. @@ -56,8 +59,8 @@ class PlatformApp extends StatelessWidget { // tested with just a hot reload. colorScheme: ColorScheme.fromSeed(seedColor: Color(0xFF329E95)), ), - home: WelcomeScreen(), - ) + home: DashboardScreen(), + )) ); } } \ No newline at end of file diff --git a/lib/payments/domain/ports/theme_port.dart b/lib/payments/domain/ports/theme_port.dart index 66a12d6b..7d4999c3 100644 --- a/lib/payments/domain/ports/theme_port.dart +++ b/lib/payments/domain/ports/theme_port.dart @@ -3,8 +3,10 @@ import 'dart:ui'; enum ThemeCode{ background_primary, background_secondary, + background_tertiary, text_primary, text_secondary, + text_tertiary, button_primary, button_secondary } 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 818f1220..4d77b721 100644 --- a/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart +++ b/lib/payments/infrastructure/adapteres/theme_adapter/theme_sf_adapter.dart @@ -11,9 +11,11 @@ class ThemeSfAdapter extends ThemePort{ Map theme = HashMap.from( { ThemeCode.background_primary: Color(0xFFFFFFFF), - ThemeCode.background_secondary: Color(0xE6FFFFFF), + ThemeCode.background_secondary: Color(0xFFF7F7F7), + ThemeCode.background_tertiary: Color(0x4D329E95), ThemeCode.text_primary: Color(0xFF4B4B4B), - ThemeCode.text_secondary: Color(0xFFE0E0E0), + ThemeCode.text_secondary: Color(0xFFFFFFFF), + ThemeCode.text_tertiary: Color(0xFFE0E0E0), ThemeCode.button_primary: Color(0xFF329e95), ThemeCode.button_secondary: Color(0xFF4B4B4B) } diff --git a/lib/payments/view/screens/account_created_screen.dart b/lib/payments/view/screens/account_created_screen.dart index 0d9561c4..4d63d2ef 100644 --- a/lib/payments/view/screens/account_created_screen.dart +++ b/lib/payments/view/screens/account_created_screen.dart @@ -1,33 +1,45 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:sf_app_platform/payments/view/screens/dashboard_screen.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/add_kid_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/core/dashboard_screen.dart'; + +import '../../domain/ports/theme_port.dart'; class AccountCreatedScreen extends StatelessWidget { @override Widget build(BuildContext context) { + ThemePort theme = context.read(); + final email = "usuario@example.com"; final fullName = "Carlos Pérez Cruz"; - return Scaffold(body: Expanded(child: Center( - child: Column( - spacing: 20, - children: [ - Spacer(), - Icon(Icons.check, color: Color(0xFF329e95), 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.rich(TextSpan(text:"Hemos enviado un email de verificación a:\n", - children: [TextSpan(text: email, style: TextStyle(fontWeight: FontWeight.bold))])), - Text("Crea la cuenta de tu peque e ingresa su primera paga para utilizarla con su reloj"), - FilledButton(onPressed: ()=>{ - Navigator.pushReplacement(context, MaterialPageRoute(builder: (_)=>DashboardScreen())) - }, child: Text("Continuar")), - Spacer() - ], - ), - ))); + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_primary), + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + spacing: 20, + children: [ + Spacer(flex: 10), + Icon(Icons.check, color: theme.getColorFor(ThemeCode.background_primary), 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.rich(TextSpan(text:"Hemos enviado un email de verificación a:\n", + children: [TextSpan(text: email, style: TextStyle(fontWeight: FontWeight.bold))])), + Text("Crea la cuenta de tu peque e ingresa su \nprimera paga para utilizarla con su reloj"), + FilledButton(onPressed: ()=>{ + Navigator.pushReplacement(context, MaterialPageRoute(builder: (_)=>AddKidScreen())) + }, child: Text("Continuar")), + Spacer(flex: 8) + ], + ), + ) + ) + ); } } \ No newline at end of file diff --git a/lib/payments/view/screens/activity_screen.dart b/lib/payments/view/screens/activity_screen.dart new file mode 100644 index 00000000..f47ba8e7 --- /dev/null +++ b/lib/payments/view/screens/activity_screen.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/activity_list.dart'; +import 'package:sf_app_platform/payments/view/screens/core/line_graph.dart'; + +import '../../domain/ports/theme_port.dart'; + +class ActivityScreen extends StatefulWidget{ + const ActivityScreen({super.key}); + + @override + State createState() => ActivityScreenState(); +} + +class ActivityScreenState extends State{ + final activity = [ + {"type": "goal"}, + {"type": "wage", "amount": 5}, + {"type": "lock"}, + {"type": "lock"} + ]; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + final content = [ + Text("Movimientos recientes", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),), + Row( + spacing: 20, + children: [ + FilledButton(onPressed: ()=>{}, child: Text("Hoy")), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Última semana")), + TextButton(onPressed: ()=>{}, child: Text("Mes")) + ], + ), + SizedBox(height: 200, child: LineGraph()), + ActivityList(activity: activity, edit: false) + ]; + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), + body: Container( + margin: EdgeInsets.fromLTRB(30, 30, 30, 0), + child: Center(child: ListView.separated( + itemBuilder: (BuildContext context, int index) {return content[index];}, + separatorBuilder: (BuildContext context, int index) { + return Divider(color: Colors.transparent, height: 30); + }, + itemCount: content.length) + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/add_kid_screen.dart b/lib/payments/view/screens/add_kid_screen.dart index 44747d55..9bc5a29d 100644 --- a/lib/payments/view/screens/add_kid_screen.dart +++ b/lib/payments/view/screens/add_kid_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/core/dashboard_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/link_watch/create_profile_screen.dart'; class AddKidScreen extends StatelessWidget{ @@ -42,7 +43,7 @@ class AddKidScreen extends StatelessWidget{ Spacer(flex: 8), Container( width: double.infinity, - child: FilledButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>DashboardScreen())), child: Text("¡Empezar!")) + child: FilledButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>CreateProfileScreen())), child: Text("¡Empezar!")) ) ], ) diff --git a/lib/payments/view/screens/alert_screen.dart b/lib/payments/view/screens/alert_screen.dart index 8129da5c..2c7016e8 100644 --- a/lib/payments/view/screens/alert_screen.dart +++ b/lib/payments/view/screens/alert_screen.dart @@ -2,6 +2,7 @@ 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/core/activity_list.dart'; class AlertScreen extends StatefulWidget { const AlertScreen({super.key}); @@ -10,9 +11,14 @@ class AlertScreen extends StatefulWidget { State createState() => AlertScreenState(); } -class AlertScreenState extends State{ +class AlertScreenState extends State { - final activity = [{"type": "goal"}, {"type": "wage", "amount": 5}, {"type": "lock"}, {"type": "lock"}]; + final activity = [ + {"type": "goal"}, + {"type": "wage", "amount": 5}, + {"type": "lock"}, + {"type": "lock"} + ]; bool edit = false; @override @@ -35,61 +41,15 @@ class AlertScreenState extends State{ children: [ Text("Alertas"), Spacer(), - TextButton(onPressed: ()=>setState((){edit = !edit;}), child: Text("Editar")) + TextButton( + onPressed: () => setState(() {edit = !edit;}), + child: Text("Editar")) ], ), - Column( - spacing: 20, - children: buildActivity(context, activity, edit) - ), + ActivityList(activity: activity, edit: 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/contact_screen.dart b/lib/payments/view/screens/contact_screen.dart new file mode 100644 index 00000000..d7fea3ee --- /dev/null +++ b/lib/payments/view/screens/contact_screen.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class ContactScreen extends StatelessWidget{ + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + spacing: 10, + children: [ + Text("Contáctanos", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)), + Text("Trasládanos tus dudas e intentaremos responderte lo antes posible"), + DropdownMenu( + initialSelection: "es", + label: Text("País"), + dropdownMenuEntries: [ + DropdownMenuEntry(value: "es", label: "España"), + DropdownMenuEntry(value: "fr", label: "Francia"), + DropdownMenuEntry(value: "pt", label: "Portugal"), + ] + ), + DropdownMenu( + initialSelection: "online", + label: Text("Canal de compra"), + dropdownMenuEntries: [ + DropdownMenuEntry(value: "online", label: "SF online shop"), + ] + ), + Expanded(child: TextField( + decoration: InputDecoration( + labelText: "Nombre", + hintText: "Nombre y apellidos", + border: OutlineInputBorder() + ) + )), + Expanded(child: TextField( + decoration: InputDecoration( + labelText: "Correo electrónico", + hintText: "Correo electrónico", + border: OutlineInputBorder() + ) + )), + Expanded(child: TextField( + minLines: 3, + maxLines: 3, + decoration: InputDecoration( + labelText: "Asunto del mensaje", + hintText: "Escribe tu mensaje", + border: OutlineInputBorder() + ) + )), + Expanded(child: FilledButton(onPressed: ()=>Navigator.pop(context), child: Text("Enviar"))) + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/activity_list.dart b/lib/payments/view/screens/core/activity_list.dart new file mode 100644 index 00000000..7a7ef483 --- /dev/null +++ b/lib/payments/view/screens/core/activity_list.dart @@ -0,0 +1,87 @@ +import 'dart:developer'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class ActivityList extends StatefulWidget { + final List activity; + bool edit = false; + + ActivityList({super.key, required this.activity, required this.edit}); + + @override + State createState() => ActivityListState(); +} + +class ActivityListState extends State{ + + late List values; + + @override + void initState() { + values = List.generate(widget.activity.length, (_)=>false); + super.initState(); + } + + @override + Widget build(BuildContext context) { + 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, "reload": Icons.attach_money_outlined}; + final titles = {"wage": "Entrega de paga", "goal": "¡Objetivo cumplido!", "lock": "Bloqueo de pago", "reload": "Recarga familiar"}; + + return Column( + spacing: 20, + children: List.generate(widget.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( + spacing: 15, + children: [ + Row( + children: [ + Icon(icons[widget.activity[index]["type"]], + color: colors[index % colors.length]), + Text(titles[widget.activity[index]["type"]]!, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), + Spacer(), + Text("14/01/2005") + ] + ), + Align( + alignment: Alignment.topLeft, + child: Text("Ana ya tiene su paga de 5€ en el reloj"), + ) + ] + ) + ); + + if (widget.edit) { + return Row(children: [ + Checkbox( + value: values[index], + onChanged: (value) => { + setState(() { + values[index] = !values[index]; + })}, + activeColor: theme.getColorFor(ThemeCode.button_primary), + semanticLabel: "Eliminar"), + Expanded(child: logItem) + ]); + } else { + return logItem; + } + }) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/dashboard_screen.dart b/lib/payments/view/screens/core/dashboard_screen.dart new file mode 100644 index 00000000..65b699f2 --- /dev/null +++ b/lib/payments/view/screens/core/dashboard_screen.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/activity_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/alert_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/home_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/profile_screen.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class DashboardScreen extends StatefulWidget { + const DashboardScreen({super.key}); + + @override + State createState() => _DashboardScreenState(); +} + +class _DashboardScreenState extends State{ + + int currentPageIndex = 0; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + final bodies = [ + HomeScreen(), + ActivityScreen(), + AlertScreen(), + ProfileScreen() + ]; + + return Scaffold( + bottomNavigationBar: NavigationBar( + backgroundColor: theme.getColorFor(ThemeCode.background_primary), + onDestinationSelected: (int index) { + setState(() { + currentPageIndex = index; + }); + }, + selectedIndex: currentPageIndex, + destinations: [ + NavigationDestination(icon: Icon(Icons.home_outlined), label: "Inicio"), + NavigationDestination(icon: Icon(Icons.watch_outlined), label: "Movimientos"), + NavigationDestination(icon: Icon(Icons.notifications_outlined), label: "Alertas"), + NavigationDestination(icon: Icon(Icons.person_outline_outlined), label: "Mi perfil"), + ] + ), + body: bodies[currentPageIndex], + ); + } + + +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/deposit_block.dart b/lib/payments/view/screens/core/deposit_block.dart new file mode 100644 index 00000000..cf5ed669 --- /dev/null +++ b/lib/payments/view/screens/core/deposit_block.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class DepositBlock extends StatelessWidget{ + final double max; + + const DepositBlock({super.key, required this.max}); + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration(color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20))), + margin: EdgeInsets.only(top: 10), + child: Column( + children: [ + Text("Ingresar dinero en el wallet", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Row( + spacing: 10, + children: [ + Expanded( + child: TextField( + decoration: InputDecoration(labelText: "Cantidad", hintText: "0€", border: OutlineInputBorder()), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ] + ) + ), + FilledButton( + onPressed: ()=>{}, + style: ButtonStyle(backgroundColor: WidgetStatePropertyAll(theme.getColorFor(ThemeCode.button_primary))), + child: Text("Ingresar") + ) + ], + ), + Align( + alignment: Alignment.topLeft, + child: Text("Máximo que puedes añadir: $max€"), + ) + ], + ), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/line_graph.dart b/lib/payments/view/screens/core/line_graph.dart new file mode 100644 index 00000000..3b3b30b3 --- /dev/null +++ b/lib/payments/view/screens/core/line_graph.dart @@ -0,0 +1,169 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class LineGraph extends StatefulWidget { + final lines = [[0,1,0,1,0,1,0],[1,0,1,0,1,0,1]]; + + LineGraph({super.key}); + + @override + State createState() => LineGraphState(); +} + +class LineGraphState extends State { + + final weekDays = ["L", "M", "X", "J", "V", "S", "D"]; + String? timeSpan; + late var days = weekDays; + + @override + void initState() { + timeSpan = "week"; + super.initState(); + } + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Container( + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + border: BoxBorder.fromLTRB(left: BorderSide(color: Colors.cyan, width: 5)), + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column( + spacing: 10, + children: [ + Row(children: [ + Text("Gastos", style: TextStyle(fontWeight: FontWeight.bold)), + Spacer(), + Container( + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + color: theme.getColorFor(ThemeCode.background_secondary), + ), + child: DropdownButton( + underline: Container(), + value: timeSpan, + onChanged: (String? value) { + setState(() { + timeSpan = value; + }); + }, + dropdownColor: theme.getColorFor(ThemeCode.background_primary), + items: [ + DropdownMenuItem(value: "day", child: Text("Hoy")), + DropdownMenuItem(value: "week", child: Text("Esta semana")), + DropdownMenuItem(value: "month", child: Text("Este mes")), + ] + ), + ) + ]), + Expanded(child: LineChart(LineChartData( + gridData: FlGridData( + show: true, + drawHorizontalLine: false, + drawVerticalLine: true, + verticalInterval: 1 + ), + titlesData: FlTitlesData( + //show: false, + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: (double value, TitleMeta meta)=>SideTitleWidget( + space: 4, + meta: meta, + /*fitInside: fitInsideBottomTitle + ? SideTitleFitInsideData.fromTitleMeta(meta, distanceFromEdge: 0) + : SideTitleFitInsideData.disable(),*/ + child: Text( + weekDays[value.toInt()] + ), + ), + ), + ), + leftTitles: AxisTitles(), + topTitles: AxisTitles(), + rightTitles: AxisTitles() + ), + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + getTooltipColor: (touchedSpot) => theme.getColorFor(ThemeCode.button_secondary), + getTooltipItems: (List touchedBarSpots){ + return touchedBarSpots.map( + (barSpot) { + return LineTooltipItem("${barSpot.y} €", TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))); + } + ).toList(); + } + ) + ), + borderData: FlBorderData( + show: true, + border: Border( + bottom: BorderSide( + color: Colors.lightBlue.withValues(alpha: 0.2), + width: 4 + ), + left: const BorderSide(color: Colors.transparent), + right: const BorderSide(color: Colors.transparent), + top: const BorderSide(color: Colors.transparent), + ), + ), + lineBarsData: [ + LineChartBarData( + isCurved: true, + color: Colors.pink, + barWidth: 5, + isStrokeCapRound: true, + dotData: const FlDotData(show: false), + belowBarData: BarAreaData(show: false), + spots: const [ + FlSpot(0, 1), + FlSpot(1, 0), + FlSpot(2, 1), + FlSpot(3, 0), + FlSpot(4, 1), + FlSpot(5, 0), + FlSpot(6, 1), + ], + ), + LineChartBarData( + isCurved: true, + color: Colors.cyan, + barWidth: 5, + isStrokeCapRound: true, + dotData: const FlDotData(show: false), + belowBarData: BarAreaData(show: false), + spots: const [ + FlSpot(0, 0), + FlSpot(1, 1), + FlSpot(2, 0), + FlSpot(3, 1), + FlSpot(4, 0), + FlSpot(5, 1), + FlSpot(6, 0), + ], + ), + ], + minX: 0, + maxX: days.length-1, + maxY: 1, + minY: 0, + ))) + ], + ), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/money_text.dart b/lib/payments/view/screens/core/money_text.dart new file mode 100644 index 00000000..842b644d --- /dev/null +++ b/lib/payments/view/screens/core/money_text.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class MoneyText extends StatelessWidget { + final String text; + final double size; + final bool resize; + final Color color; + + const MoneyText({super.key, required this.text, required this.size, required this.resize, required this.color}); + + @override + Widget build(BuildContext context) { + final units = text.split(".")[0]; + final cents = ",${text.split(".")[1]}"; + + return Text.rich(TextSpan( + text: units, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: size, + color: color + ), + children: [ + TextSpan( + text: cents, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: resize ? size/2 : size + ) + ) + ] + )); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/core/wallet_management_layout.dart b/lib/payments/view/screens/core/wallet_management_layout.dart new file mode 100644 index 00000000..d66573ae --- /dev/null +++ b/lib/payments/view/screens/core/wallet_management_layout.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/entities/kid.dart'; +import '../../../domain/ports/theme_port.dart'; + +class WalletManagementLayout extends StatefulWidget { + final List children; + final Widget footer; + final Kid kid; + + const WalletManagementLayout({super.key, required this.kid, required this.children, required this.footer}); + + @override + State createState() => WalletManagementLayoutState(); +} + +class WalletManagementLayoutState extends State{ + + @override + Widget build(BuildContext context) { + final theme = context.read(); + + final content = [ + Container( + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 20), + child: Stack( + children: [ + IconButton(onPressed: ()=>Navigator.pop(context), icon: Icon(Icons.arrow_back_ios_outlined, color: theme.getColorFor(ThemeCode.text_secondary))), + Expanded(child: Center(child: Column(children: [ + Text(widget.kid.name, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30, color: theme.getColorFor(ThemeCode.text_secondary))), + Text.rich(TextSpan( + text: "Saldo disponible: ", + style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary)), + children: [ + TextSpan(text: "${widget.kid.balance}", style: TextStyle(fontWeight: FontWeight.bold, color: theme.getColorFor(ThemeCode.text_secondary))), + TextSpan(text: "€", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))) + ])) + ]))) + ], + ) + ), + ...widget.children + ]; + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), + 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: 200), + ), + Column(children: [ + Expanded(child: ListView.separated( + itemBuilder: (BuildContext context, int index) {return Container(margin: EdgeInsets.symmetric(horizontal: 20), child: content[index]);}, + separatorBuilder: (BuildContext context, int index) {return Divider(height: 30, color: Colors.transparent);}, + itemCount: content.length)), + widget.footer + ]) + ]) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/dashboard_screen.dart b/lib/payments/view/screens/dashboard_screen.dart deleted file mode 100644 index d91d2f77..00000000 --- a/lib/payments/view/screens/dashboard_screen.dart +++ /dev/null @@ -1,238 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:provider/provider.dart'; -import 'package:sf_app_platform/payments/view/screens/kid_wallet_screen.dart'; - -import '../../domain/entities/kid.dart'; -import '../../domain/ports/theme_port.dart'; - -class DashboardScreen extends StatefulWidget { - const DashboardScreen({super.key}); - - @override - State createState() => _DashboardScreenState(); -} - -class _DashboardScreenState extends State{ - - int currentPageIndex = 0; - - final String name = "Juan"; - final double total = 100; - final List kids = [ - Kid(name:"Carlos", balance:25.47), - Kid(name:"Ana", balance:25.47), - ]; - late final double available = double.parse(kids.fold(total, (t, e) => t - e.balance).toStringAsFixed(2)); - - @override - Widget build(BuildContext context) { - - return Scaffold( - bottomNavigationBar: NavigationBar( - - onDestinationSelected: (int index) { - setState(() { - currentPageIndex = index; - }); - }, - selectedIndex: currentPageIndex, - destinations: [ - NavigationDestination(icon: Icon(Icons.home_outlined), label: "Inicio"), - NavigationDestination(icon: Icon(Icons.person_outline_outlined), label: "Mi perfil"), - NavigationDestination(icon: Icon(Icons.watch_outlined), label: "Movimientos"), - NavigationDestination(icon: Icon(Icons.notifications_outlined), label: "Alertas"), - ],), - body: [ - 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)), - ], - ), - ), - 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), - 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") - ), - ), - Expanded( - child: Center( - child: Text("Movimientos") - ), - ), - Expanded( - child: Center( - child: Text("Alertas") - ), - ) - ][currentPageIndex], - ); - } - - Widget walletsList(BuildContext context, List kids) { - final theme = context.read(); - - return Column( - spacing: 20, - children: List.generate(kids.length, (int index) { - return - GestureDetector( - onTap: ()=>{Navigator.push(context, MaterialPageRoute(builder: (_)=>KidWalletScreen(kid: kids[index])))}, - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16.0)), - child: Container( - padding: EdgeInsets.fromLTRB(20, 20, 20, 5), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: theme.getCardColorFor(index) - ) - ), - child: Column( - children: [ - Text(kids[index].name, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - color: Colors.white - ) - ), - Row( - spacing: 10, - children: [ - SizedBox( - height: 60, - width: 60, - child: SvgPicture.asset("assets/images/ui/face.svg"), - ), - Spacer(), - Text.rich( - TextSpan( - text:kids[index].balance.toString(), - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25, color: Colors.white), - children: [ - TextSpan( - text:"€\nen su hucha", - style: TextStyle(fontWeight: FontWeight.normal, fontSize: 16), - ), - ] - ) - ) - ] - ), - Row( - children: [ - 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, color: theme.getColorFor(ThemeCode.text_secondary)), - Text("Editar", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))) - ] - ) - ), - Spacer(), - FilledButton( - onPressed: ()=>{}, - style: ButtonStyle( - ), - child: Text("+ Añadir dinero") - ) - ], - ) - ] - ), - ) - ) - ); - }) - ); - } -} \ No newline at end of file diff --git a/lib/payments/view/screens/deposit_screen.dart b/lib/payments/view/screens/deposit_screen.dart new file mode 100644 index 00000000..d97f5611 --- /dev/null +++ b/lib/payments/view/screens/deposit_screen.dart @@ -0,0 +1,183 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/wallet_management_layout.dart'; + +import '../../domain/entities/kid.dart'; +import '../../domain/ports/theme_port.dart'; + +class DepositScreen extends StatefulWidget{ + final Kid kid; + + const DepositScreen({super.key, required this.kid}); + + @override + State createState() => DepositScreenState(); + +} + +class DepositScreenState extends State{ + String reason = "other"; + bool program = false; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return WalletManagementLayout( + kid: widget.kid, + children: [ + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Ingresar dinero en el wallet", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + TextField( + decoration: InputDecoration(labelText: "Cantidad", hintText: "0€", border: OutlineInputBorder()), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ] + ), + Align( + alignment: Alignment.topLeft, + child: Text("Saldo total disponible después: 30 €") + ) + ], + ), + ), + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Motivo", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Este dato aparecerá en el reloj del peque"), + CheckboxListTile( + title: Text('Paga semanal'), + controlAffinity: ListTileControlAffinity.leading, + value: reason=="weekly", + onChanged: (value) { + setState(() { + reason="weekly"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Objetivo semanal cumplido'), + controlAffinity: ListTileControlAffinity.leading, + value: reason=="goal", + onChanged: (value) { + setState(() { + reason="goal"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Gastos extraordinarios'), + controlAffinity: ListTileControlAffinity.leading, + value: reason=="extraordinary", + onChanged: (value) { + setState(() { + reason="extraordinary"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Otro'), + controlAffinity: ListTileControlAffinity.leading, + value: reason=="other", + onChanged: (value) { + setState(() { + reason="other"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + TextField( + minLines: 3, + maxLines: 3, + maxLength: 150, + decoration: InputDecoration( + labelText: "Escribir mensaje a ${widget.kid.name} del motivo del ingreso", + hintText: "Escribe tu mensaje", + border: OutlineInputBorder(), + ) + ), + Align( + alignment: Alignment.topLeft, + child: Text("Máximo 150 caracteres") + ) + ], + ), + ), + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Cuándo se envía el dinero", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Este dato aparecerá en el reloj del peque"), + CheckboxListTile( + title: Text('Ahora'), + controlAffinity: ListTileControlAffinity.leading, + value: program==false, + onChanged: (value) { + setState(() { + program=false; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Programar'), + controlAffinity: ListTileControlAffinity.leading, + value: program==true, + onChanged: (value) { + setState(() { + program=true; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + if (program) TextField() + ], + ), + ), + ], + footer: Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column(children: [ + FilledButton(onPressed: ()=>{}, child: Container( + width: double.infinity, + padding: EdgeInsets.all(20), + child: Center(child: Text("Añadir dinero")) + )), + TextButton(onPressed: ()=>Navigator.pop(context), child: Text("Cancelar")) + ]) + ) + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/home_screen.dart b/lib/payments/view/screens/home_screen.dart new file mode 100644 index 00000000..fd3be2b1 --- /dev/null +++ b/lib/payments/view/screens/home_screen.dart @@ -0,0 +1,210 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/deposit_block.dart'; +import 'package:sf_app_platform/payments/view/screens/core/money_text.dart'; +import 'package:sf_app_platform/payments/view/screens/link_watch/create_profile_screen.dart'; + +import '../../domain/entities/kid.dart'; +import '../../domain/ports/theme_port.dart'; +import 'deposit_screen.dart'; +import 'kid_wallet_screen.dart'; + + +class HomeScreen extends StatelessWidget{ + final String name = "Juan"; + final double total = 95.03; + final List kids = [ + Kid(name:"Carlos", balance:25.47), + Kid(name:"Ana", balance:25.47), + ]; + late final double available = double.parse(kids.fold(total, (t, e) => t - e.balance).toStringAsFixed(2)); + + HomeScreen({super.key}); + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return SingleChildScrollView( child: Container( + color: theme.getColorFor(ThemeCode.background_secondary), + margin: EdgeInsets.all(30), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text.rich( + TextSpan( + text: "Hola, ", + style: TextStyle(fontSize: 25), + children: [ + TextSpan(text: name, style: TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ) + ), + walletsList(context, kids), + Align( + alignment: Alignment.topLeft, + child: TextButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>CreateProfileScreen())), + child: Text("+ Añadir otro peque", style: TextStyle( + fontWeight: FontWeight.bold, + color: theme.getColorFor(ThemeCode.text_primary) + )) + ) + ), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration(color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20))), + child: Column( + spacing: 5, + children: [ + Row( + children: [ + Text("Wallet", style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20 + )), + Spacer(), + MoneyText( + text: "$total€ total", + size: 25, + resize: true, + color: theme.getColorFor(ThemeCode.text_primary) + ) + ] + ), + Stack( + children: [ + LinearProgressIndicator( + value: available/total, + minHeight: 70, + borderRadius: BorderRadius.all(Radius.circular(16)), + color: theme.getColorFor(ThemeCode.button_primary), + backgroundColor: theme.getColorFor(ThemeCode.background_tertiary), + ), + FractionallySizedBox( + widthFactor: available/total, + child: Container( + padding: EdgeInsets.symmetric(vertical: 10), + child: Center( + child: MoneyText( + text: "$available€", + size: 35, + resize: true, + color: theme.getColorFor(ThemeCode.text_secondary) + ), + ) + ) + ), + ], + ), + Center(child: Text("Disponible")) + ], + ), + ), + DepositBlock(max: 150-total) + ] + ), + )); + } + + Widget walletsList(BuildContext context, List kids) { + final theme = context.read(); + + return Column( + spacing: 20, + children: List.generate(kids.length, (int index) { + return + GestureDetector( + onTap: ()=>{Navigator.push(context, MaterialPageRoute(builder: (_)=>KidWalletScreen(kid: kids[index])))}, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(16.0)), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 8), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: theme.getCardColorFor(index) + ) + ), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text(kids[index].name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + color: theme.getColorFor(ThemeCode.text_secondary) + ) + ) + ), + Row( + spacing: 10, + children: [ + SizedBox( + height: 60, + width: 60, + child: SvgPicture.asset("assets/images/ui/face.svg"), + ), + Spacer(), + Column(children: [ + MoneyText( + text: "${kids[index].balance}€", + size: 50, + resize: true, + color: theme.getColorFor(ThemeCode.text_secondary) + ), + Text("en su hucha", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))) + ]) + + ] + ), + Row( + children: [ + 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, color: theme.getColorFor(ThemeCode.text_secondary)), + Text("Editar", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))) + ] + ) + ), + Spacer(), + FilledButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>DepositScreen(kid: kids[index]))), + style: ButtonStyle( + backgroundColor: WidgetStatePropertyAll(theme.getColorFor(ThemeCode.button_secondary)), + ), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 0,vertical: 10), + child: Text("+ Añadir dinero") + ) + ) + ], + ) + ] + ), + ) + ) + ); + }) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/kid_wallet_screen.dart b/lib/payments/view/screens/kid_wallet_screen.dart index 084460f6..4679d7a6 100644 --- a/lib/payments/view/screens/kid_wallet_screen.dart +++ b/lib/payments/view/screens/kid_wallet_screen.dart @@ -1,7 +1,10 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/money_text.dart'; +import 'package:sf_app_platform/payments/view/screens/deposit_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/limits_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/wage_screen.dart'; import '../../domain/entities/kid.dart'; import '../../domain/ports/theme_port.dart'; @@ -61,8 +64,12 @@ class _KidWalletScreenState extends State { SizedBox(height: 30, child: SvgPicture.asset("assets/images/ui/face.svg")), ], ), - Text("${widget.kid.balance.toString()}€", - style: TextStyle(color: theme.getColorFor(ThemeCode.background_primary), fontSize: 35, fontWeight: FontWeight.bold)), + MoneyText( + text: "${widget.kid.balance.toString()}€", + size: 60, + resize: true, + color: theme.getColorFor(ThemeCode.text_secondary) + ), Text("Saldo disponible", style: TextStyle(color: theme.getColorFor(ThemeCode.background_primary))), LinearProgressIndicator( value: 0.7, @@ -71,57 +78,58 @@ class _KidWalletScreenState extends State { minHeight: 10, borderRadius: BorderRadius.all(Radius.circular(5)), ), - //Spacer(), - Center( child: Container( - padding: EdgeInsets.all(8), + Container( + padding: EdgeInsets.all(10), margin: EdgeInsets.only(top: 30), decoration: BoxDecoration( color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20)), ), - child: Row( + child: Expanded(child: Center( 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") - ] - ) + children: [ + TextButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>DepositScreen(kid: widget.kid))), + child: Column( + spacing: 10, + children: [ + Icon(Icons.add_circle_outline, color: theme.getColorFor(ThemeCode.text_primary)), + Text("Añadir", style: TextStyle(color: theme.getColorFor(ThemeCode.text_primary))) + ] ) - ], - ) + ), + Spacer(), + TextButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>WageScreen(kid: widget.kid))), + child: Column( + spacing: 10, + children: [ + Icon(Icons.account_balance_wallet_outlined, color: theme.getColorFor(ThemeCode.text_primary)), + Text("Paga", style: TextStyle(color: theme.getColorFor(ThemeCode.text_primary))) + ] + ) + ), + Spacer(), + TextButton(onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>LimitsScreen(kid: widget.kid))), + child: Column( + spacing: 10, + children: [ + Icon(Icons.list_alt_outlined, color: theme.getColorFor(ThemeCode.text_primary)), + Text("Límites", style: TextStyle(color: theme.getColorFor(ThemeCode.text_primary))) + ] + ) + ), + Spacer(), + TextButton(onPressed: ()=>{}, + child: Column( + spacing: 10, + children: [ + Icon(Icons.emoji_events_outlined, color: theme.getColorFor(ThemeCode.text_primary)), + Text("Metas", style: TextStyle(color: theme.getColorFor(ThemeCode.text_primary))) + ] + ) + ) + ], ) - ), + ))), Container( padding: EdgeInsets.all(15), height: 400, @@ -145,12 +153,11 @@ class _KidWalletScreenState extends State { } 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( + return Expanded(child: ListView( children: List.generate(activity.length, (int index) { return Column( spacing: 20, @@ -159,13 +166,16 @@ class _KidWalletScreenState extends State { Column( spacing: 15, children: List.generate((activity[index]["payments"] as List).length, (int i) { - var a = (activity[index]["payments"] as List)[i]; + //var a = (activity[index]["payments"] as List)[i]; return Row( - spacing: 5, + spacing: 7, children: [ Container( padding: EdgeInsets.all(9), - color: theme.getColorFor(ThemeCode.button_primary).withAlpha(0x1A), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_tertiary), + borderRadius: BorderRadius.all(Radius.circular(16)) + ), child: Icon(Icons.local_pizza_outlined, color: theme.getColorFor(ThemeCode.button_primary)), ), Column( @@ -175,13 +185,18 @@ class _KidWalletScreenState extends State { ], ), Spacer(), - Text("5.1€", style: TextStyle(fontWeight: FontWeight.bold)) + MoneyText( + text: "5.1€", + size: 20, + resize: true, + color: theme.getColorFor(ThemeCode.text_primary) + ) ], ); })) ], ); }) - ))); + )); } } \ No newline at end of file diff --git a/lib/payments/view/screens/limits_screen.dart b/lib/payments/view/screens/limits_screen.dart new file mode 100644 index 00000000..36fd5a51 --- /dev/null +++ b/lib/payments/view/screens/limits_screen.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/wallet_management_layout.dart'; + +import '../../domain/entities/kid.dart'; +import '../../domain/ports/theme_port.dart'; + +class LimitsScreen extends StatefulWidget{ + final Kid kid; + + const LimitsScreen({super.key, required this.kid}); + + @override + State createState() => LimitsScreenState(); +} + +class LimitsScreenState extends State{ + late List dailyLimits; + late List timeLimits; + late List conditions; + late List blocks; + + @override + void initState() { + super.initState(); + dailyLimits = [{"title": "Diario L-V", "limit": "5", "edit": false}, + {"title": "Fines de semana", "limit": "8", "edit": false}, + {"title": "Semanal", "limit": "30", "edit": false}, + {"title": "Mensual", "limit": "1200", "edit": false},]; + timeLimits = [{"title": "Lunes a Viernes", "start": "08:00", "end": "20:00", "edit": false}, + {"title": "Fines de semana", "start": "10:00", "end": "21:00", "edit": false}, + {"title": "Vacaciones", "start": "09:00", "end": "22:00", "edit": false}]; + conditions = [{"title": "Alimentación", "limit": "10", "edit": false}, + {"title": "Transporte", "limit": "10", "edit": false}, + {"title": "Alimentación", "limit": "10", "edit": false},]; + blocks = []; + } + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return WalletManagementLayout( + kid: widget.kid, + children: [ + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary), + ), + child: Column( + spacing: 10, + children: [ + Text("Pon límite de gastos", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Libertad para ellos, tranquilidad para ti"), + ...List.generate(dailyLimits.length, (int index) { + return Column(children: [ + Row(children: [ + Text("${dailyLimits[index]["title"]}: ${dailyLimits[index]["limit"]} €"), + Spacer(), + TextButton(onPressed: ()=>{setState(() { + dailyLimits[index]["edit"] = !dailyLimits[index]["edit"]; + })}, child: Text("Editar")) + ]), + if (dailyLimits[index]["edit"]) TextField() + ]); + }), + + ], + ), + ), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary), + ), + child: Column( + spacing: 10, + children: [ + Text("Horarios permitidos", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Controla cuándo pueden comprar"), + ...List.generate(timeLimits.length, (int index) { + return Column(children: [ + Row(children: [ + Text("${timeLimits[index]["title"]}: ${timeLimits[index]["start"]} - ${timeLimits[index]["end"]}"), + Spacer(), + TextButton(onPressed: ()=>{setState(() { + timeLimits[index]["edit"] = !timeLimits[index]["edit"]; + })}, child: Text("Editar")) + ]), + if (timeLimits[index]["edit"]) TextField() + ]); + }), + ], + ), + ) + ], + footer: Column(children: [ + FilledButton(onPressed: ()=>{}, child: SizedBox( + width: double.infinity, + child: Center(child: Text("Guardar límites")), + )) + ]), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/link_phone_screen.dart b/lib/payments/view/screens/link_phone_screen.dart index 3116ccde..d3000949 100644 --- a/lib/payments/view/screens/link_phone_screen.dart +++ b/lib/payments/view/screens/link_phone_screen.dart @@ -55,5 +55,4 @@ class LinkPhoneScreen extends StatelessWidget{ ) ); } - } \ No newline at end of file diff --git a/lib/payments/view/screens/link_watch/account_created_kid_screen.dart b/lib/payments/view/screens/link_watch/account_created_kid_screen.dart new file mode 100644 index 00000000..04a0512d --- /dev/null +++ b/lib/payments/view/screens/link_watch/account_created_kid_screen.dart @@ -0,0 +1,55 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/add_kid_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/core/dashboard_screen.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class AccountCreatedKidScreen extends StatelessWidget { + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + final model = "SaveWatch Plus 2"; + final id = "1106652524"; + final fullName = "Carlos Pérez Cruz"; + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_primary), + body: Container( + margin: EdgeInsets.all(30), + child: Center( + child: Column( + spacing: 20, + children: [ + Spacer(flex: 2), + Icon(Icons.check, color: theme.getColorFor(ThemeCode.background_primary), 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")) + ]) + ) + ], + ), + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/link_watch/create_profile_screen.dart b/lib/payments/view/screens/link_watch/create_profile_screen.dart new file mode 100644 index 00000000..e9a7db0b --- /dev/null +++ b/lib/payments/view/screens/link_watch/create_profile_screen.dart @@ -0,0 +1,168 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class CreateProfileScreen extends StatefulWidget { + const CreateProfileScreen({super.key}); + + @override + State createState() => CreateProfileScreenState(); + +} + +class CreateProfileScreenState extends State{ + int currentStep = 0; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_primary), + 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(theme.getColorFor(ThemeCode.button_primary))), + 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.") + ], + ) + ], + ) + ) + ] + ) + ], + ), + ), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/login_screen.dart b/lib/payments/view/screens/login_screen.dart index 2bf5efe5..1a426d89 100644 --- a/lib/payments/view/screens/login_screen.dart +++ b/lib/payments/view/screens/login_screen.dart @@ -1,8 +1,9 @@ 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/core/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'; +import 'package:sf_app_platform/payments/view/screens/signup/signup_screen.dart'; class LoginScreen extends StatefulWidget { @@ -87,7 +88,10 @@ class LoginScreenState extends State{ ], ), Text("¿No tienes cuenta?"), - TextButton(onPressed: ()=>{}, child: Text("Crear una ahora")) + TextButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>SignupScreen())), + child: Text("Crear una ahora") + ) ], ), ), diff --git a/lib/payments/view/screens/phone_code_screen.dart b/lib/payments/view/screens/phone_code_screen.dart index b745bb81..15b7e187 100644 --- a/lib/payments/view/screens/phone_code_screen.dart +++ b/lib/payments/view/screens/phone_code_screen.dart @@ -1,6 +1,6 @@ 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/core/dashboard_screen.dart'; import 'package:sf_app_platform/payments/view/screens/login_screen.dart'; class PhoneCodeScreen extends StatefulWidget { diff --git a/lib/payments/view/screens/profile_screen.dart b/lib/payments/view/screens/profile_screen.dart new file mode 100644 index 00000000..7dca5868 --- /dev/null +++ b/lib/payments/view/screens/profile_screen.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/activity_list.dart'; +import 'package:sf_app_platform/payments/view/screens/core/deposit_block.dart'; +import 'package:sf_app_platform/payments/view/screens/settings_screen.dart'; + +import '../../domain/ports/theme_port.dart'; +import 'core/line_graph.dart'; + +class ProfileScreen extends StatelessWidget{ + const ProfileScreen({super.key}); + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + final activity = [ + {"type": "goal"}, + {"type": "wage", "amount": 5}, + {"type": "lock"}, + {"type": "lock"} + ]; + + final name = "Juan"; + final total = 95.03; + final available = 44.09; + + final content = [ + Row( + children: [ + Text(name, style: TextStyle( + color: theme.getColorFor(ThemeCode.text_secondary), + fontWeight: FontWeight.bold, + fontSize: 30) + ), + Spacer(), + TextButton( + onPressed: ()=>Navigator.push(context, MaterialPageRoute(builder: (_)=>SettingsScreen())), + child: Text("Ajustes de la cuenta", style: TextStyle( + color: theme.getColorFor(ThemeCode.text_secondary)) + ) + ) + ], + ), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration(color: theme.getColorFor(ThemeCode.background_primary), borderRadius: BorderRadius.all(Radius.circular(20))), + child: Column( + spacing: 5, + children: [ + Row( + children: [ + Text("Wallet", style: TextStyle(fontWeight: FontWeight.bold),), + Spacer(), + Text("$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: theme.getColorFor(ThemeCode.text_secondary), fontSize: 20) + ) + ) + ) + ), + ], + ), + Center(child: Text("Disponible")) + ], + ), + ), + SizedBox( + height: 200, + child: LineGraph() + ), + DepositBlock(max: 150-total), + Row(), + ActivityList(activity: activity, edit: false) + ]; + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), + body: Stack(children: [ + DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(30)), + color: Color(0xFF4B4B4B) + ), + child: SizedBox(width: double.infinity, height: 200), + ), + Column(children: [Expanded (child: Container( + margin: EdgeInsets.fromLTRB(20, 20, 20, 0), + child: ListView.separated( + itemBuilder: (BuildContext context, int index) {return content[index];}, + separatorBuilder: (BuildContext context, int index) { + return Divider(color: Colors.transparent, height: 20); + }, + itemCount: content.length + ) + ))]), + ]) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/settings_screen.dart b/lib/payments/view/screens/settings_screen.dart new file mode 100644 index 00000000..4a5b8a1d --- /dev/null +++ b/lib/payments/view/screens/settings_screen.dart @@ -0,0 +1,231 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../domain/ports/theme_port.dart'; + +class SettingsScreen extends StatefulWidget{ + @override + State createState() => SettingsScreenState(); + +} + +class SettingsScreenState extends State{ + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + final name = "Juan"; + final balance = 50; + final fullName = "Juan Pérez Cruz"; + final birthDate = "08/03/1976"; + final relation = "Padre"; + final address = "Calle Gran Vía 30 6º, 28013"; + final country = "España"; + final nationality = "Español"; + final email = "juanpcruz@gmail.com"; + final phone = "123456789"; + + final content = [ + Center(child: Column(children: [ + Text("Ajustes de la cuenta", style: TextStyle(fontSize: 30, color: theme.getColorFor(ThemeCode.text_secondary))), + Text("Saldo: $balance€", style: TextStyle(color: theme.getColorFor(ThemeCode.text_secondary))), + ])), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column(children: [ + Row( + spacing: 10, + children: [ + Text(name, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar wallet")), + Icon(Icons.attach_money), + ], + ), + Text(relation) + ]), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column(children: [ + Row( + spacing: 10, + children: [ + Text("Datos personales", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar")) + ], + ), + Text.rich(TextSpan(text:"Nombre: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: fullName, style: TextStyle(fontWeight: FontWeight.normal)) + ])), + Text.rich(TextSpan(text:"Fecha de nacimiento: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: birthDate, style: TextStyle(fontWeight: FontWeight.normal)) + ])), + Text.rich(TextSpan(text:"Familiar: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: relation, style: TextStyle(fontWeight: FontWeight.normal)) + ])) + ]), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column(children: [ + Row( + spacing: 10, + children: [ + Text("Dirección", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar")) + ], + ), + Text.rich(TextSpan(text:"Dirección: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: address, style: TextStyle(fontWeight: FontWeight.normal)) + ])), + Text.rich(TextSpan(text:"País: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: country, style: TextStyle(fontWeight: FontWeight.normal)) + ])), + Text.rich(TextSpan(text:"Nacionalidad: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: nationality, style: TextStyle(fontWeight: FontWeight.normal)) + ])) + ]), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column(children: [ + Row( + spacing: 10, + children: [ + Text("Usuario", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar")) + ], + ), + Text.rich(TextSpan(text:"Correo: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: email, style: TextStyle(fontWeight: FontWeight.normal)) + ])), + Text.rich(TextSpan(text:"Teléfono: ", style: TextStyle(fontWeight: FontWeight.bold), + children: [TextSpan(text: phone, style: TextStyle(fontWeight: FontWeight.normal)) + ])) + ]), + ), + + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Row( + spacing: 10, + children: [ + Text("Cambio de contraseña", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar")) + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary) + ), + child: Column( + children: [ + Row( + spacing: 10, + children: [ + Text("Método de pago", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Editar")) + ], + ), + Text("Puedes cambiar el método de pago en cualquier momento") + ] + ) + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_tertiary) + ), + child: Column( + children: [ + Row( + spacing: 10, + children: [ + Text("Plan anual", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Spacer(), + TextButton(onPressed: ()=>{}, child: Text("Cambiar Plan")) + ], + ), + Text("Sin permanencia"), + Text("Llamadas y datos ilimitados"), + Text("2 meses gratis"), + ] + ) + ), + + TextButton(onPressed: ()=>{}, child: Text("Contáctanos")), + TextButton(onPressed: ()=>{}, child: Text("Preguntas frecuentes")), + ]; + + return Scaffold( + backgroundColor: theme.getColorFor(ThemeCode.background_secondary), + body: Stack(children: [ + DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(30)), + color: Color(0xFF4B4B4B) + ), + child: SizedBox(width: double.infinity, height: 200), + ), + Column(children: [Expanded (child: Container( + margin: EdgeInsets.all(20), + child: ListView.separated( + itemBuilder: (BuildContext context, int index) {return content[index];}, + separatorBuilder: (BuildContext context, int index) { + return Divider(color: Colors.transparent, height: 20); + }, + itemCount: content.length))), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)), + color: theme.getColorFor(ThemeCode.background_primary), + ), + child: Column( + children: [ + FilledButton(onPressed: ()=>{}, child: Container( + width: double.infinity, + padding: EdgeInsets.all(20), + child: Center(child: Text("Guardar cambios")) + )), + TextButton(onPressed: ()=>Navigator.pop(context), child: Text("Cancelar")) + ], + ), + ), + ]) + ]) + ); + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup/signup_address_screen.dart b/lib/payments/view/screens/signup/signup_address_screen.dart new file mode 100644 index 00000000..d2c713ed --- /dev/null +++ b/lib/payments/view/screens/signup/signup_address_screen.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +class SignupAddressScreen extends StatelessWidget{ + + @override + Widget build(BuildContext context) { + return Column( + spacing: 30, + children: [ + Text("Domicilio"), + Text("Tu dirección", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30)), + 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( + dropdownMenuEntries: List.generate(3, (int index) { + return DropdownMenuEntry(value: "España", label: "España"); + }), + hintText: "País", + width: double.infinity, + ), + TextField(decoration: InputDecoration(hintText: "Nacionalidad", border: OutlineInputBorder())) + ], + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup/signup_personal_screen.dart b/lib/payments/view/screens/signup/signup_personal_screen.dart new file mode 100644 index 00000000..1e3aecb0 --- /dev/null +++ b/lib/payments/view/screens/signup/signup_personal_screen.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class SignupPersonalScreen extends StatelessWidget{ + const SignupPersonalScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + spacing: 30, + 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"), + ], + ), + ], + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup/signup_screen.dart b/lib/payments/view/screens/signup/signup_screen.dart new file mode 100644 index 00000000..cded314a --- /dev/null +++ b/lib/payments/view/screens/signup/signup_screen.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.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/signup/signup_address_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/signup/signup_personal_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/signup/signup_user_screen.dart'; + +import '../../../domain/ports/theme_port.dart'; + +class SignupScreen extends StatefulWidget { + const SignupScreen({super.key}); + + @override + _SignupScreenState createState() => _SignupScreenState(); +} + +class _SignupScreenState extends State { + int currentStep = 0; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return MaterialApp( + home: Scaffold( + body: Center(child: Container( + color: theme.getColorFor(ThemeCode.background_primary), + padding: const EdgeInsets.all(20), + child: SizedBox( + child: Stepper( + controlsBuilder: (BuildContext context, ControlsDetails controls) { + return Row( + children: [ + Expanded(child: OutlinedButton( + onPressed: controls.onStepCancel, + child: const Text('Atrás'), + )), + Expanded(child: FilledButton( + style: ButtonStyle( + backgroundColor: WidgetStatePropertyAll(theme.getColorFor(ThemeCode.button_secondary)) + ), + 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(), + ) + )), + )), + ); + } + + List getSteps() { + return [ + 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() + ), + 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() + ), + 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() + ), + ]; + } +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup/signup_user_screen.dart b/lib/payments/view/screens/signup/signup_user_screen.dart new file mode 100644 index 00000000..1b9da81f --- /dev/null +++ b/lib/payments/view/screens/signup/signup_user_screen.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; + +class SignupUserScreen extends StatefulWidget{ + const SignupUserScreen({super.key}); + + @override + State createState() => SignupUserScreenState(); +} + +class SignupUserScreenState extends State{ + bool passwordVisible=false; + + @override + Widget build(BuildContext context) { + return Column( + spacing: 30, + 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.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; + }); + }, + ), + ) + ), + 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; + }); + }, + ), + ) + ), + ], + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/signup_screen.dart b/lib/payments/view/screens/signup_screen.dart deleted file mode 100644 index bde99726..00000000 --- a/lib/payments/view/screens/signup_screen.dart +++ /dev/null @@ -1,208 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:sf_app_platform/payments/view/screens/account_created_screen.dart'; - -class SignupScreen extends StatefulWidget { - const SignupScreen({super.key}); - - @override - _SignupScreenState createState() => _SignupScreenState(); -} - -class _SignupScreenState extends State { - int currentStep = 0; - bool passwordVisible=false; - - @override - void initState(){ - super.initState(); - passwordVisible=true; - } - @override - Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - body: Center(child: Container( - padding: const EdgeInsets.all(20), - child: SizedBox( - child: Stepper( - controlsBuilder: (BuildContext context, ControlsDetails controls) { - return Row( - children: [ - OutlinedButton( - onPressed: controls.onStepCancel, - child: const Text('Atrás'), - ), - FilledButton( - 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(), - ) - )), - )), - ); - } - - List getSteps() { - return [ - 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: Column( - spacing: 30, - children: [ - 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", 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"), - ], - ), - ], - ), - ), - 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: Column( - spacing: 30, - children: [ - 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", border: OutlineInputBorder())), - TextField(decoration: InputDecoration(hintText: "Ciudad", border: OutlineInputBorder())), - DropdownMenu( - dropdownMenuEntries: List.generate(3, (int index) { - return DropdownMenuEntry(value: "España", label: "España"); - }), - hintText: "País", - width: double.infinity, - ), - TextField(decoration: InputDecoration(hintText: "Nacionalidad", border: OutlineInputBorder())) - ], - ), - ), - 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: Column( - spacing: 30, - children: [ - 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", border: OutlineInputBorder())), - 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( - 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; - }); - }, - ), - ) - ), - 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; - }); - }, - ), - ) - ), - ], - ), - ), - ]; - } -} \ No newline at end of file diff --git a/lib/payments/view/screens/wage_screen.dart b/lib/payments/view/screens/wage_screen.dart new file mode 100644 index 00000000..dd114c0f --- /dev/null +++ b/lib/payments/view/screens/wage_screen.dart @@ -0,0 +1,197 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import 'package:sf_app_platform/payments/view/screens/core/wallet_management_layout.dart'; + +import '../../domain/entities/kid.dart'; +import '../../domain/ports/theme_port.dart'; + +class WageScreen extends StatefulWidget{ + final Kid kid; + + const WageScreen({super.key, required this.kid}); + + @override + State createState() => WageScreenState(); + +} + +class WageScreenState extends State{ + String frequence = "weekly"; + var conditions = {"weeklyLimits": false, "incidences": false, "holidays": false}; + + @override + Widget build(BuildContext context) { + ThemePort theme = context.read(); + + return WalletManagementLayout( + kid: widget.kid, + children: [ + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Paga automática", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + TextField( + decoration: InputDecoration(labelText: "Cantidad", hintText: "0€", border: OutlineInputBorder()), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ] + ), + Text("Saldo total disponible después: 30 €") + ], + ), + ), + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Frecuencia", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Cuándo se envía el dinero"), + CheckboxListTile( + title: Text('Semanal'), + controlAffinity: ListTileControlAffinity.leading, + value: frequence=="weekly", + onChanged: (value) { + setState(() { + frequence="weekly"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Cada dos semanas'), + controlAffinity: ListTileControlAffinity.leading, + value: frequence=="biweekly", + onChanged: (value) { + setState(() { + frequence="biweekly"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Mensual'), + controlAffinity: ListTileControlAffinity.leading, + value: frequence=="monthly", + onChanged: (value) { + setState(() { + frequence="monthly"; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + Container(width: double.infinity, child: DropdownMenu( + label: Text("Día de la semana"), + initialSelection: "Domingo", + dropdownMenuEntries: List.generate(7, (int index){ + final days = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"]; + return DropdownMenuEntry(value: days[index], label: days[index]); + }) + )), + DropdownMenu( + label: Text("Hora del día"), + initialSelection: 9, + dropdownMenuEntries: List.generate(24, (int index){ + return DropdownMenuEntry(value: index, label: "$index:00"); + }) + ), + TextField( + minLines: 3, + maxLines: 3, + maxLength: 150, + decoration: InputDecoration( + labelText: "Escribir mensaje a ${widget.kid.name} del motivo del ingreso", + hintText: "Escribe tu mensaje", + border: OutlineInputBorder(), + ) + ), + Align( + alignment: Alignment.topLeft, + child: Text("Máximo 150 caracteres"), + ) + ], + ), + ), + Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + padding: EdgeInsets.all(10), + child: Column( + spacing: 10, + children: [ + Text("Condiciones", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + Text("Este dato aparecerá en el reloj del peque"), + CheckboxListTile( + title: Text('Sólo si cumple límites semanales'), + controlAffinity: ListTileControlAffinity.leading, + value: conditions["weeklyLimits"], + onChanged: (value) { + setState(() { + conditions["weeklyLimits"] = !conditions["weeklyLimits"]!; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Sólo si no ha tenido incidencias'), + controlAffinity: ListTileControlAffinity.leading, + value: conditions["incidences"], + onChanged: (value) { + setState(() { + conditions["incidences"] = !conditions["incidences"]!; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + CheckboxListTile( + title: Text('Pausar durante vacaciones'), + controlAffinity: ListTileControlAffinity.leading, + value: conditions["holidays"], + onChanged: (value) { + setState(() { + conditions["holidays"] = !conditions["holidays"]!; + }); + }, + activeColor: theme.getColorFor(ThemeCode.button_primary), + ), + ], + ), + ), + ], + footer: Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.background_primary), + borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)) + ), + child: Column( + spacing: 10, + children: [ + FilledButton(onPressed: ()=>{}, child: Container( + width:double.infinity, + padding: EdgeInsets.all(20), + child: Center(child: Text("Activar paga automática")) + )), + TextButton(onPressed: ()=>{}, child: Text("Cancelar")) + ], + ), + ) + ); + } + +} \ No newline at end of file diff --git a/lib/payments/view/screens/wallet_management_screen.dart b/lib/payments/view/screens/wallet_management_screen.dart deleted file mode 100644 index 8e185e8f..00000000 --- a/lib/payments/view/screens/wallet_management_screen.dart +++ /dev/null @@ -1,63 +0,0 @@ -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 diff --git a/lib/payments/view/screens/welcome_screen.dart b/lib/payments/view/screens/welcome_screen.dart index ba1b1485..cc3a3dcb 100644 --- a/lib/payments/view/screens/welcome_screen.dart +++ b/lib/payments/view/screens/welcome_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:sf_app_platform/payments/view/screens/link_phone_screen.dart'; -import 'package:sf_app_platform/payments/view/screens/signup_screen.dart'; +import 'package:sf_app_platform/payments/view/screens/signup/signup_screen.dart'; -import 'dashboard_screen.dart'; +import 'core/dashboard_screen.dart'; class WelcomeScreen extends StatelessWidget { const WelcomeScreen({super.key}); diff --git a/pubspec.lock b/pubspec.lock index 692a1ac5..4350a545 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + url: "https://pub.dev" + source: hosted + version: "85.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d" + url: "https://pub.dev" + source: hosted + version: "7.7.1" args: dependency: transitive description: @@ -33,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" clock: dependency: transitive description: @@ -49,6 +73,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" cupertino_icons: dependency: "direct main" description: @@ -57,6 +105,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + equatable: + dependency: transitive + description: + name: equatable + sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + url: "https://pub.dev" + source: hosted + version: "2.0.7" fake_async: dependency: transitive description: @@ -65,6 +121,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9" + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -78,6 +150,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "9e2d6907f12cc7d23a846847615941bddee8709bf2bfd274acdf5e80bcf22fde" + url: "https://pub.dev" + source: hosted + version: "3.0.3" flutter_svg: dependency: "direct main" description: @@ -91,6 +171,22 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" http: dependency: transitive description: @@ -99,6 +195,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" http_parser: dependency: transitive description: @@ -107,6 +211,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" leak_tracker: dependency: transitive description: @@ -139,6 +259,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: @@ -163,6 +291,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" nested: dependency: transitive description: @@ -171,6 +307,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" path: dependency: transitive description: @@ -195,6 +347,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" provider: dependency: "direct main" description: @@ -203,11 +363,75 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.5+1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: c406de02bff19d920b832bddfb8283548bfa05ce41c59afba57ce643e116aa59 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: @@ -224,6 +448,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -248,6 +480,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" + url: "https://pub.dev" + source: hosted + version: "1.26.2" test_api: dependency: transitive description: @@ -256,6 +496,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.6" + test_core: + dependency: transitive + description: + name: test_core + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" + url: "https://pub.dev" + source: hosted + version: "0.6.11" typed_data: dependency: transitive description: @@ -304,6 +552,14 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" + url: "https://pub.dev" + source: hosted + version: "1.1.4" web: dependency: transitive description: @@ -312,6 +568,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" xml: dependency: transitive description: @@ -320,6 +600,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.9.2 <4.0.0" flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8adf42c5..576b594f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,8 @@ dependencies: flutter: sdk: flutter provider: ^6.1.5+1 + flutter_riverpod: ^3.0.3 + fl_chart: ^1.1.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.