- create auth, main shell, home, profile, notifications and settings modules.
- added navigation, utils, design system and shared packages - implemented go router in entiered app - implemented flutter riverpod instead provider
This commit is contained in:
31
modules/auth/.gitignore
vendored
Normal file
31
modules/auth/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
modules/auth/.metadata
Normal file
10
modules/auth/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
modules/auth/CHANGELOG.md
Normal file
3
modules/auth/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
modules/auth/LICENSE
Normal file
1
modules/auth/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
39
modules/auth/README.md
Normal file
39
modules/auth/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
4
modules/auth/analysis_options.yaml
Normal file
4
modules/auth/analysis_options.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
6
modules/auth/lib/auth.dart
Normal file
6
modules/auth/lib/auth.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
export 'src/device_sign_up/link_watch/create_profile_screen.dart';
|
||||
export 'src/onboarding/onboarding_builder.dart';
|
||||
export 'src/login/link_phone_builder.dart';
|
||||
export 'src/login/phone_code_builder.dart';
|
||||
export 'src/login/login_builder.dart';
|
||||
export 'src/recover_password/recover_password_builder.dart';
|
||||
57
modules/auth/lib/src/device_sign_up/add_kid_screen.dart
Normal file
57
modules/auth/lib/src/device_sign_up/add_kid_screen.dart
Normal file
@@ -0,0 +1,57 @@
|
||||
import 'package:auth/src/device_sign_up/link_watch/create_profile_screen.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.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 {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Column(
|
||||
spacing: 15,
|
||||
children: [
|
||||
Spacer(flex: 6),
|
||||
Text("Añade a tu peque"),
|
||||
Text(
|
||||
"Controla su gasto a la vez que aprende hábitos financieros responsables",
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 30, horizontal: 50),
|
||||
child: Row(
|
||||
children: [
|
||||
Column(children: [Text("1"), Text("2"), Text("3")]),
|
||||
Column(
|
||||
children: [
|
||||
Text("Crea su perfil"),
|
||||
Text("Vincula su correa y su reloj"),
|
||||
Text("Carga su hucha"),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("¡Y todo listo para que tenga su dinero!"),
|
||||
Text("Recuerda que necesitas tener un Plan SaveFamily"),
|
||||
Text(
|
||||
"Si aún no lo tienes, puedes conseguirlo a través de nuestra web",
|
||||
),
|
||||
Spacer(flex: 8),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => CreateProfileScreen()),
|
||||
),
|
||||
child: Text("¡Empezar!"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
79
modules/auth/lib/src/device_sign_up/contact_screen.dart
Normal file
79
modules/auth/lib/src/device_sign_up/contact_screen.dart
Normal file
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ContactScreen extends StatelessWidget {
|
||||
const ContactScreen({super.key});
|
||||
|
||||
@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"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:auth/src/device_sign_up/add_kid_screen.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class AccountCreatedKidScreen extends ConsumerWidget {
|
||||
const AccountCreatedKidScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final model = "SaveWatch Plus 2";
|
||||
final id = "1106652524";
|
||||
final fullName = "Carlos Pérez Cruz";
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(flex: 2),
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
size: 50,
|
||||
),
|
||||
Text(
|
||||
"Cuenta creada",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Has creado la cuenta para:\n",
|
||||
children: [
|
||||
TextSpan(
|
||||
text: fullName,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Reloj: $model"),
|
||||
Text("ID del reloj: $id"),
|
||||
Text(
|
||||
"Ya puedes darle su primera paga paa que empiece a disfrutarla en su reloj",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Spacer(flex: 6),
|
||||
Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(20),
|
||||
topLeft: Radius.circular(20),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () => {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => AddKidScreen()),
|
||||
),
|
||||
},
|
||||
child: Text("Dale su primera paga"),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Text("Añadir otro peque"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class CreateProfileScreen extends ConsumerWidget {
|
||||
CreateProfileScreen({super.key});
|
||||
|
||||
int currentStep = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Stepper(
|
||||
type: StepperType.horizontal,
|
||||
currentStep: currentStep,
|
||||
onStepCancel: () => currentStep == 0,
|
||||
// ? null
|
||||
// :
|
||||
// setState(() {
|
||||
// currentStep -= 1;
|
||||
// }),
|
||||
controlsBuilder:
|
||||
(BuildContext context, ControlsDetails controls) {
|
||||
return FilledButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
),
|
||||
onPressed: controls.onStepContinue,
|
||||
child: const Text('Continuar'),
|
||||
);
|
||||
},
|
||||
steps: [
|
||||
Step(
|
||||
state: currentStep > 0
|
||||
? StepState.complete
|
||||
: StepState.indexed,
|
||||
isActive: currentStep >= 0,
|
||||
stepStyle: currentStep >= 0
|
||||
? StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Color(0xFF329e95),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
)
|
||||
: StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Colors.transparent,
|
||||
boxShadow: BoxShadow(spreadRadius: 5),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
),
|
||||
title: Text(""),
|
||||
content: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"Crea su perfil",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Necesitamos estos datos para crear su cuenta y gestionar sus pagas y gastos",
|
||||
),
|
||||
Text(
|
||||
"Comienza con un peque; luego podrás agregar más",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Nombre",
|
||||
hintText: "Nombre",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Apellidos",
|
||||
hintText: "Apellidos",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
label: Text("Fecha de nacimiento"),
|
||||
hintText: "DD",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "MM",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "AAAA",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Dirección completa",
|
||||
hintText: "Nombre de la calle",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Text(
|
||||
"Cambiar dirección",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Step(
|
||||
state: currentStep > 1
|
||||
? StepState.complete
|
||||
: StepState.indexed,
|
||||
isActive: currentStep >= 1,
|
||||
stepStyle: currentStep >= 1
|
||||
? StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Color(0xFF329e95),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
)
|
||||
: StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Colors.transparent,
|
||||
boxShadow: BoxShadow(spreadRadius: 5),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
),
|
||||
title: Text(""),
|
||||
content: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"Vincula su correa y su reloj",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
SvgPicture.asset("assets/images/ui/formulario.svg"),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text("1"),
|
||||
Column(
|
||||
children: [
|
||||
Text("Escanea la correa"),
|
||||
Text("El peque podrá realizar pagos"),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text("2"),
|
||||
Column(
|
||||
children: [
|
||||
Text("Escanea el reloj"),
|
||||
Text("Visualizarás los gastos que se hagan"),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Step(
|
||||
state: currentStep > 2
|
||||
? StepState.complete
|
||||
: StepState.indexed,
|
||||
isActive: currentStep >= 2,
|
||||
stepStyle: currentStep >= 2
|
||||
? StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Color(0xFF329e95),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
)
|
||||
: StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Colors.transparent,
|
||||
boxShadow: BoxShadow(spreadRadius: 5),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
),
|
||||
title: Text(""),
|
||||
content: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"¡Dale su primera paga!",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 30,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Enséñales a gestionar su dinero recargando su reloj",
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Cantidad de dinero de la paga",
|
||||
hintText: "0€",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
Text("Cantidad mínima: 10€"),
|
||||
Text(
|
||||
"Por seguridad sólo se puede disponer de un máximo de 150€ por wallet",
|
||||
),
|
||||
Text("Método de ingreso"),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: SvgPicture.asset(
|
||||
"assets/images/ui/visa.svg",
|
||||
),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: SvgPicture.asset(
|
||||
"assets/images/ui/paypal.svg",
|
||||
),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
"assets/images/ui/banco.svg",
|
||||
),
|
||||
Text("Transferencia"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.lock_outline),
|
||||
Text(
|
||||
"EL pago en esta app es seguro y cumple la normativa europea. Sólo se usará el dinero que decidas para las huchas de tus hijos.",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
modules/auth/lib/src/login/link_phone_builder.dart
Normal file
18
modules/auth/lib/src/login/link_phone_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/login/presentation/link_phone_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class LinkPhoneBuilder {
|
||||
const LinkPhoneBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: LinkPhoneScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
modules/auth/lib/src/login/login_builder.dart
Normal file
18
modules/auth/lib/src/login/login_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/login/presentation/login_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class LoginBuilder {
|
||||
const LoginBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: LoginScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
modules/auth/lib/src/login/phone_code_builder.dart
Normal file
18
modules/auth/lib/src/login/phone_code_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/login/presentation/phone_code_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class PhoneCodeBuilder {
|
||||
const PhoneCodeBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: PhoneCodeScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class LinkPhoneScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const LinkPhoneScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
TextEditingController phoneController = TextEditingController();
|
||||
// String? phone;
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"¡Nos alegra mucho tenerte por aquí!",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
"Para poder entrar de forma segura, te vamos a enviar un código al teléfono",
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
initialSelection: "es",
|
||||
dropdownMenuEntries: List<DropdownMenuEntry>.generate(3, (
|
||||
int index,
|
||||
) {
|
||||
return DropdownMenuEntry(
|
||||
labelWidget: Icon(Icons.outlined_flag),
|
||||
label: "es",
|
||||
value: "es",
|
||||
);
|
||||
}),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
onSubmitted: (String value) {
|
||||
// phone = value;
|
||||
},
|
||||
controller: phoneController,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Teléfono móvil",
|
||||
hintText: "Teléfono",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
onPressed: () => navigationContract.pushTo('/phone_code'),
|
||||
child: Text("Siguiente"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class LoadingGoogleScreen extends StatelessWidget {
|
||||
const LoadingGoogleScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 50,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Continuar con Google",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
CircularProgressIndicator(),
|
||||
Text("Redirigiendo a Google"),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
25
modules/auth/lib/src/login/presentation/loading_screen.dart
Normal file
25
modules/auth/lib/src/login/presentation/loading_screen.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class LoadingScreen extends StatelessWidget{
|
||||
const LoadingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 50,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
SvgPicture.asset("assets/images/ui/logo_sf.svg"),
|
||||
CircularProgressIndicator(),
|
||||
Spacer(flex: 10)
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
107
modules/auth/lib/src/login/presentation/login_screen.dart
Normal file
107
modules/auth/lib/src/login/presentation/login_screen.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
import 'package:auth/src/login/presentation/loading_google_screen.dart';
|
||||
import 'package:auth/src/recover_password/presentation/restore_password_screen.dart';
|
||||
import 'package:auth/src/sign_up/signup_screen.dart';
|
||||
import 'package:dashboard_shell/dashboard_shell.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.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 ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const LoginScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
bool passwordVisible = true;
|
||||
return Scaffold(
|
||||
body: Expanded(
|
||||
child: Center(
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(Icons.check, color: Color(0xFF329e95), size: 50),
|
||||
Text(
|
||||
"¡Te damos la bienvenida!",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Nombre de usuario",
|
||||
labelText: "Nombre de usuario",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
obscureText: passwordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Contraseña",
|
||||
hintText: "********",
|
||||
border: OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
passwordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
// setState(() {
|
||||
// passwordVisible = !passwordVisible;
|
||||
// });
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
navigationContract.pushTo('/recover_password'),
|
||||
child: Text("¿Has olvidado la contraseña?"),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () =>
|
||||
navigationContract.pushTo('/dashboard_shell'),
|
||||
child: Text("Iniciar sesión"),
|
||||
),
|
||||
Stack(children: [Divider(), Text("o continúa con")]),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
OutlinedButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => LoadingGoogleScreen(),
|
||||
),
|
||||
),
|
||||
child: Text("Google", semanticsLabel: "Google"),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: Icon(Icons.apple, semanticLabel: "Apple"),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text("¿No tienes cuenta?"),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => SignupScreen()),
|
||||
),
|
||||
child: Text("Crear una ahora"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import 'package:auth/src/login/presentation/login_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/core/dashboard_screen.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/login_screen.dart';
|
||||
|
||||
class PhoneCodeScreen extends ConsumerWidget {
|
||||
// final String phone;
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
PhoneCodeScreen({super.key, required this.navigationContract});
|
||||
// const PhoneCodeScreen({super.key, required this.phone});
|
||||
|
||||
// class PhoneCodeScreenState extends State<PhoneCodeScreen> {
|
||||
final focusNodes = List<FocusNode>.generate(6, (int i) {
|
||||
return FocusNode();
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 15,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Conéctate",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Hemos enviado el código al ",
|
||||
children: [
|
||||
TextSpan(
|
||||
// text: widget.phone,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text("Introduce el código aquí"),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: List<Widget>.generate(6, (int i) {
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
focusNode: focusNodes[i],
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: "0",
|
||||
counterText: "",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
maxLength: 1,
|
||||
onChanged: (String value) => {
|
||||
value != ""
|
||||
? focusNodes[i + 1].requestFocus()
|
||||
: focusNodes[i - 1].requestFocus(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => {navigationContract.pushTo('/login')},
|
||||
child: Text("Entrar"),
|
||||
),
|
||||
Text("¿No lo has recibido?"),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Text(
|
||||
"Volver a intentarlo",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
modules/auth/lib/src/onboarding/onboarding_builder.dart
Normal file
18
modules/auth/lib/src/onboarding/onboarding_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/onboarding/presentation/welcome_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class OnboardingBuilder {
|
||||
const OnboardingBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: WelcomeScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
// import 'package:sf_app_platform/payments/view/screens/link_phone_screen.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/signup/signup_screen.dart';
|
||||
|
||||
// import '../../../../../apps/mobile_app/lib/payments/view/screens/core/dashboard_screen.dart';
|
||||
|
||||
class WelcomeScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const WelcomeScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Spacer(),
|
||||
Expanded(
|
||||
child: CarouselView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemExtent: double.infinity,
|
||||
itemSnapping: true,
|
||||
shrinkExtent: 400,
|
||||
children: generateSteps(),
|
||||
),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => navigationContract.goTo('/link_phone'),
|
||||
child: const Text('Continuar'),
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void jumpToNext(BuildContext context) {
|
||||
// Navigator.pushReplacement(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (_) => LinkPhoneScreen()),
|
||||
// );
|
||||
return;
|
||||
}
|
||||
|
||||
List<Widget> generateSteps() {
|
||||
return [
|
||||
Column(
|
||||
spacing: 30,
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/ui/bienvenida_paso1.svg"),
|
||||
Text(
|
||||
"Aprende a gestionar su dinero",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
),
|
||||
Text("Tu peque crea hábitos y se divierte mientras lo hace"),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/ui/bienvenida_paso2.svg"),
|
||||
Text("Tranquilidad en cada pago que hacen"),
|
||||
Text("Supervisa gastos, fija límites y acompáñalos en cada paso"),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
SvgPicture.asset("assets/images/ui/bienvenida_paso3.svg"),
|
||||
Text("Pagos fáciles y seguros en sus manos"),
|
||||
Text("Podrá pagar desde su reloj.\n Sin móvil ni efectivo"),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'package:auth/src/recover_password/presentation/new_password_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// import 'package:sf_app_platform/payments/domain/ports/theme_port.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/restore_password/new_password_screen.dart';
|
||||
|
||||
class EmailSentScreen extends StatefulWidget {
|
||||
final String email;
|
||||
|
||||
const EmailSentScreen({super.key, required this.email});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => EmailSentScreenState();
|
||||
}
|
||||
|
||||
class EmailSentScreenState extends State<EmailSentScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.read<ThemePort>();
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Text(
|
||||
"Correo enviado correctamente",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
Text(
|
||||
"Revisa tu email y haz clic en el enlace para crear una nueva contraseña",
|
||||
),
|
||||
Text(
|
||||
"Si no recibes el correo en unos minutos, revisa tu carpeta de spam o pulsa \"Reenviar correo\"",
|
||||
),
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () => {},
|
||||
child: Text("Reenviar correo"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => NewPasswordScreen(),
|
||||
),
|
||||
),
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
child: Text("Continuar"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// import '../../../domain/ports/theme_port.dart';
|
||||
|
||||
class NewPasswordScreen extends StatefulWidget {
|
||||
const NewPasswordScreen({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => NewPasswordScreenState();
|
||||
}
|
||||
|
||||
class NewPasswordScreenState extends State<NewPasswordScreen> {
|
||||
bool passwordVisible = false;
|
||||
bool equalPasswords = false;
|
||||
String password = "";
|
||||
var securityChecks = {
|
||||
"min": false,
|
||||
"capital": false,
|
||||
"number": false,
|
||||
"special": false,
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
passwordVisible = false;
|
||||
equalPasswords = false;
|
||||
String password = "";
|
||||
securityChecks = {
|
||||
"min": false,
|
||||
"capital": false,
|
||||
"number": false,
|
||||
"special": false,
|
||||
};
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.read<ThemePort>();
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Spacer(flex: 4),
|
||||
Text(
|
||||
"Recuperar contraseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
TextField(
|
||||
obscureText: passwordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Nueva contraseña",
|
||||
hintText: "********",
|
||||
border: OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
passwordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
passwordVisible = !passwordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
password = value;
|
||||
securityChecks = checkSecurity(value);
|
||||
}),
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
obscureText: passwordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Repetir contraseña",
|
||||
hintText: "********",
|
||||
border: OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
passwordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
passwordVisible = !passwordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: (value) => {
|
||||
setState(() {
|
||||
equalPasswords = password == value;
|
||||
}),
|
||||
},
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["min"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Al menos 8 caracteres"),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["capital"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Una mayúscula"),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["number"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un número"),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
securityChecks["special"]!
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
)
|
||||
: Icon(
|
||||
Icons.cancel_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
Text("Un carácter especial"),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 1),
|
||||
FilledButton(
|
||||
onPressed: () => {},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text("Aceptar"),
|
||||
),
|
||||
),
|
||||
Spacer(flex: 4),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: Extraer de la vista
|
||||
Map<String, bool> checkSecurity(String value) {
|
||||
Map<String, bool> checks = {};
|
||||
|
||||
checks["min"] = value.length >= 8;
|
||||
checks["capital"] = RegExp(r'[A-Z]').hasMatch(value);
|
||||
checks["number"] = RegExp(r'[0-9]').hasMatch(value);
|
||||
checks["special"] = RegExp(r'[^A-Za-z0-9]').hasMatch(value);
|
||||
|
||||
return checks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'package:auth/src/recover_password/presentation/email_sent_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
// import 'package:sf_app_platform/payments/domain/ports/theme_port.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/restore_password/email_sent_screen.dart';
|
||||
|
||||
class RestorePasswordScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const RestorePasswordScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
// ThemePort theme = context.read<ThemePort>();
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 30,
|
||||
children: [
|
||||
Spacer(flex: 8),
|
||||
Text(
|
||||
"Recuperar contaseña",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
|
||||
),
|
||||
Text(
|
||||
"Introduce tu email para enviarte un enlace de recuperación",
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Correo electrónico",
|
||||
hintText: "Correo electrónico",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () => {Navigator.pop(context)},
|
||||
child: Text("Volver"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
onPressed: () => {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => EmailSentScreen(email: ""),
|
||||
),
|
||||
),
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
child: Text("Enviar"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(flex: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:auth/src/recover_password/presentation/restore_password_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class RecoverPasswordBuilder {
|
||||
const RecoverPasswordBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: RestorePasswordScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
78
modules/auth/lib/src/sign_up/account_created_screen.dart
Normal file
78
modules/auth/lib/src/sign_up/account_created_screen.dart
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'package:auth/src/device_sign_up/add_kid_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
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 '../../../../../apps/mobile_app/lib/payments/domain/ports/theme_port.dart';
|
||||
|
||||
class AccountCreatedScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ThemePort theme = context.read<ThemePort>();
|
||||
|
||||
final email = "usuario@example.com";
|
||||
final fullName = "Carlos Pérez Cruz";
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Center(
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Spacer(flex: 10),
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
size: 50,
|
||||
),
|
||||
Text(
|
||||
"Cuenta creada",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Has creado la cuenta para:\n",
|
||||
children: [
|
||||
TextSpan(
|
||||
text: fullName,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text.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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
27
modules/auth/lib/src/sign_up/signup_address_screen.dart
Normal file
27
modules/auth/lib/src/sign_up/signup_address_screen.dart
Normal file
@@ -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<DropdownMenuEntry>.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()))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
49
modules/auth/lib/src/sign_up/signup_personal_screen.dart
Normal file
49
modules/auth/lib/src/sign_up/signup_personal_screen.dart
Normal file
@@ -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"),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
140
modules/auth/lib/src/sign_up/signup_screen.dart
Normal file
140
modules/auth/lib/src/sign_up/signup_screen.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'package:auth/src/sign_up/account_created_screen.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:sf_app_platform/payments/view/screens/account_created_screen.dart';
|
||||
import 'package:auth/src/sign_up/signup_address_screen.dart';
|
||||
import 'package:auth/src/sign_up/signup_personal_screen.dart';
|
||||
import 'package:auth/src/sign_up/signup_user_screen.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
// import '../../../../../apps/mobile_app/lib/payments/domain/ports/theme_port.dart';
|
||||
|
||||
class SignupScreen extends ConsumerWidget {
|
||||
SignupScreen({super.key});
|
||||
|
||||
int currentStep = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
child: Container(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: SizedBox(
|
||||
child: Stepper(
|
||||
controlsBuilder:
|
||||
(BuildContext context, ControlsDetails controls) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: controls.onStepCancel,
|
||||
child: const Text('Atrás'),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FilledButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
onPressed: controls.onStepContinue,
|
||||
child: const Text('Siguiente'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
type: StepperType.horizontal,
|
||||
currentStep: currentStep,
|
||||
onStepCancel: () => currentStep == 0,
|
||||
// ? null
|
||||
// : setState(() {
|
||||
// currentStep -= 1;
|
||||
// }),
|
||||
onStepContinue: () {
|
||||
bool isLastStep = (currentStep == getSteps().length - 1);
|
||||
if (isLastStep) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => AccountCreatedScreen()),
|
||||
);
|
||||
} else {
|
||||
// setState(() {
|
||||
// currentStep += 1;
|
||||
// });
|
||||
}
|
||||
},
|
||||
steps: getSteps(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Step> getSteps() {
|
||||
return <Step>[
|
||||
Step(
|
||||
state: currentStep > 0 ? StepState.complete : StepState.indexed,
|
||||
isActive: currentStep >= 0,
|
||||
stepStyle: currentStep >= 0
|
||||
? StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Color(0xFF329e95),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
)
|
||||
: StepStyle(
|
||||
connectorThickness: 0,
|
||||
color: Colors.transparent,
|
||||
boxShadow: BoxShadow(spreadRadius: 5),
|
||||
indexStyle: TextStyle(color: Colors.transparent),
|
||||
),
|
||||
title: const Text(""),
|
||||
content: SignupPersonalScreen(),
|
||||
),
|
||||
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(),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
77
modules/auth/lib/src/sign_up/signup_user_screen.dart
Normal file
77
modules/auth/lib/src/sign_up/signup_user_screen.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SignupUserScreen extends StatefulWidget{
|
||||
const SignupUserScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SignupUserScreen> createState() => SignupUserScreenState();
|
||||
}
|
||||
|
||||
class SignupUserScreenState extends State<SignupUserScreen>{
|
||||
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<DropdownMenuEntry>.generate(3, (int index){
|
||||
return DropdownMenuEntry(labelWidget: Icon(Icons.outlined_flag), label: "es", value: "es");
|
||||
})
|
||||
),
|
||||
Expanded(child: TextField(
|
||||
decoration: InputDecoration(labelText: "Teléfono móvil", hintText: "Teléfono", border: OutlineInputBorder()),
|
||||
keyboardType: TextInputType.number)
|
||||
)
|
||||
]),
|
||||
TextField(
|
||||
obscureText: passwordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Contraseña",
|
||||
hintText: "********",
|
||||
border: OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(passwordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
passwordVisible = !passwordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
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;
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
69
modules/auth/pubspec.yaml
Normal file
69
modules/auth/pubspec.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
name: auth
|
||||
# resolution: workspace
|
||||
description: "A new Flutter package project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
#modules dependencies go here
|
||||
dashboard_shell:
|
||||
path: ../../modules/dashboard_shell
|
||||
#packages dependencies go here
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
navigation:
|
||||
path: ../../packages/navigation
|
||||
#dependencies go here
|
||||
flutter_svg: ^2.2.1
|
||||
get_it: ^9.0.5
|
||||
go_router: ^17.0.0
|
||||
flutter_riverpod: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/to/asset-from-package
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/to/font-from-package
|
||||
16
modules/auth/pubspec_overrides.yaml
Normal file
16
modules/auth/pubspec_overrides.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
# melos_managed_dependency_overrides: dashboard_shell,design_system,home,notifications,profile,sf_shared,navigation
|
||||
dependency_overrides:
|
||||
dashboard_shell:
|
||||
path: ../dashboard_shell
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
home:
|
||||
path: ../home
|
||||
navigation:
|
||||
path: ../../packages/navigation
|
||||
notifications:
|
||||
path: ../notifications
|
||||
profile:
|
||||
path: ../profile
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
31
modules/dashboard_shell/.gitignore
vendored
Normal file
31
modules/dashboard_shell/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
modules/dashboard_shell/.metadata
Normal file
10
modules/dashboard_shell/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
modules/dashboard_shell/CHANGELOG.md
Normal file
3
modules/dashboard_shell/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
modules/dashboard_shell/LICENSE
Normal file
1
modules/dashboard_shell/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
39
modules/dashboard_shell/README.md
Normal file
39
modules/dashboard_shell/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
4
modules/dashboard_shell/analysis_options.yaml
Normal file
4
modules/dashboard_shell/analysis_options.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
18
modules/dashboard_shell/lib/dashboard_builder.dart
Normal file
18
modules/dashboard_shell/lib/dashboard_builder.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:dashboard_shell/dashboard_shell.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
class DashboardBuilder {
|
||||
const DashboardBuilder();
|
||||
|
||||
Widget build(BuildContext context, StatefulNavigationShell navShell) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return DashboardScreen(
|
||||
navigationShell: navShell,
|
||||
navigationContract: navigationContract,
|
||||
);
|
||||
}
|
||||
}
|
||||
2
modules/dashboard_shell/lib/dashboard_shell.dart
Normal file
2
modules/dashboard_shell/lib/dashboard_shell.dart
Normal file
@@ -0,0 +1,2 @@
|
||||
export 'src/presentation/dashboard_screen.dart';
|
||||
export 'dashboard_builder.dart';
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:home/home.dart';
|
||||
import 'package:notifications/notifications.dart';
|
||||
import 'package:profile/profile.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class DashboardScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
DashboardScreen({super.key, required this.navigationContract});
|
||||
|
||||
int currentPageIndex = 3;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final bodies = [
|
||||
HomeScreen(),
|
||||
ActivityScreen(),
|
||||
AlertScreen(),
|
||||
ProfileScreen(),
|
||||
];
|
||||
|
||||
return Scaffold(
|
||||
bottomNavigationBar: NavigationBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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],
|
||||
);
|
||||
}
|
||||
}
|
||||
73
modules/dashboard_shell/pubspec.yaml
Normal file
73
modules/dashboard_shell/pubspec.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
name: dashboard_shell
|
||||
resoluction: workspace
|
||||
description: "A new Flutter package project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
#modules dependencies go here
|
||||
home:
|
||||
path: ../../modules/home
|
||||
notifications:
|
||||
path: ../../modules/notifications
|
||||
profile:
|
||||
path: ../../modules/profile
|
||||
#packages dependencies go here
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
|
||||
#dependencies go here
|
||||
navigation: ^0.0.1
|
||||
get_it: ^9.0.5
|
||||
go_router: ^17.0.0
|
||||
flutter_riverpod: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/to/asset-from-package
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/to/font-from-package
|
||||
16
modules/dashboard_shell/pubspec_overrides.yaml
Normal file
16
modules/dashboard_shell/pubspec_overrides.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
# melos_managed_dependency_overrides: auth,design_system,home,notifications,profile,sf_shared,navigation
|
||||
dependency_overrides:
|
||||
auth:
|
||||
path: ../auth
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
home:
|
||||
path: ../home
|
||||
navigation:
|
||||
path: ../../packages/navigation
|
||||
notifications:
|
||||
path: ../notifications
|
||||
profile:
|
||||
path: ../profile
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
31
modules/home/.gitignore
vendored
Normal file
31
modules/home/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
modules/home/.metadata
Normal file
10
modules/home/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
modules/home/CHANGELOG.md
Normal file
3
modules/home/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
modules/home/LICENSE
Normal file
1
modules/home/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
39
modules/home/README.md
Normal file
39
modules/home/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
4
modules/home/analysis_options.yaml
Normal file
4
modules/home/analysis_options.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
1
modules/home/lib/home.dart
Normal file
1
modules/home/lib/home.dart
Normal file
@@ -0,0 +1 @@
|
||||
export 'src/presentation/home_screen.dart';
|
||||
193
modules/home/lib/src/presentation/deposit_screen.dart
Normal file
193
modules/home/lib/src/presentation/deposit_screen.dart
Normal file
@@ -0,0 +1,193 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class DepositScreen extends ConsumerWidget {
|
||||
final Kid kid;
|
||||
|
||||
DepositScreen({super.key, required this.kid});
|
||||
|
||||
String reason = "other";
|
||||
bool program = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return WalletManagementLayout(
|
||||
kid: kid,
|
||||
footer: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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.backgroundPrimary),
|
||||
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.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Objetivo semanal cumplido'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: reason == "goal",
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// reason = "goal";
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Gastos extraordinarios'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: reason == "extraordinary",
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// reason = "extraordinary";
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Otro'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: reason == "other",
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// reason = "other";
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
TextField(
|
||||
minLines: 3,
|
||||
maxLines: 3,
|
||||
maxLength: 150,
|
||||
decoration: InputDecoration(
|
||||
labelText:
|
||||
"Escribir mensaje a ${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.backgroundPrimary),
|
||||
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.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Programar'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: program == true,
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// program = true;
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
if (program) TextField(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
274
modules/home/lib/src/presentation/home_screen.dart
Normal file
274
modules/home/lib/src/presentation/home_screen.dart
Normal file
@@ -0,0 +1,274 @@
|
||||
import 'package:auth/auth.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:home/src/presentation/deposit_screen.dart';
|
||||
import 'package:home/src/presentation/kid_wallet_screen.dart';
|
||||
import 'package:home/src/presentation/money_text.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class HomeScreen extends ConsumerWidget {
|
||||
final String name = "Juan";
|
||||
final double total = 95.03;
|
||||
final List<Kid> 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, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
color: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
text: "Hola, ",
|
||||
style: TextStyle(fontSize: 25),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: name,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
walletsList(context, kids, ref),
|
||||
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.textPrimary),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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.textPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
LinearProgressIndicator(
|
||||
value: available / total,
|
||||
minHeight: 70,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
backgroundColor: theme.getColorFor(
|
||||
ThemeCode.backgroundTertiary,
|
||||
),
|
||||
),
|
||||
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.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Center(child: Text("Disponible")),
|
||||
],
|
||||
),
|
||||
),
|
||||
DepositBlock(max: 150 - total),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget walletsList(BuildContext context, List<Kid> kids, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Column(
|
||||
spacing: 20,
|
||||
children: List<Widget>.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.textSecondary),
|
||||
),
|
||||
),
|
||||
),
|
||||
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.textSecondary),
|
||||
),
|
||||
Text(
|
||||
"en su hucha",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
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.textSecondary),
|
||||
),
|
||||
Text(
|
||||
"Editar",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => DepositScreen(kid: kids[index]),
|
||||
),
|
||||
),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll<Color>(
|
||||
theme.getColorFor(ThemeCode.buttonSecondary),
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 0,
|
||||
vertical: 10,
|
||||
),
|
||||
child: Text("+ Añadir dinero"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
308
modules/home/lib/src/presentation/kid_wallet_screen.dart
Normal file
308
modules/home/lib/src/presentation/kid_wallet_screen.dart
Normal file
@@ -0,0 +1,308 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:home/src/presentation/deposit_screen.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:home/src/presentation/limits_screen.dart';
|
||||
import 'package:home/src/presentation/money_text.dart';
|
||||
import 'package:home/src/presentation/wage_screen.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class KidWalletScreen extends ConsumerWidget {
|
||||
final Kid kid;
|
||||
|
||||
const KidWalletScreen({super.key, required this.kid});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
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.symmetric(vertical: 50, horizontal: 20),
|
||||
child: Column(
|
||||
spacing: 15,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 7,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
icon: Icon(
|
||||
Icons.arrow_back_ios_new_outlined,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: SvgPicture.asset("assets/images/ui/face.svg"),
|
||||
),
|
||||
Text(
|
||||
kid.name,
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
child: SvgPicture.asset("assets/images/ui/face.svg"),
|
||||
),
|
||||
],
|
||||
),
|
||||
MoneyText(
|
||||
text: "${kid.balance.toString()}€",
|
||||
size: 60,
|
||||
resize: true,
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
Text(
|
||||
"Saldo disponible",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
),
|
||||
LinearProgressIndicator(
|
||||
value: 0.7,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
backgroundColor: theme
|
||||
.getColorFor(ThemeCode.backgroundPrimary)
|
||||
.withAlpha(0x4C),
|
||||
minHeight: 10,
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(top: 30),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
child: Expanded(
|
||||
child: Center(
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => DepositScreen(kid: kid),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_circle_outline,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Añadir",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => WageScreen(kid: kid),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.account_balance_wallet_outlined,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Paga",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => LimitsScreen(kid: kid),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.list_alt_outlined,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Límites",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () => {},
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.emoji_events_outlined,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Metas",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
height: 400,
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Últimos movimientos"),
|
||||
activityList(context, theme),
|
||||
TextButton(onPressed: () => {}, child: Text("Ver todos")),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget activityList(BuildContext context, theme) {
|
||||
final activity = [
|
||||
{
|
||||
"date": "10/05",
|
||||
"payments": [1, 2, 3],
|
||||
},
|
||||
{
|
||||
"date": "10/04",
|
||||
"payments": [1, 2],
|
||||
},
|
||||
{
|
||||
"date": "10/02",
|
||||
"payments": [1, 2, 3, 4],
|
||||
},
|
||||
];
|
||||
|
||||
return Expanded(
|
||||
child: ListView(
|
||||
children: List<Widget>.generate(activity.length, (int index) {
|
||||
return Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Text(activity[index]["date"].toString()),
|
||||
Column(
|
||||
spacing: 15,
|
||||
children: List<Widget>.generate(
|
||||
(activity[index]["payments"] as List<Object>).length,
|
||||
(int i) {
|
||||
//var a = (activity[index]["payments"] as List<Object>)[i];
|
||||
return Row(
|
||||
spacing: 7,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(9),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.backgroundTertiary,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.local_pizza_outlined,
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
"Vips",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text("20:15"),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
MoneyText(
|
||||
text: "5.1€",
|
||||
size: 20,
|
||||
resize: true,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
156
modules/home/lib/src/presentation/limits_screen.dart
Normal file
156
modules/home/lib/src/presentation/limits_screen.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class LimitsScreen extends ConsumerStatefulWidget {
|
||||
final Kid kid;
|
||||
|
||||
const LimitsScreen({super.key, required this.kid});
|
||||
|
||||
@override
|
||||
ConsumerState<LimitsScreen> createState() => LimitsScreenState();
|
||||
}
|
||||
|
||||
class LimitsScreenState extends ConsumerState<LimitsScreen> {
|
||||
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) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return WalletManagementLayout(
|
||||
kid: widget.kid,
|
||||
footer: Column(
|
||||
children: [
|
||||
FilledButton(
|
||||
onPressed: () => {},
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Center(child: Text("Guardar límites")),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
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<Widget>.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.backgroundPrimary),
|
||||
),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text(
|
||||
"Horarios permitidos",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
),
|
||||
Text("Controla cuándo pueden comprar"),
|
||||
...List<Widget>.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(),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
35
modules/home/lib/src/presentation/money_text.dart
Normal file
35
modules/home/lib/src/presentation/money_text.dart
Normal file
@@ -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
|
||||
)
|
||||
)
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
228
modules/home/lib/src/presentation/wage_screen.dart
Normal file
228
modules/home/lib/src/presentation/wage_screen.dart
Normal file
@@ -0,0 +1,228 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class WageScreen extends ConsumerWidget {
|
||||
final Kid kid;
|
||||
|
||||
WageScreen({super.key, required this.kid});
|
||||
|
||||
String frequence = "weekly";
|
||||
var conditions = {
|
||||
"weeklyLimits": false,
|
||||
"incidences": false,
|
||||
"holidays": false,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return WalletManagementLayout(
|
||||
kid: kid,
|
||||
footer: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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")),
|
||||
],
|
||||
),
|
||||
),
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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.backgroundPrimary),
|
||||
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.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Cada dos semanas'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: frequence == "biweekly",
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// frequence = "biweekly";
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Mensual'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: frequence == "monthly",
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// frequence = "monthly";
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: DropdownMenu(
|
||||
label: Text("Día de la semana"),
|
||||
initialSelection: "Domingo",
|
||||
dropdownMenuEntries: List<DropdownMenuEntry>.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<DropdownMenuEntry>.generate(24, (
|
||||
int index,
|
||||
) {
|
||||
return DropdownMenuEntry(value: index, label: "$index:00");
|
||||
}),
|
||||
),
|
||||
TextField(
|
||||
minLines: 3,
|
||||
maxLines: 3,
|
||||
maxLength: 150,
|
||||
decoration: InputDecoration(
|
||||
labelText:
|
||||
"Escribir mensaje a ${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.backgroundPrimary),
|
||||
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.buttonPrimary),
|
||||
),
|
||||
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.buttonPrimary),
|
||||
),
|
||||
CheckboxListTile(
|
||||
title: Text('Pausar durante vacaciones'),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: conditions["holidays"],
|
||||
onChanged: (value) {
|
||||
// setState(() {
|
||||
// conditions["holidays"] = !conditions["holidays"]!;
|
||||
// });
|
||||
},
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
70
modules/home/pubspec.yaml
Normal file
70
modules/home/pubspec.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
name: home
|
||||
# resolution: workspace
|
||||
description: "A new Flutter package project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
#modules dependencies go here
|
||||
auth:
|
||||
path: ../../modules/auth
|
||||
notifications:
|
||||
path: ../../modules/notifications
|
||||
|
||||
#packages dependencies go here
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
#dependencies go here
|
||||
flutter_svg: ^2.2.1
|
||||
flutter_riverpod: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/to/asset-from-package
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/to/font-from-package
|
||||
16
modules/home/pubspec_overrides.yaml
Normal file
16
modules/home/pubspec_overrides.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
# melos_managed_dependency_overrides: auth,dashboard_shell,design_system,notifications,profile,sf_shared,navigation
|
||||
dependency_overrides:
|
||||
auth:
|
||||
path: ../auth
|
||||
dashboard_shell:
|
||||
path: ../dashboard_shell
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
navigation:
|
||||
path: ../../packages/navigation
|
||||
notifications:
|
||||
path: ../notifications
|
||||
profile:
|
||||
path: ../profile
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
31
modules/notifications/.gitignore
vendored
Normal file
31
modules/notifications/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
modules/notifications/.metadata
Normal file
10
modules/notifications/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
modules/notifications/CHANGELOG.md
Normal file
3
modules/notifications/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
modules/notifications/LICENSE
Normal file
1
modules/notifications/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
39
modules/notifications/README.md
Normal file
39
modules/notifications/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
4
modules/notifications/analysis_options.yaml
Normal file
4
modules/notifications/analysis_options.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
3
modules/notifications/lib/notifications.dart
Normal file
3
modules/notifications/lib/notifications.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
export 'src/presentation/alert_screen.dart';
|
||||
export 'src/presentation/activity_screen.dart';
|
||||
export 'src/core/activity_list.dart';
|
||||
106
modules/notifications/lib/src/core/activity_list.dart
Normal file
106
modules/notifications/lib/src/core/activity_list.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ActivityList extends ConsumerStatefulWidget {
|
||||
final List activity;
|
||||
bool edit = false;
|
||||
|
||||
ActivityList({super.key, required this.activity, required this.edit});
|
||||
|
||||
@override
|
||||
ConsumerState<ActivityList> createState() => ActivityListState();
|
||||
}
|
||||
|
||||
class ActivityListState extends ConsumerState<ActivityList> {
|
||||
late List<bool> values;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
values = List<bool>.generate(widget.activity.length, (_) => false);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
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<Widget>.generate(widget.activity.length, (int index) {
|
||||
var logItem = Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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.buttonPrimary),
|
||||
semanticLabel: "Eliminar",
|
||||
),
|
||||
Expanded(child: logItem),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return logItem;
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:notifications/src/core/activity_list.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
class ActivityScreen extends ConsumerWidget {
|
||||
ActivityScreen({super.key});
|
||||
|
||||
final activity = [
|
||||
{"type": "goal"},
|
||||
{"type": "wage", "amount": 5},
|
||||
{"type": "lock"},
|
||||
{"type": "lock"},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
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.backgroundSecondary),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
56
modules/notifications/lib/src/presentation/alert_screen.dart
Normal file
56
modules/notifications/lib/src/presentation/alert_screen.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:notifications/src/core/activity_list.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class AlertScreen extends ConsumerStatefulWidget {
|
||||
const AlertScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<AlertScreen> createState() => AlertScreenState();
|
||||
}
|
||||
|
||||
class AlertScreenState extends ConsumerState<AlertScreen> {
|
||||
final activity = [
|
||||
{"type": "goal"},
|
||||
{"type": "wage", "amount": 5},
|
||||
{"type": "lock"},
|
||||
{"type": "lock"},
|
||||
];
|
||||
bool edit = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
edit = false;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
body: Container(
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("Alertas"),
|
||||
Spacer(),
|
||||
TextButton(
|
||||
onPressed: () => setState(() {
|
||||
edit = !edit;
|
||||
}),
|
||||
child: Text("Editar"),
|
||||
),
|
||||
],
|
||||
),
|
||||
ActivityList(activity: activity, edit: edit),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
65
modules/notifications/pubspec.yaml
Normal file
65
modules/notifications/pubspec.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
name: notifications
|
||||
# resolution: workspace
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
description: "A new Flutter package project."
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
#modules dependencies go here
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
#packages dependencies go here
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
#dependencies go here
|
||||
flutter_riverpod: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/to/asset-from-package
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/to/font-from-package
|
||||
6
modules/notifications/pubspec_overrides.yaml
Normal file
6
modules/notifications/pubspec_overrides.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# melos_managed_dependency_overrides: design_system,sf_shared
|
||||
dependency_overrides:
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
31
modules/profile/.gitignore
vendored
Normal file
31
modules/profile/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
modules/profile/.metadata
Normal file
10
modules/profile/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
modules/profile/CHANGELOG.md
Normal file
3
modules/profile/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
modules/profile/LICENSE
Normal file
1
modules/profile/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
39
modules/profile/README.md
Normal file
39
modules/profile/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
4
modules/profile/analysis_options.yaml
Normal file
4
modules/profile/analysis_options.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
1
modules/profile/lib/profile.dart
Normal file
1
modules/profile/lib/profile.dart
Normal file
@@ -0,0 +1 @@
|
||||
export 'src/presentation/profile_screen.dart';
|
||||
135
modules/profile/lib/src/presentation/profile_screen.dart
Normal file
135
modules/profile/lib/src/presentation/profile_screen.dart
Normal file
@@ -0,0 +1,135 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:notifications/notifications.dart';
|
||||
import 'package:profile/src/settings_screen.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ProfileScreen extends ConsumerWidget {
|
||||
const ProfileScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
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.textSecondary),
|
||||
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.textSecondary),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
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.textSecondary),
|
||||
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.backgroundSecondary),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
360
modules/profile/lib/src/settings_screen.dart
Normal file
360
modules/profile/lib/src/settings_screen.dart
Normal file
@@ -0,0 +1,360 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class SettingsScreen extends ConsumerWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
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.textSecondary),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Saldo: $balance€",
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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.backgroundTertiary),
|
||||
),
|
||||
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.backgroundSecondary),
|
||||
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.backgroundPrimary),
|
||||
),
|
||||
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"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
67
modules/profile/pubspec.yaml
Normal file
67
modules/profile/pubspec.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
name: profile
|
||||
# resolution: workspace
|
||||
description: "A new Flutter package project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
#modules dependencies go here
|
||||
notifications:
|
||||
path: ../../modules/notifications
|
||||
#packages dependencies go here
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
|
||||
#dependencies go here
|
||||
flutter_riverpod: ^3.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/to/asset-from-package
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
# To add custom fonts to your package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/to/font-from-package
|
||||
8
modules/profile/pubspec_overrides.yaml
Normal file
8
modules/profile/pubspec_overrides.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
# melos_managed_dependency_overrides: design_system,notifications,sf_shared
|
||||
dependency_overrides:
|
||||
design_system:
|
||||
path: ../../packages/design_system
|
||||
notifications:
|
||||
path: ../notifications
|
||||
sf_shared:
|
||||
path: ../../packages/sf_shared
|
||||
Reference in New Issue
Block a user