mirror of
https://github.com/Iconica-Development/flutter_registration.git
synced 2025-05-19 05:23:43 +02:00
refactor: go to previous step + email validation fix
This commit is contained in:
parent
1f54717cf3
commit
7f36ab8eca
2 changed files with 112 additions and 85 deletions
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_registration/src/model/auth_action.dart';
|
|
||||||
import 'package:flutter_registration/src/model/auth_field.dart';
|
import 'package:flutter_registration/src/model/auth_field.dart';
|
||||||
import 'package:flutter_registration/src/model/auth_step.dart';
|
import 'package:flutter_registration/src/model/auth_step.dart';
|
||||||
|
|
||||||
|
@ -10,7 +9,6 @@ class AuthScreen extends StatefulWidget {
|
||||||
required this.steps,
|
required this.steps,
|
||||||
required this.submitBtnTitle,
|
required this.submitBtnTitle,
|
||||||
required this.onFinish,
|
required this.onFinish,
|
||||||
this.actions,
|
|
||||||
super.key,
|
super.key,
|
||||||
}) : assert(steps.length > 0, 'At least one step is required');
|
}) : assert(steps.length > 0, 'At least one step is required');
|
||||||
|
|
||||||
|
@ -18,15 +16,16 @@ class AuthScreen extends StatefulWidget {
|
||||||
final Function(HashMap<String, String>) onFinish;
|
final Function(HashMap<String, String>) onFinish;
|
||||||
final List<AuthStep> steps;
|
final List<AuthStep> steps;
|
||||||
final String submitBtnTitle;
|
final String submitBtnTitle;
|
||||||
final List<AuthAction>? actions;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AuthScreen> createState() => _AuthScreenState();
|
State<AuthScreen> createState() => _AuthScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AuthScreenState extends State<AuthScreen> {
|
class _AuthScreenState extends State<AuthScreen> {
|
||||||
int _index = 0;
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final _pageController = PageController();
|
||||||
|
final _animationDuration = const Duration(milliseconds: 300);
|
||||||
|
final _animationCurve = Curves.ease;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -37,89 +36,117 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||||
),
|
),
|
||||||
body: Form(
|
body: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: PageView(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
children: [
|
controller: _pageController,
|
||||||
const Spacer(),
|
children: <Widget>[
|
||||||
Padding(
|
for (AuthStep step in widget.steps)
|
||||||
padding: const EdgeInsets.symmetric(
|
Column(
|
||||||
vertical: 8.0,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
horizontal: 30.0,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
Column(
|
const Spacer(),
|
||||||
children: [
|
Padding(
|
||||||
for (AuthField field in widget.steps[_index].fields)
|
padding: const EdgeInsets.symmetric(
|
||||||
Column(
|
vertical: 8.0,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
horizontal: 30.0,
|
||||||
children: [
|
),
|
||||||
Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.only(
|
children: [
|
||||||
top: 24.0,
|
for (AuthField field in step.fields)
|
||||||
bottom: 12.0,
|
Column(
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Text(
|
children: [
|
||||||
field.title,
|
Padding(
|
||||||
style: const TextStyle(
|
padding: const EdgeInsets.only(
|
||||||
fontWeight: FontWeight.bold,
|
top: 24.0,
|
||||||
|
bottom: 12.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
field.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
field.build(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(30.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: widget.steps.first != step
|
||||||
|
? MainAxisAlignment.spaceBetween
|
||||||
|
: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
if (widget.steps.first != step)
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => _pageController.previousPage(
|
||||||
|
duration: _animationDuration,
|
||||||
|
curve: _animationCurve,
|
||||||
),
|
),
|
||||||
field.build(),
|
child: Row(
|
||||||
],
|
children: [
|
||||||
)
|
const Icon(
|
||||||
],
|
Icons.arrow_back,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 4.0),
|
||||||
|
child: Text('Vorige stap'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (!_formKey.currentState!.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.steps.last == step) {
|
||||||
|
var values = HashMap<String, String>();
|
||||||
|
|
||||||
|
for (var step in widget.steps) {
|
||||||
|
for (var field in step.fields) {
|
||||||
|
values[field.name] = field.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.onFinish(values);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pageController.nextPage(
|
||||||
|
duration: _animationDuration,
|
||||||
|
curve: _animationCurve,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
widget.steps.last == step
|
||||||
|
? widget.submitBtnTitle
|
||||||
|
: 'Volgende stap',
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 4.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.arrow_forward,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(30.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
minimumSize: const Size.fromHeight(50),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if (!_formKey.currentState!.validate()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (widget.steps.length > _index + 1) {
|
|
||||||
setState(() {
|
|
||||||
_index++;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var values = HashMap<String, String>();
|
|
||||||
|
|
||||||
for (var step in widget.steps) {
|
|
||||||
for (var field in step.fields) {
|
|
||||||
values[field.name] = field.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
widget.onFinish(values);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
widget.steps.length > _index + 1
|
|
||||||
? 'Volgende stap'
|
|
||||||
: widget.submitBtnTitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
for (AuthAction action in widget.actions ?? [])
|
|
||||||
TextButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
minimumSize: const Size.fromHeight(40),
|
|
||||||
),
|
|
||||||
onPressed: action.onPress,
|
|
||||||
child: Text(action.title),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -55,11 +55,11 @@ class RegistrationScreen extends StatelessWidget {
|
||||||
(email) => (email == null || email.isEmpty)
|
(email) => (email == null || email.isEmpty)
|
||||||
? 'Geef uw e-mailadres op'
|
? 'Geef uw e-mailadres op'
|
||||||
: null,
|
: null,
|
||||||
(email) => RegExp(
|
(email) =>
|
||||||
r'^.+@[a-zA-Z]+\.{1}[a-zA-Z]+(\.{0,1}[a-zA-Z]+)$',
|
RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
|
||||||
).hasMatch(email!)
|
.hasMatch(email!)
|
||||||
? 'Geef een geldig e-mailadres op'
|
? null
|
||||||
: null,
|
: 'Geef een geldig e-mailadres op',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue