277 lines
10 KiB
Dart
277 lines
10 KiB
Dart
import 'package:easy_localization/easy_localization.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/enmus.dart';
|
|
import '../../../common/translations/locale_keys.g.dart';
|
|
import '../../../common/ui_helpers.dart';
|
|
import '../../../widgets/custom_elevated_button.dart';
|
|
import '../../../widgets/large_app_bar.dart';
|
|
import '../../../widgets/obscure_password.dart';
|
|
import '../../../widgets/page_loading_indicator.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.registerWithEmail(SignUpMethod.email);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context, RegisterViewModel viewModel) =>
|
|
_buildScaffoldWrapper(viewModel);
|
|
|
|
Widget _buildScaffoldWrapper(RegisterViewModel viewModel) => Scaffold(
|
|
backgroundColor: kcBackgroundColor,
|
|
body: _buildScaffoldContainer(viewModel),
|
|
);
|
|
|
|
Widget _buildScaffoldContainer(RegisterViewModel viewModel) => Container(
|
|
decoration: bgDecoration,
|
|
child: _buildScaffoldStack(viewModel),
|
|
);
|
|
|
|
Widget _buildScaffoldStack(RegisterViewModel viewModel) => Stack(
|
|
children: [
|
|
_buildScaffold(viewModel),
|
|
_buildRegistrationState(viewModel),
|
|
],
|
|
);
|
|
|
|
Widget _buildScaffold(RegisterViewModel viewModel) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: _buildScaffoldChildren(viewModel),
|
|
);
|
|
|
|
List<Widget> _buildScaffoldChildren(RegisterViewModel viewModel) => [
|
|
_buildAppBar(viewModel),
|
|
verticalSpaceMedium,
|
|
_buildExpandedBody(viewModel)
|
|
];
|
|
|
|
Widget _buildAppBar(RegisterViewModel viewModel) => LargeAppBar(
|
|
showBackButton: true,
|
|
onPop: viewModel.goBack,
|
|
showLanguageSelection: true,
|
|
language: viewModel.selectedLanguage['code'],
|
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
);
|
|
|
|
Widget _buildExpandedBody(RegisterViewModel viewModel) =>
|
|
Expanded(child: _buildColumnScroller(viewModel));
|
|
|
|
Widget _buildColumnScroller(RegisterViewModel viewModel) =>
|
|
SingleChildScrollView(
|
|
child: _buildBodyWrapper(viewModel),
|
|
);
|
|
|
|
Widget _buildBodyWrapper(RegisterViewModel viewModel) => Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 15),
|
|
child: _buildBody(viewModel),
|
|
);
|
|
|
|
Widget _buildBody(RegisterViewModel viewModel) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: _buildBodyColumnChildren(viewModel),
|
|
);
|
|
|
|
List<Widget> _buildBodyColumnChildren(RegisterViewModel viewModel) => [
|
|
verticalSpaceMedium,
|
|
_buildTitle(),
|
|
verticalSpaceMedium,
|
|
_buildPasswordLabel(LocaleKeys.password.tr()),
|
|
verticalSpaceSmall,
|
|
_buildPasswordFormField(viewModel),
|
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
|
verticalSpaceTiny,
|
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
|
_buildPasswordValidationWrapper(viewModel),
|
|
verticalSpaceMedium,
|
|
_buildPasswordLabel(LocaleKeys.confirm_password.tr()),
|
|
verticalSpaceSmall,
|
|
_buildConfirmPasswordFormField(viewModel),
|
|
if (viewModel.hasConfirmPasswordValidationMessage &&
|
|
viewModel.focusConfirmPassword)
|
|
verticalSpaceTiny,
|
|
if (viewModel.hasConfirmPasswordValidationMessage &&
|
|
viewModel.focusConfirmPassword)
|
|
_buildConfirmPasswordValidationWrapper(viewModel),
|
|
verticalSpaceMedium,
|
|
_buildLinearProgressIndicator(viewModel),
|
|
verticalSpaceSmall,
|
|
_buildCharLengthValidator(viewModel),
|
|
_buildPasswordMatchValidator(viewModel),
|
|
_buildCheckBox(viewModel),
|
|
verticalSpaceSmall,
|
|
_buildSignUpButton(viewModel),
|
|
verticalSpaceMedium
|
|
];
|
|
|
|
Widget _buildTitle() => Text(
|
|
LocaleKeys.create_password.tr(),
|
|
style: style25DG600,
|
|
);
|
|
|
|
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: LocaleKeys.password.tr(),
|
|
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: style12R700,
|
|
);
|
|
|
|
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(
|
|
focus: viewModel.focusConfirmPassword,
|
|
hint: LocaleKeys.confirm_password.tr(),
|
|
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: style12R700,
|
|
);
|
|
|
|
Widget _buildLinearProgressIndicator(RegisterViewModel viewModel) =>
|
|
CustomLinearProgressIndicator(
|
|
activeColor: kcPrimaryColor,
|
|
backgroundColor: kcVeryLightGrey,
|
|
progress: viewModel.validationProgress(),
|
|
);
|
|
|
|
Widget _buildCharLengthValidator(RegisterViewModel viewModel) =>
|
|
ValidatorListTile(
|
|
label: LocaleKeys.eight_character_minimum.tr(),
|
|
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
|
|
);
|
|
|
|
Widget _buildPasswordMatchValidator(RegisterViewModel viewModel) =>
|
|
ValidatorListTile(
|
|
label: LocaleKeys.password_match.tr(),
|
|
backgroundColor: viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
|
|
);
|
|
|
|
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: LocaleKeys.sign_up_agreement.tr(),
|
|
style: style14DG400,
|
|
children: [
|
|
TextSpan(
|
|
text: ' ${LocaleKeys.terms_of_services.tr()}',
|
|
style: style14P600,
|
|
recognizer: TapGestureRecognizer()
|
|
..onTap = () => viewMode.navigateToTermsAndConditions()),
|
|
TextSpan(text: ' ${LocaleKeys.and.tr()} ', style: style14DG400),
|
|
TextSpan(
|
|
style: style14P600,
|
|
text: LocaleKeys.privacy_policy.tr(),
|
|
recognizer: TapGestureRecognizer()
|
|
..onTap = () => viewMode.navigateToPrivacyPolicy()),
|
|
]),
|
|
);
|
|
|
|
Widget _buildSignUpButton(RegisterViewModel viewModel) =>
|
|
CustomElevatedButton(
|
|
height: 55,
|
|
borderRadius: 12,
|
|
foregroundColor: kcWhite,
|
|
text: LocaleKeys.register.tr(),
|
|
onTap: passwordController.text.isNotEmpty &&
|
|
confirmPasswordController.text.isNotEmpty &&
|
|
viewModel.length &&
|
|
viewModel.passwordMatch &&
|
|
viewModel.agree
|
|
? () async => await _signUp(viewModel)
|
|
: null,
|
|
backgroundColor: passwordController.text.isNotEmpty &&
|
|
confirmPasswordController.text.isNotEmpty &&
|
|
viewModel.length &&
|
|
viewModel.passwordMatch &&
|
|
viewModel.agree
|
|
? kcPrimaryColor
|
|
: kcPrimaryColor.withOpacity(0.1),
|
|
);
|
|
|
|
Widget _buildRegistrationState(RegisterViewModel viewModel) =>
|
|
viewModel.busy(StateObjects.register)
|
|
? const PageLoadingIndicator()
|
|
: Container();
|
|
}
|