diff options
author | Iván Ávalos <avalos@disroot.org> | 2023-02-26 01:25:47 -0600 |
---|---|---|
committer | Iván Ávalos <avalos@disroot.org> | 2023-02-26 01:25:55 -0600 |
commit | 91e6c82c06e7f84fd953d5d7c8a29d2ebead77b2 (patch) | |
tree | 0a518cca4a9602fcae8ebe805012ea5cbcfd75a0 | |
parent | cf038e04b39f8b88059a10787bb0212c5da692c5 (diff) | |
download | pmsna1-91e6c82c06e7f84fd953d5d7c8a29d2ebead77b2.tar.gz pmsna1-91e6c82c06e7f84fd953d5d7c8a29d2ebead77b2.tar.bz2 pmsna1-91e6c82c06e7f84fd953d5d7c8a29d2ebead77b2.zip |
Refactored avatar picker into AvatarPicker and added validation on registration
-rw-r--r-- | lib/screens/login_screen.dart | 4 | ||||
-rw-r--r-- | lib/screens/register_screen.dart | 189 | ||||
-rw-r--r-- | lib/widgets/avatar_picker.dart | 61 | ||||
-rw-r--r-- | pubspec.lock | 8 | ||||
-rw-r--r-- | pubspec.yaml | 1 |
5 files changed, 163 insertions, 100 deletions
diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart index 2b0e115..d4dc3a2 100644 --- a/lib/screens/login_screen.dart +++ b/lib/screens/login_screen.dart @@ -68,8 +68,8 @@ class _LoginScreenState extends State<LoginScreen> children: [ TextField( controller: _emailController, - decoration: InputDecoration( - border: const OutlineInputBorder(), + decoration: const InputDecoration( + border: OutlineInputBorder(), labelText: 'Correo electrónico', hintText: 'test@example.com', ), diff --git a/lib/screens/register_screen.dart b/lib/screens/register_screen.dart index 3cadd7d..ddd8965 100644 --- a/lib/screens/register_screen.dart +++ b/lib/screens/register_screen.dart @@ -1,7 +1,9 @@ import 'dart:io'; +import 'package:email_validator/email_validator.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:pmsna1/widgets/avatar_picker.dart'; import 'package:social_login_buttons/social_login_buttons.dart'; import '../widgets/loading_modal_widget.dart'; @@ -19,7 +21,6 @@ class _RegisterScreenState extends State<RegisterScreen> { final padding = 16.0; final spacer = const SizedBox(height: 16.0); - final ImagePicker _picker = ImagePicker(); XFile? _avatar; File? getAvatarFile() { @@ -31,6 +32,8 @@ class _RegisterScreenState extends State<RegisterScreen> { late TextEditingController _emailController; late TextEditingController _passwordController; + final _formKey = GlobalKey<FormState>(); + @override void initState() { // TODO: implement initState @@ -40,6 +43,13 @@ class _RegisterScreenState extends State<RegisterScreen> { _passwordController = TextEditingController(); } + bool validateForm() { + if (_formKey.currentState!.validate() && _avatar != null) { + return true; + } + return false; + } + @override Widget build(BuildContext context) { return Scaffold( @@ -60,110 +70,93 @@ class _RegisterScreenState extends State<RegisterScreen> { EdgeInsets.fromLTRB(padding, 0, padding, padding), child: Padding( padding: EdgeInsets.all(padding), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircleAvatar( - radius: 50.0, - backgroundImage: getAvatarFile() == null - ? null - : FileImage(getAvatarFile()!), - child: getAvatarFile() == null - ? const Icon(Icons.person, size: 50.0) - : null, + child: Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AvatarPicker( + avatar: _avatar, + onAvatarPicked: (avatar) { + setState(() { + _avatar = avatar; + }); + }, + ), + spacer, + TextFormField( + controller: _nameController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Nombre', + hintText: 'Juan Pérez', ), - const SizedBox(width: 18.0), - Column( - children: [ - FilledButton.icon( - icon: const Icon(Icons.camera_alt), - label: const Text('Cámara'), - onPressed: () { - _picker - .pickImage( - source: ImageSource.camera) - .then((image) { - setState(() { - _avatar = image; - }); - }); - }, - ), - spacer, - FilledButton.icon( - icon: const Icon(Icons.collections), - label: const Text('Galería'), - onPressed: () { - _picker - .pickImage( - source: ImageSource.gallery) - .then((image) { - setState(() { - _avatar = image; - }); - }); - }, - ) - ], - ) - ], - ), - spacer, - TextField( - controller: _nameController, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: 'Nombre', - hintText: 'Juan Pérez', + keyboardType: TextInputType.name, + validator: (value) { + if (value == null || value.isEmpty) { + return 'El nombre no debe estar vacío'; + } + return null; + }, ), - keyboardType: TextInputType.name, - ), - spacer, - TextField( - controller: _emailController, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: 'Correo electrónico', - hintText: 'test@example.com', + spacer, + TextFormField( + controller: _emailController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Correo electrónico', + hintText: 'test@example.com', + ), + keyboardType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) { + return 'El correo no debe estar vacío'; + } else if (!EmailValidator.validate( + value)) { + return 'El formato del correo es inválido'; + } + return null; + }, ), - keyboardType: TextInputType.emailAddress, - ), - spacer, - TextField( - controller: _passwordController, - obscureText: true, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: 'Contraseña', + spacer, + TextFormField( + controller: _passwordController, + obscureText: true, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Contraseña', + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'La contraseña no debe estar vacía'; + } + return null; + }, ), - ), - spacer, - SocialLoginButton( - buttonType: SocialLoginButtonType.generalLogin, - text: 'Crear cuenta', - backgroundColor: - Theme.of(context).colorScheme.primary, - onPressed: () { - setState(() { - isLoading = true; - }); - Future.delayed(const Duration(seconds: 4)) - .whenComplete(() { + spacer, + SocialLoginButton( + buttonType: + SocialLoginButtonType.generalLogin, + text: 'Crear cuenta', + backgroundColor: + Theme.of(context).colorScheme.primary, + onPressed: () { setState(() { isLoading = false; - Navigator.of(context).pushNamed('/dash'); - print(_nameController.text); - print(_emailController.text); - print(_passwordController.text); + if (validateForm()) { + Future.delayed( + const Duration(seconds: 4)) + .whenComplete(() { + Navigator.of(context) + .pushNamed('/dash'); + }); + } }); - }); - }, - ), - ], + }, + ), + ], + ), ), ), ), diff --git a/lib/widgets/avatar_picker.dart b/lib/widgets/avatar_picker.dart new file mode 100644 index 0000000..bdfec6d --- /dev/null +++ b/lib/widgets/avatar_picker.dart @@ -0,0 +1,61 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; + +class AvatarPicker extends StatelessWidget { + final ImagePicker picker = ImagePicker(); + final XFile? avatar; + final Function(XFile? avatar) onAvatarPicked; + + AvatarPicker({ + super.key, + required this.avatar, + required this.onAvatarPicked, + }); + + File? _getAvatarFile() { + return avatar == null ? null : File(avatar!.path); + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircleAvatar( + radius: 50.0, + backgroundImage: + _getAvatarFile() == null ? null : FileImage(_getAvatarFile()!), + child: _getAvatarFile() == null + ? const Icon(Icons.person, size: 50.0) + : null, + ), + const SizedBox(width: 18.0), + Column( + children: [ + FilledButton.icon( + icon: const Icon(Icons.camera_alt), + label: const Text('Cámara'), + onPressed: () { + picker.pickImage(source: ImageSource.camera).then((image) { + onAvatarPicked(image); + }); + }, + ), + const SizedBox(height: 16.0), + FilledButton.icon( + icon: const Icon(Icons.collections), + label: const Text('Galería'), + onPressed: () { + picker.pickImage(source: ImageSource.gallery).then((image) { + onAvatarPicked(image); + }); + }, + ) + ], + ) + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 7b54443..ba71d4f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -65,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + email_validator: + dependency: "direct main" + description: + name: email_validator + sha256: e9a90f27ab2b915a27d7f9c2a7ddda5dd752d6942616ee83529b686fc086221b + url: "https://pub.dev" + source: hosted + version: "2.1.17" fake_async: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8accd4d..0f67306 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: sqflite: ^2.2.4+1 path_provider: ^2.0.13 image_picker: ^0.8.6+3 + email_validator: ^2.1.17 dev_dependencies: flutter_test: |