diff --git a/lib/screens/register/register_screen.dart b/lib/screens/register/register_screen.dart index aecec9a..ce0b1cf 100644 --- a/lib/screens/register/register_screen.dart +++ b/lib/screens/register/register_screen.dart @@ -1,3 +1,4 @@ +import 'package:email_validator/email_validator.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; @@ -43,6 +44,11 @@ class RegisterForm extends StatefulWidget { class _RegisterFormState extends State { final _formKey = GlobalKey(); + final _nameFormKey = GlobalKey(); + final _usernameFormKey = GlobalKey(); + final _emailFormKey = GlobalKey(); + final _passwordFormKey = GlobalKey(); + final _confirmPasswordFormKey = GlobalKey(); final _nameController = TextEditingController(); final _usernameController = TextEditingController(); @@ -71,16 +77,27 @@ class _RegisterFormState extends State { return null; } + String _validateUserName(String value) { + if (value.length < 4) { + return "Username cannot be less than 4 characters"; + } else if (value.length > 26) { + return "Username cannot be more 26 characters"; + } + return null; + } + String _validateEmail(String value) { - if (value.isEmpty) { - return "Email cannot be empty"; // TODO: Add regex based validation + if (!EmailValidator.validate(value)) { + return "Email is not valid"; } return null; } String _validatePassword(String value) { - if (value.isEmpty) { - return "Password cannot be empty"; // TODO: Add regex based validation + if (value.length < 8) { + return "Password should be longer than 8 characters"; // TODO: Add regex based validation + } else if (value.length > 64) { + return "Password should be no longer than 64 characters"; // TODO: Add regex based validation } return null; } @@ -116,59 +133,84 @@ class _RegisterFormState extends State { key: _formKey, child: Column( children: [ - TextFormField( - controller: _nameController, - validator: _validateName, - decoration: InputDecoration( - labelText: "Name", - border: OutlineInputBorder(), + Form( + key: _nameFormKey, + child: TextFormField( + onChanged: (val) => _nameFormKey.currentState.validate(), + controller: _nameController, + validator: _validateName, + decoration: InputDecoration( + labelText: "Name", + border: OutlineInputBorder(), + ), ), ), SizedBox(height: spacing), - TextFormField( - controller: _usernameController, - validator: _validateName, - decoration: InputDecoration( - labelText: "Username", - border: OutlineInputBorder(), + Form( + key: _usernameFormKey, + child: TextFormField( + onChanged: (val) => _usernameFormKey.currentState.validate(), + controller: _usernameController, + validator: _validateUserName, + decoration: InputDecoration( + labelText: "Username", + border: OutlineInputBorder(), + ), ), ), SizedBox(height: spacing), - TextFormField( - controller: _emailController, - validator: _validateEmail, - decoration: InputDecoration( - labelText: "Email", - border: OutlineInputBorder(), + Form( + key: _emailFormKey, + child: TextFormField( + onChanged: (val) => _emailFormKey.currentState.validate(), + controller: _emailController, + validator: _validateEmail, + decoration: InputDecoration( + labelText: "Email", + border: OutlineInputBorder(), + ), ), ), SizedBox(height: spacing), - TextFormField( - controller: _passwordController, - validator: _validatePassword, - decoration: InputDecoration( - suffixIcon: IconButton( - icon: Icon(_passwordVisible ? Icons.visibility : Icons.visibility_off), - onPressed: _togglePasswordVisibility, + Form( + key: _passwordFormKey, + child: TextFormField( + onChanged: (val) => _passwordFormKey.currentState.validate(), + controller: _passwordController, + validator: _validatePassword, + decoration: InputDecoration( + suffixIcon: IconButton( + icon: Icon(_passwordVisible + ? Icons.visibility + : Icons.visibility_off), + onPressed: _togglePasswordVisibility, + ), + labelText: "Enter password", + border: OutlineInputBorder(), ), - labelText: "Enter password", - border: OutlineInputBorder(), + obscureText: !_passwordVisible, ), - obscureText: !_passwordVisible, ), SizedBox(height: spacing), - TextFormField( - controller: _confirmPasswordController, - validator: _validatePassword, - decoration: InputDecoration( - suffixIcon: IconButton( - icon: Icon(_passwordVisible ? Icons.visibility : Icons.visibility_off), - onPressed: _togglePasswordVisibility, + Form( + key: _confirmPasswordFormKey, + child: TextFormField( + onChanged: (val) => + _confirmPasswordFormKey.currentState.validate(), + controller: _confirmPasswordController, + validator: _validatePassword, + decoration: InputDecoration( + suffixIcon: IconButton( + icon: Icon(_passwordVisible + ? Icons.visibility + : Icons.visibility_off), + onPressed: _togglePasswordVisibility, + ), + labelText: "Confirm password", + border: OutlineInputBorder(), ), - labelText: "Confirm password", - border: OutlineInputBorder(), + obscureText: !_passwordVisible, ), - obscureText: !_passwordVisible, ), Padding( padding: EdgeInsets.all(8), @@ -294,7 +336,8 @@ class ConditionsText extends StatelessWidget { style: TextStyle( color: Colors.black, ), - text: "By checking this box, I affirm that I have read and accept to be bound by the " + text: + "By checking this box, I affirm that I have read and accept to be bound by the " "AnitaB.org ", ), TextSpan( @@ -346,7 +389,8 @@ class ConditionsText extends StatelessWidget { style: TextStyle( color: Colors.black, ), - text: ". Further, I consent to the use of my information for the stated purpose.", + text: + ". Further, I consent to the use of my information for the stated purpose.", ), ], ), diff --git a/pubspec.lock b/pubspec.lock index dd4a0fe..3ab4d8f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -35,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.5.0-nullsafety.3" auto_size_text: dependency: "direct main" description: @@ -56,7 +56,7 @@ packages: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.3" bottom_navy_bar: dependency: "direct main" description: @@ -120,13 +120,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.0.9" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0-nullsafety.5" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety.3" checked_yaml: dependency: transitive description: @@ -161,7 +168,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety.3" code_builder: dependency: transitive description: @@ -175,7 +182,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.15.0-nullsafety.5" color: dependency: transitive description: @@ -218,6 +225,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.6" + email_validator: + dependency: "direct main" + description: + name: email_validator + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" equatable: dependency: "direct main" description: @@ -238,7 +252,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.3" fixnum: dependency: transitive description: @@ -365,7 +379,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.1+1" + version: "0.6.3-nullsafety.3" json_annotation: dependency: transitive description: @@ -386,14 +400,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.10-nullsafety.3" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.6" mime: dependency: transitive description: @@ -442,7 +456,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.3" pedantic: dependency: transitive description: @@ -538,21 +552,21 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.4" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0-nullsafety.6" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.3" stream_transform: dependency: transitive description: @@ -566,21 +580,21 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.3" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.3" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.16" + version: "0.2.19-nullsafety.6" timing: dependency: transitive description: @@ -601,7 +615,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0-nullsafety.5" url_launcher: dependency: "direct main" description: @@ -643,7 +657,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.5" watcher: dependency: transitive description: @@ -673,5 +687,5 @@ packages: source: hosted version: "2.2.0" sdks: - dart: ">=2.7.0 <3.0.0" + dart: ">=2.12.0-0.0 <3.0.0" flutter: ">=1.16.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 4e2d84c..308bf44 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,6 +37,7 @@ dependencies: bloc: ^6.0.1 flutter_bloc: ^6.0.1 chopper: ^3.0.3 + email_validator: ^1.0.6 # plugins not needed in app