diff --git a/.idea/epic_flutter.iml b/.idea/epic_flutter.iml
index 2ce7fb4..b946f02 100644
--- a/.idea/epic_flutter.iml
+++ b/.idea/epic_flutter.iml
@@ -1,5 +1,10 @@
+
+
+
+
+
@@ -10,7 +15,9 @@
-
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
new file mode 100644
index 0000000..b07fba4
--- /dev/null
+++ b/.idea/libraries/Dart_Packages.xml
@@ -0,0 +1,1220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml
new file mode 100644
index 0000000..c6628b5
--- /dev/null
+++ b/.idea/libraries/Dart_SDK.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_base/lib/mobx/form/form_store.dart b/flutter_base/lib/mobx/form/form_store.dart
index 6f39e91..bb34688 100644
--- a/flutter_base/lib/mobx/form/form_store.dart
+++ b/flutter_base/lib/mobx/form/form_store.dart
@@ -41,7 +41,7 @@ abstract class _FormStore with Store {
@action
void validateEmail(String value) {
- error.email = isEmail(value) ? 'Not a valid email' : null;
+ error.email = !isEmail(value) ? 'Not a valid email' : null;
}
@action
diff --git a/flutter_base/lib/mobx/form_bloc/form_bloc.dart b/flutter_base/lib/mobx/form_bloc/form_bloc.dart
new file mode 100644
index 0000000..ab181b6
--- /dev/null
+++ b/flutter_base/lib/mobx/form_bloc/form_bloc.dart
@@ -0,0 +1,114 @@
+import 'package:bloc/bloc.dart';
+import 'package:validators2/validators.dart';
+
+abstract class ValidateEvent {}
+
+class ValidateUsernameEvent extends ValidateEvent {
+ final String username;
+ ValidateUsernameEvent(this.username);
+}
+
+class ValidatePasswordEvent extends ValidateEvent {
+ final String password;
+ ValidatePasswordEvent(this.password);
+}
+
+class ValidateEmailEvent extends ValidateEvent {
+ final String email;
+ ValidateEmailEvent(this.email);
+}
+
+class FormErrorState {
+ final String? errorUsername;
+ final String? errorEmail;
+ final String? errorPassword;
+
+ FormErrorState({
+ required this.errorUsername,
+ required this.errorEmail,
+ required this.errorPassword,
+ });
+
+ bool get hasErrors => errorUsername != null || errorEmail != null || errorPassword != null;
+
+}
+
+class ValidateBloc extends Bloc {
+ ValidateBloc()
+ : super(
+ FormErrorState(
+ errorUsername: null,
+ errorEmail: null,
+ errorPassword: null,
+ ),
+ ) {
+ on((ValidateUsernameEvent event, Emitter emit) async {
+ if (isNull(event.username) || event.username.isEmpty) {
+ emit(FormErrorState(
+ errorUsername: 'Field is required',
+ errorEmail: state.errorEmail,
+ errorPassword: state.errorPassword));
+ return;
+ }
+ try {
+ emit(
+ FormErrorState(
+ errorUsername: null,
+ errorEmail: state.errorEmail,
+ errorPassword: state.errorPassword),
+ );
+ final isValid = await checkValidUsername(event.username);
+ if (!isValid) {
+ emit(
+ FormErrorState(
+ errorUsername: 'Username cannot be "admin"',
+ errorEmail: state.errorEmail,
+ errorPassword: state.errorPassword),
+ );
+ return;
+ }
+ } catch (_) {
+ emit(
+ FormErrorState(
+ errorUsername: null,
+ errorEmail: state.errorEmail,
+ errorPassword: state.errorPassword),
+ );
+ }
+ });
+ on((ValidatePasswordEvent event, Emitter emit) {
+ if (!isNull(event.password) && event.password.isNotEmpty) {
+ emit(FormErrorState(
+ errorUsername: state.errorUsername,
+ errorEmail: state.errorEmail,
+ errorPassword: null));
+ } else {
+ emit(FormErrorState(
+ errorUsername: state.errorUsername,
+ errorEmail: state.errorEmail,
+ errorPassword: 'Field is required'));
+ }
+ });
+ on((ValidateEmailEvent event, Emitter emit) {
+ if (isEmail(event.email)) {
+ emit(FormErrorState(
+ errorUsername: state.errorUsername,
+ errorEmail: null,
+ errorPassword: state.errorPassword));
+ } else {
+ emit(FormErrorState(
+ errorUsername: state.errorUsername,
+ errorEmail: 'Not a valid email',
+ errorPassword: state.errorPassword));
+ }
+ });
+ }
+
+
+} //close bloc
+
+Future checkValidUsername(String value) async {
+ await Future.delayed(const Duration(seconds: 1));
+
+ return value != 'admin';
+}
diff --git a/flutter_base/lib/mobx/form_bloc/main.dart b/flutter_base/lib/mobx/form_bloc/main.dart
new file mode 100644
index 0000000..1cf7577
--- /dev/null
+++ b/flutter_base/lib/mobx/form_bloc/main.dart
@@ -0,0 +1,92 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'form_bloc.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: BlocProvider(
+ create: (context) => ValidateBloc(),
+ child: const AppForm(),
+ ),
+ );
+ }
+}
+
+class AppForm extends StatefulWidget {
+ const AppForm({Key? key}) : super(key: key);
+ @override
+ State createState() => _AppFormState();
+}
+
+class _AppFormState extends State {
+
+ @override
+ Widget build(BuildContext context) {
+ ValidateBloc bloc = BlocProvider.of(context);
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Signum form'),
+ ),
+ body: Form(
+ child: Padding(
+ padding: const EdgeInsets.all(10),
+ child: Column(
+ children: [
+ BlocBuilder(
+ bloc: bloc,
+ builder: (context, state) => TextField(
+ onChanged: (value) {
+ bloc.add(ValidateUsernameEvent(value));
+ },
+ decoration: InputDecoration(
+ labelText: 'Username',
+ hintText: 'Pick a username',
+ errorText: state.errorUsername,
+ ),
+ ),
+ ),
+ BlocBuilder(
+ bloc: bloc,
+ builder: (context, state) => TextField(
+ onChanged: (value) {
+ bloc.add(ValidateEmailEvent(value));
+ },
+ decoration: InputDecoration(
+ labelText: 'Email',
+ hintText: 'Enter your email address',
+ errorText: state.errorEmail,
+ ),
+ ),
+ ),
+ BlocBuilder(
+ bloc: bloc,
+ builder: (context, state) => TextField(
+ onChanged: (value) {
+ bloc.add(ValidatePasswordEvent(value));
+ },
+ decoration: InputDecoration(
+ labelText: 'Password',
+ hintText: 'Set a password',
+ errorText: state.errorPassword,
+ ),
+ ),
+ ),
+ ElevatedButton(
+ onPressed: () {},
+ child: const Text('Sign up'),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/flutter_base/pubspec.lock b/flutter_base/pubspec.lock
index c9940bc..8a8b282 100644
--- a/flutter_base/pubspec.lock
+++ b/flutter_base/pubspec.lock
@@ -84,7 +84,7 @@ packages:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
+ version: "2.0.9"
build_runner:
dependency: "direct dev"
description:
@@ -119,7 +119,7 @@ packages:
name: cached_network_image
url: "https://pub.dartlang.org"
source: hosted
- version: "3.2.0"
+ version: "3.2.1"
cached_network_image_platform_interface:
dependency: transitive
description:
@@ -189,14 +189,14 @@ packages:
name: convert
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.3"
+ version: "0.3.3+1"
crypto:
dependency: transitive
description:
@@ -210,7 +210,7 @@ packages:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.4"
+ version: "1.0.5"
dart_style:
dependency: transitive
description:
@@ -245,7 +245,7 @@ packages:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.2"
+ version: "1.2.1"
file:
dependency: transitive
description:
@@ -259,7 +259,7 @@ packages:
name: file_picker
url: "https://pub.dartlang.org"
source: hosted
- version: "4.5.1"
+ version: "4.6.1"
fixnum:
dependency: transitive
description:
@@ -285,7 +285,7 @@ packages:
name: flutter_blurhash
url: "https://pub.dartlang.org"
source: hosted
- version: "0.6.8"
+ version: "0.7.0"
flutter_cache_manager:
dependency: transitive
description:
@@ -320,7 +320,7 @@ packages:
name: flutter_form_builder
url: "https://pub.dartlang.org"
source: hosted
- version: "7.1.1"
+ version: "7.2.1"
flutter_keyboard_visibility:
dependency: transitive
description:
@@ -374,7 +374,7 @@ packages:
name: flutter_rating_bar
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -475,7 +475,7 @@ packages:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
image:
dependency: transitive
description:
@@ -496,7 +496,7 @@ packages:
name: image_picker_android
url: "https://pub.dartlang.org"
source: hosted
- version: "0.8.4+13"
+ version: "0.8.5"
image_picker_for_web:
dependency: transitive
description:
@@ -510,7 +510,7 @@ packages:
name: image_picker_ios
url: "https://pub.dartlang.org"
source: hosted
- version: "0.8.5+2"
+ version: "0.8.5+5"
image_picker_platform_interface:
dependency: transitive
description:
@@ -622,7 +622,7 @@ packages:
name: octo_image
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.1"
+ version: "1.0.2"
package_config:
dependency: transitive
description:
@@ -643,49 +643,49 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.9"
+ version: "2.0.11"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.13"
+ version: "2.0.14"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.8"
+ version: "2.0.9"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.5"
+ version: "2.1.7"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ version: "2.0.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.3"
+ version: "2.0.4"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ version: "2.0.7"
pedantic:
dependency: transitive
description:
@@ -776,7 +776,7 @@ packages:
name: provider
url: "https://pub.dartlang.org"
source: hosted
- version: "6.0.2"
+ version: "6.0.3"
pub_semver:
dependency: transitive
description:
@@ -804,42 +804,42 @@ packages:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
- version: "0.27.3"
+ version: "0.27.4"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.13"
+ version: "2.0.15"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.11"
+ version: "2.0.12"
shared_preferences_ios:
dependency: transitive
description:
name: shared_preferences_ios
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.3"
+ version: "2.0.4"
shared_preferences_platform_interface:
dependency: transitive
description:
@@ -853,14 +853,14 @@ packages:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.3"
+ version: "2.0.4"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
shelf:
dependency: transitive
description:
@@ -881,7 +881,7 @@ packages:
name: signature
url: "https://pub.dartlang.org"
source: hosted
- version: "5.0.0"
+ version: "5.0.1"
sky_engine:
dependency: transitive
description: flutter
@@ -977,7 +977,7 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0"
+ version: "1.3.1"
uuid:
dependency: transitive
description:
@@ -1026,7 +1026,7 @@ packages:
name: win32
url: "https://pub.dartlang.org"
source: hosted
- version: "2.5.2"
+ version: "2.6.1"
xdg_directories:
dependency: transitive
description:
@@ -1050,4 +1050,4 @@ packages:
version: "3.1.1"
sdks:
dart: ">=2.17.0 <3.0.0"
- flutter: ">=2.8.1"
+ flutter: ">=3.0.0"