215 lines
7.1 KiB
Dart
215 lines
7.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:stacked/stacked.dart';
|
|
import 'package:yimaru_app/ui/views/login/login_view.form.dart';
|
|
import 'package:yimaru_app/ui/widgets/obscure_password.dart';
|
|
|
|
import '../../../common/app_colors.dart';
|
|
import '../../../common/ui_helpers.dart';
|
|
import '../../../widgets/custom_elevated_button.dart';
|
|
import '../../../widgets/option_text_divider.dart';
|
|
import '../../../widgets/register_for_account.dart';
|
|
import '../login_viewmodel.dart';
|
|
|
|
class LoginWithEmailScreen extends ViewModelWidget<LoginViewModel> {
|
|
final TextEditingController emailController;
|
|
final TextEditingController passwordController;
|
|
|
|
const LoginWithEmailScreen(
|
|
{super.key,
|
|
required this.emailController,
|
|
required this.passwordController});
|
|
|
|
Future<void> _login(LoginViewModel viewModel) async {
|
|
FocusManager.instance.primaryFocus?.unfocus();
|
|
|
|
Map<String, dynamic> data = {
|
|
'email': emailController.text,
|
|
'password': passwordController.text,
|
|
};
|
|
viewModel.addUserData(data);
|
|
|
|
await viewModel.emailLogin();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context, LoginViewModel viewModel) =>
|
|
_buildBody(viewModel);
|
|
|
|
Widget _buildBody(LoginViewModel viewModel) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: _buildBodyChildren(viewModel),
|
|
);
|
|
|
|
List<Widget> _buildBodyChildren(LoginViewModel viewModel) =>
|
|
[_buildColumnScroller(viewModel), _buildLowerColumn(viewModel)];
|
|
|
|
Widget _buildColumnScroller(LoginViewModel viewModel) =>
|
|
SingleChildScrollView(
|
|
child: _buildUpperColumn(viewModel),
|
|
);
|
|
|
|
Widget _buildUpperColumn(LoginViewModel viewModel) => Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: _buildUpperColumnChildren(viewModel),
|
|
);
|
|
|
|
List<Widget> _buildUpperColumnChildren(LoginViewModel viewModel) => [
|
|
verticalSpaceMedium,
|
|
_buildTitle(),
|
|
_buildSubTitleWrapper(viewModel),
|
|
verticalSpaceLarge,
|
|
_buildEmailFormField(viewModel),
|
|
if (viewModel.hasEmailValidationMessage && viewModel.focusEmail)
|
|
verticalSpaceTiny,
|
|
if (viewModel.hasEmailValidationMessage && viewModel.focusEmail)
|
|
_buildEmailValidatorWrapper(viewModel),
|
|
verticalSpaceMedium,
|
|
_buildPasswordFormField(viewModel),
|
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
|
verticalSpaceTiny,
|
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
|
_buildPasswordValidationWrapper(viewModel),
|
|
_buildForgetPasswordTextButtonWrapper(),
|
|
];
|
|
|
|
Widget _buildTitle() => const Text(
|
|
'Welcome Back',
|
|
style: TextStyle(
|
|
fontSize: 25,
|
|
color: kcDarkGrey,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
);
|
|
|
|
Widget _buildSubTitleWrapper(LoginViewModel viewModel) => RegisterForAccount(
|
|
onTap: () async => await viewModel.navigateToRegister(),
|
|
);
|
|
|
|
Widget _buildEmailFormField(LoginViewModel viewModel) => TextFormField(
|
|
controller: emailController,
|
|
keyboardType: TextInputType.emailAddress,
|
|
onTap: viewModel.setEmailFocus,
|
|
decoration: inputDecoration(
|
|
hint: 'Email',
|
|
focus: viewModel.focusEmail,
|
|
filled: emailController.text.isNotEmpty),
|
|
);
|
|
|
|
Widget _buildEmailValidatorWrapper(LoginViewModel viewModel) =>
|
|
viewModel.hasEmailValidationMessage
|
|
? _buildEmailValidator(viewModel)
|
|
: Container();
|
|
|
|
Widget _buildEmailValidator(LoginViewModel viewModel) => Text(
|
|
viewModel.emailValidationMessage!,
|
|
style: const TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.red,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
);
|
|
|
|
Widget _buildPasswordFormField(LoginViewModel viewModel) => TextFormField(
|
|
controller: passwordController,
|
|
onTap: viewModel.setPasswordFocus,
|
|
obscureText: viewModel.obscurePassword,
|
|
decoration: inputDecoration(
|
|
hint: 'Password',
|
|
focus: viewModel.focusPassword,
|
|
suffix: _buildObscureButton(viewModel),
|
|
filled: passwordController.text.isNotEmpty),
|
|
);
|
|
|
|
Widget _buildObscureButton(LoginViewModel viewModel) => ObscurePassword(
|
|
focus: viewModel.focusPassword,
|
|
obscure: viewModel.obscurePassword,
|
|
onTap: viewModel.setObscurePassword,
|
|
);
|
|
|
|
Widget _buildPasswordValidationWrapper(LoginViewModel viewModel) =>
|
|
viewModel.hasPasswordValidationMessage
|
|
? _buildPasswordValidator(viewModel)
|
|
: Container();
|
|
|
|
Widget _buildPasswordValidator(LoginViewModel viewModel) => Text(
|
|
viewModel.passwordValidationMessage!,
|
|
style: const TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.red,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
);
|
|
|
|
Widget _buildForgetPasswordTextButtonWrapper() => Align(
|
|
alignment: Alignment.centerRight,
|
|
child: _buildForgetPasswordTextButton(),
|
|
);
|
|
|
|
Widget _buildForgetPasswordTextButton() => TextButton(
|
|
onPressed: () {},
|
|
child: _buildForgetPasswordText(),
|
|
);
|
|
|
|
Widget _buildForgetPasswordText() => const Text(
|
|
'Forget Password?',
|
|
style: TextStyle(color: kcPrimaryColor),
|
|
);
|
|
|
|
Widget _buildLowerColumn(LoginViewModel viewModel) => Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: _buildLowerColumnChildren(viewModel),
|
|
);
|
|
|
|
List<Widget> _buildLowerColumnChildren(LoginViewModel viewModel) => [
|
|
_buildContinueButton(viewModel),
|
|
_buildLoginWithGoogleButton(viewModel),
|
|
_buildOptionTextDivider(),
|
|
_buildLoginWithPhoneButton(viewModel),
|
|
verticalSpaceMedium
|
|
];
|
|
|
|
Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton(
|
|
height: 55,
|
|
safe: false,
|
|
text: 'Continue',
|
|
borderRadius: 12,
|
|
foregroundColor: kcWhite,
|
|
onTap: emailController.text.isNotEmpty &&
|
|
passwordController.text.isNotEmpty
|
|
? () async => await _login(viewModel)
|
|
: null,
|
|
backgroundColor: emailController.text.isNotEmpty &&
|
|
passwordController.text.isNotEmpty
|
|
? kcPrimaryColor
|
|
: kcPrimaryColor.withOpacity(0.1),
|
|
);
|
|
|
|
Widget _buildLoginWithGoogleButton(LoginViewModel viewModel) =>
|
|
CustomElevatedButton(
|
|
height: 55,
|
|
borderRadius: 12,
|
|
backgroundColor: kcWhite,
|
|
text: 'Login with Google',
|
|
borderColor: kcPrimaryColor,
|
|
foregroundColor: kcPrimaryColor,
|
|
leadingImage: 'assets/icons/google.png',
|
|
onTap: () async => await viewModel.googleLogin(),
|
|
);
|
|
|
|
Widget _buildOptionTextDivider() => const OptionTextDivider();
|
|
|
|
Widget _buildLoginWithPhoneButton(LoginViewModel viewModel) =>
|
|
CustomElevatedButton(
|
|
height: 55,
|
|
borderRadius: 12,
|
|
backgroundColor: kcWhite,
|
|
leadingIcon: Icons.phone,
|
|
borderColor: kcPrimaryColor,
|
|
foregroundColor: kcPrimaryColor,
|
|
text: 'Login with Phone Number',
|
|
onTap: () => viewModel.goTo(1),
|
|
);
|
|
}
|