Yimaru-Mobile/lib/ui/views/register/screens/create_password_screen.dart

252 lines
9.2 KiB
Dart

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:yimaru_app/ui/views/register/register_viewmodel.dart';
import 'package:yimaru_app/ui/widgets/custom_form_label.dart';
import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart';
import 'package:yimaru_app/ui/widgets/validator_list_tile.dart';
import '../../../common/app_colors.dart';
import '../../../common/ui_helpers.dart';
import '../../../widgets/custom_elevated_button.dart';
import '../../../widgets/obscure_password.dart';
import '../register_view.form.dart';
class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
final TextEditingController passwordController;
final TextEditingController confirmPasswordController;
const CreatePasswordScreen(
{super.key,
required this.passwordController,
required this.confirmPasswordController});
Future<void> _signUp(RegisterViewModel viewModel) async {
FocusManager.instance.primaryFocus?.unfocus();
Map<String, dynamic> data = {
'role': 'STUDENT',
'otp_medium': 'email',
'password': passwordController.text,
};
viewModel.addUserData(data);
await viewModel.register();
}
@override
Widget build(BuildContext context, RegisterViewModel viewModel) =>
_buildBodyChildren(viewModel);
Widget _buildBodyChildren(RegisterViewModel viewModel) =>
SingleChildScrollView(
child: _buildBodyColumn(viewModel),
);
Widget _buildBodyColumn(RegisterViewModel viewModel) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildBodyColumnChildren(viewModel),
);
List<Widget> _buildBodyColumnChildren(RegisterViewModel viewModel) => [
verticalSpaceMedium,
_buildTitle(),
verticalSpaceMedium,
_buildPasswordLabel('Password'),
verticalSpaceSmall,
_buildPasswordFormField(viewModel),
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
verticalSpaceTiny,
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
_buildPasswordValidationWrapper(viewModel),
verticalSpaceMedium,
_buildPasswordLabel('Confirm Password'),
verticalSpaceSmall,
_buildConfirmPasswordFormField(viewModel),
if (viewModel.hasConfirmPasswordValidationMessage &&
viewModel.focusConfirmPassword)
verticalSpaceTiny,
if (viewModel.hasConfirmPasswordValidationMessage &&
viewModel.focusConfirmPassword)
_buildConfirmPasswordValidationWrapper(viewModel),
verticalSpaceMedium,
_buildLinearProgressIndicator(viewModel),
verticalSpaceSmall,
_buildCharLengthValidator(viewModel),
_buildNumberValidator(viewModel),
_buildSymbolValidator(viewModel),
_buildPasswordMatchValidator(viewModel),
_buildCheckBox(viewModel),
verticalSpaceSmall,
_buildSignUpButton(viewModel),
verticalSpaceMedium
];
Widget _buildTitle() => const Text(
'Create Password',
style: TextStyle(
fontSize: 25,
color: kcDarkGrey,
fontWeight: FontWeight.w600,
),
);
Widget _buildPasswordLabel(String label) => CustomFormLabel(
label: label,
style: style14DG400,
);
Widget _buildPasswordFormField(RegisterViewModel viewModel) => TextFormField(
controller: passwordController,
onTap: viewModel.setPasswordFocus,
obscureText: viewModel.obscurePassword,
decoration: inputDecoration(
hint: 'Password',
focus: viewModel.focusPassword,
suffix: _buildObscurePassword(viewModel),
filled: passwordController.text.isNotEmpty),
onChanged: (value) => viewModel.validatePassword(
password: passwordController.text,
confirmPassword: confirmPasswordController.text),
);
Widget _buildObscurePassword(RegisterViewModel viewModel) => ObscurePassword(
focus: viewModel.focusPassword,
obscure: viewModel.obscurePassword,
onTap: viewModel.setObscurePassword,
);
Widget _buildPasswordValidationWrapper(RegisterViewModel viewModel) =>
viewModel.hasPasswordValidationMessage
? _buildPasswordValidator(viewModel)
: Container();
Widget _buildPasswordValidator(RegisterViewModel viewModel) => Text(
viewModel.passwordValidationMessage!,
style: const TextStyle(
fontSize: 12,
color: Colors.red,
fontWeight: FontWeight.w700,
),
);
Widget _buildConfirmPasswordFormField(RegisterViewModel viewModel) =>
TextFormField(
controller: confirmPasswordController,
onTap: viewModel.setConfirmPasswordFocus,
obscureText: viewModel.obscureConfirmPassword,
onChanged: (value) => viewModel.validatePassword(
password: passwordController.text,
confirmPassword: confirmPasswordController.text),
decoration: inputDecoration(
hint: 'Confirm Password',
focus: viewModel.focusConfirmPassword,
suffix: _buildObscureConfirmPassword(viewModel),
filled: confirmPasswordController.text.isNotEmpty),
);
Widget _buildObscureConfirmPassword(RegisterViewModel viewModel) =>
ObscurePassword(
focus: viewModel.focusConfirmPassword,
obscure: viewModel.obscureConfirmPassword,
onTap: viewModel.setObscureConfirmPassword,
);
Widget _buildConfirmPasswordValidationWrapper(RegisterViewModel viewModel) =>
viewModel.hasConfirmPasswordValidationMessage
? _buildConfirmPasswordValidator(viewModel)
: Container();
Widget _buildConfirmPasswordValidator(RegisterViewModel viewModel) => Text(
viewModel.confirmPasswordValidationMessage!,
style: const TextStyle(
fontSize: 12,
color: Colors.red,
fontWeight: FontWeight.w700,
),
);
Widget _buildLinearProgressIndicator(RegisterViewModel viewModel) =>
CustomLinearProgressIndicator(
activeColor: kcPrimaryColor,
backgroundColor: kcVeryLightGrey,
progress: viewModel.validationProgress(),
);
Widget _buildCharLengthValidator(RegisterViewModel viewModel) =>
ValidatorListTile(
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
label: '8 characters minimum');
Widget _buildNumberValidator(RegisterViewModel viewModel) =>
ValidatorListTile(
backgroundColor: viewModel.number ? kcPrimaryColor : kcLightGrey,
label: 'a number');
Widget _buildSymbolValidator(RegisterViewModel viewModel) =>
ValidatorListTile(
backgroundColor: viewModel.specialChar ? kcPrimaryColor : kcLightGrey,
label: 'one symbol minimum');
Widget _buildPasswordMatchValidator(RegisterViewModel viewModel) =>
ValidatorListTile(
backgroundColor:
viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
label: 'password match');
Widget _buildCheckBox(RegisterViewModel viewMode) => CheckboxListTile(
value: viewMode.agree,
activeColor: kcPrimaryColor,
title: _buildCheckBoxTitle(viewMode),
controlAffinity: ListTileControlAffinity.leading,
onChanged: (value) => viewMode.setAgreement(value ?? false));
Widget _buildCheckBoxTitle(RegisterViewModel viewMode) => Text.rich(
TextSpan(
text: 'By clicking "Sign Up", you agree to our',
style: style14DG400,
children: [
TextSpan(
text: ' Terms of Service',
style: style14P600,
recognizer: TapGestureRecognizer()
..onTap = () => viewMode.navigateToTermsAndConditions()),
TextSpan(text: ' and ', style: style14DG400),
TextSpan(
text: 'Privacy Policy',
style: style14P600,
recognizer: TapGestureRecognizer()
..onTap = () => viewMode.navigateToPrivacyPolicy()),
]),
);
Widget _buildSignUpButton(RegisterViewModel viewModel) =>
CustomElevatedButton(
height: 55,
text: 'Sign Up',
borderRadius: 12,
foregroundColor: kcWhite,
onTap: passwordController.text.isNotEmpty &&
confirmPasswordController.text.isNotEmpty &&
viewModel.number &&
viewModel.length &&
viewModel.specialChar &&
viewModel.specialChar &&
viewModel.passwordMatch &&
viewModel.agree
? () async => await _signUp(viewModel)
: null,
backgroundColor: passwordController.text.isNotEmpty &&
confirmPasswordController.text.isNotEmpty &&
viewModel.number &&
viewModel.length &&
viewModel.specialChar &&
viewModel.specialChar &&
viewModel.passwordMatch &&
viewModel.agree
? kcPrimaryColor
: kcPrimaryColor.withOpacity(0.1),
);
}