summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2023-02-26 01:25:47 -0600
committerIván Ávalos <avalos@disroot.org>2023-02-26 01:25:55 -0600
commit91e6c82c06e7f84fd953d5d7c8a29d2ebead77b2 (patch)
tree0a518cca4a9602fcae8ebe805012ea5cbcfd75a0
parentcf038e04b39f8b88059a10787bb0212c5da692c5 (diff)
downloadpmsna1-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.dart4
-rw-r--r--lib/screens/register_screen.dart189
-rw-r--r--lib/widgets/avatar_picker.dart61
-rw-r--r--pubspec.lock8
-rw-r--r--pubspec.yaml1
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: