| class LoginForm extends StatelessWidget { | class LoginForm extends StatelessWidget { | ||||
| AuthenticationBloc _authenticationBloc; | AuthenticationBloc _authenticationBloc; | ||||
| FocusNode _usernameFocus = FocusNode(); | |||||
| FocusNode _passwordFocus = FocusNode(); | |||||
| @override | @override | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
| mainAxisSize: MainAxisSize.min, | mainAxisSize: MainAxisSize.min, | ||||
| children: [ | children: [ | ||||
| _UsernameInput(), | |||||
| _UsernameInput( | |||||
| usernameFocus: _usernameFocus, nextFocus: _passwordFocus), | |||||
| const Padding(padding: EdgeInsets.all(12)), | const Padding(padding: EdgeInsets.all(12)), | ||||
| _PasswordInput(), | |||||
| _PasswordInput( | |||||
| passwordFocus: _passwordFocus, | |||||
| ), | |||||
| const Padding(padding: EdgeInsets.all(16)), | const Padding(padding: EdgeInsets.all(16)), | ||||
| _LoginButton(), | _LoginButton(), | ||||
| const Padding(padding: EdgeInsets.all(6)), | const Padding(padding: EdgeInsets.all(6)), | ||||
| } | } | ||||
| class _UsernameInput extends StatelessWidget { | class _UsernameInput extends StatelessWidget { | ||||
| final FocusNode usernameFocus; | |||||
| final FocusNode nextFocus; | |||||
| _UsernameInput({@required this.usernameFocus, @required this.nextFocus}); | |||||
| @override | @override | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| return BlocBuilder<LoginBloc, LoginState>( | return BlocBuilder<LoginBloc, LoginState>( | ||||
| color: COLOR_CONST.GRAY7), | color: COLOR_CONST.GRAY7), | ||||
| child: Center( | child: Center( | ||||
| child: TextFormField( | child: TextFormField( | ||||
| focusNode: usernameFocus, | |||||
| textInputAction: TextInputAction.next, | |||||
| onChanged: (username) => context | onChanged: (username) => context | ||||
| .bloc<LoginBloc>() | .bloc<LoginBloc>() | ||||
| .add(LoginUsernameChanged(username)), | .add(LoginUsernameChanged(username)), | ||||
| ? 'Vui lòng nhập tên đăng nhập' | ? 'Vui lòng nhập tên đăng nhập' | ||||
| : null; | : null; | ||||
| }, | }, | ||||
| onFieldSubmitted: (_) { | |||||
| usernameFocus.unfocus(); | |||||
| FocusScope.of(context).requestFocus(nextFocus); | |||||
| }, | |||||
| maxLines: 1, | maxLines: 1, | ||||
| keyboardType: TextInputType.text, | keyboardType: TextInputType.text, | ||||
| obscureText: false, | obscureText: false, | ||||
| } | } | ||||
| class _PasswordInput extends StatelessWidget { | class _PasswordInput extends StatelessWidget { | ||||
| final FocusNode passwordFocus; | |||||
| _PasswordInput({this.passwordFocus}); | |||||
| @override | @override | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| return BlocBuilder<LoginBloc, LoginState>( | return BlocBuilder<LoginBloc, LoginState>( | ||||
| color: COLOR_CONST.GRAY7), | color: COLOR_CONST.GRAY7), | ||||
| child: Center( | child: Center( | ||||
| child: TextFormField( | child: TextFormField( | ||||
| focusNode: passwordFocus, | |||||
| onChanged: (password) => context | onChanged: (password) => context | ||||
| .bloc<LoginBloc>() | .bloc<LoginBloc>() | ||||
| .add(LoginPasswordChanged(password)), | .add(LoginPasswordChanged(password)), | ||||
| ? 'Vui lòng nhập mật khẩu' | ? 'Vui lòng nhập mật khẩu' | ||||
| : null; | : null; | ||||
| }, | }, | ||||
| onFieldSubmitted: (_) { | |||||
| passwordFocus.unfocus(); | |||||
| if (state.status.isValidated) { | |||||
| context.bloc<LoginBloc>().add(const LoginSubmitted()); | |||||
| } | |||||
| }, | |||||
| maxLines: 1, | maxLines: 1, | ||||
| keyboardType: TextInputType.text, | keyboardType: TextInputType.text, | ||||
| obscureText: false, | |||||
| obscureText: true, | |||||
| textAlign: TextAlign.left, | textAlign: TextAlign.left, | ||||
| decoration: InputDecoration.collapsed( | decoration: InputDecoration.collapsed( | ||||
| hintText: 'Mật khẩu', | hintText: 'Mật khẩu', |