Skip to content

Instantly share code, notes, and snippets.

@albertusdev
Created March 20, 2019 15:20
Show Gist options
  • Save albertusdev/ba7ba967b37a58e97810b1806767b2b4 to your computer and use it in GitHub Desktop.
Save albertusdev/ba7ba967b37a58e97810b1806767b2b4 to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:learn_fazz/app_config.dart';
import 'package:learn_fazz/models/login_result.dart';
import 'package:learn_fazz/pages/dashboard_page.dart';
import 'package:learn_fazz/repositories/auth_repository.dart';
import 'package:learn_fazz/widgets/image_picker_bottom_sheet.dart';
import '../assets/learn_fazz_icons.dart';
class RegisterFormPage extends StatefulWidget {
static String tag = '/register-form-page';
static String kNoImageErrorMessage =
'Please choose image first to be able to proceed.';
@override
_RegisterFormPageState createState() => _RegisterFormPageState();
}
class _RegisterFormPageState extends State<RegisterFormPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> _passKey =
GlobalKey<FormFieldState<String>>();
final Color borderColor = Colors.black.withOpacity(0.4);
bool passwordVisible = true;
bool confirmPasswordVisible = true;
bool _isSubmitting = false;
String _name;
String _email;
String _identificationNumber;
String _password;
String _passwordConfirmation;
String _role;
File _imageFile;
@override
Widget build(BuildContext context) {
final Widget logo = _imageFile == null
? Container(
child: CircleAvatar(
radius: 72.0,
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
child: const Icon(LearnFazz.camera, size: 50.0),
),
padding: const EdgeInsets.all(2.0), // border width
decoration: const BoxDecoration(
color: Colors.white, // border color
shape: BoxShape.circle,
),
)
: CircleAvatar(
radius: 72.0,
child: ClipOval(child: Image.file(_imageFile)),
);
final Widget addPhotoLabel = InkWell(
child: const Text(
'Add Photo',
key: Key('addPhotoLabel'),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0,
decoration: TextDecoration.underline,
color: Colors.white),
textAlign: TextAlign.center,
),
onTap: () async {
final File _choosenImage = await showImagePickerBottomSheet(context);
setState(() => _imageFile = _choosenImage);
},
);
final TextFormField name = TextFormField(
autofocus: true,
validator: (String value) {
if (value.isEmpty) {
return 'Name cannot be empty';
}
},
onSaved: (String val) => _name = val,
style: const TextStyle(color: Colors.black, fontSize: 16.0),
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Name',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(width: 1.5, color: borderColor),
),
prefixIcon: const Icon(LearnFazz.person_outline),
),
);
final TextFormField email = TextFormField(
keyboardType: TextInputType.emailAddress,
validator: (String value) {
if (value.isEmpty) {
return 'Email cannot be empty';
} else if (value.isNotEmpty && !value.contains('@gmail.')) {
return 'Invalid email address';
}
},
onSaved: (String val) => _email = val,
style: const TextStyle(color: Colors.black, fontSize: 16.0),
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Email',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(width: 1.5, color: borderColor),
),
prefixIcon: const Icon(LearnFazz.mail),
),
);
final TextFormField idNumber = TextFormField(
keyboardType: TextInputType.number,
validator: (String value) {
if (value.isEmpty) {
return 'Identification number cannot be empty';
}
},
onSaved: (String identificationNumber) =>
_identificationNumber = identificationNumber,
style: const TextStyle(color: Colors.black, fontSize: 16.0),
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Identification Number',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(width: 1.5, color: borderColor),
),
prefixIcon: const Icon(LearnFazz.id_card),
),
);
final TextFormField password = TextFormField(
validator: (String value) {
if (value.isEmpty) {
return 'Password cannot be empty';
} else if (value.length < 8) {
return 'Password should\'ve at least 8 characters';
}
},
onSaved: (String password) => _password = password,
style: const TextStyle(color: Colors.black, fontSize: 16.0),
obscureText: passwordVisible,
key: _passKey,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Password',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(width: 1.5, color: borderColor),
),
prefixIcon: const Icon(LearnFazz.lock),
suffixIcon: IconButton(
icon: Icon(passwordVisible ? LearnFazz.eye : Icons.visibility_off),
onPressed: () {
setState(() {
passwordVisible
? passwordVisible = false
: passwordVisible = true;
});
}),
),
);
final TextFormField confirmPassword = TextFormField(
validator: (String value) {
final String password = _passKey.currentState.value;
return (value == password) ? null : 'Password doesn\'t match';
},
onSaved: (String passwordConfirmation) =>
_passwordConfirmation = passwordConfirmation,
style: const TextStyle(color: Colors.black, fontSize: 16.0),
obscureText: confirmPasswordVisible,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Confirm Password',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0),
borderSide: BorderSide(width: 1.5, color: borderColor),
),
prefixIcon: const Icon(LearnFazz.lock),
suffixIcon: IconButton(
icon: Icon(
confirmPasswordVisible ? LearnFazz.eye : Icons.visibility_off),
onPressed: () {
setState(() {
confirmPasswordVisible
? confirmPasswordVisible = false
: confirmPasswordVisible = true;
});
},
),
),
);
final Widget bottomNavigationBar =
_isSubmitting ? LinearProgressIndicator() : null;
return Scaffold(
body: Builder(
builder: (BuildContext context) => Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
'lib/assets/images/blue-white-pattern-background.png'),
fit: BoxFit.cover,
)),
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.only(
top: 100.0, left: 45.0, right: 45.0, bottom: 40.0),
children: <Widget>[
logo,
const SizedBox(height: 10.0),
addPhotoLabel,
const SizedBox(height: 30.0),
name,
const SizedBox(height: 8.0),
email,
const SizedBox(height: 8.0),
idNumber,
const SizedBox(height: 8.0),
password,
const SizedBox(height: 8.0),
confirmPassword,
const SizedBox(height: 30.0),
InkWell(
key: const Key('registerButton'),
onTap: () => _validateThenPostToBackend(context),
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: _isSubmitting
? Colors.grey
: const Color(0xFF3A8FF3),
borderRadius: BorderRadius.circular(30.0),
),
child: const Center(
child: Text(
'Register',
style: TextStyle(fontSize: 18.0, color: Colors.white),
),
),
),
),
],
),
)),
),
bottomNavigationBar: bottomNavigationBar,
);
}
Future<void> _validateThenPostToBackend(BuildContext context) async {
if (_isSubmitting) {
return;
}
if (_formKey.currentState.validate()) {
setState(() => _isSubmitting = true);
_formKey.currentState.save();
try {
if (_imageFile == null) {
throw RegisterFormPage.kNoImageErrorMessage;
}
final AuthRepository authRepository =
AppConfig.of(context).authRepository;
final LoginResult response = await authRepository.register(
name: _name,
email: _email,
identificationNumber: _identificationNumber,
password: _password,
passwordConfirmation: _passwordConfirmation,
role: _role,
photo: _imageFile,
);
Navigator.of(context).push<dynamic>(MaterialPageRoute<dynamic>(
builder: (BuildContext context) => DashboardPage(user: response.user),
));
} catch (e) {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(e.toString()), duration: const Duration(seconds: 5)));
}
setState(() => _isSubmitting = false);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment