Password field checks for match with old password from db and check so that new password feild matches with the confirm password field
This commit is contained in:
@@ -10,6 +10,8 @@ class ConfirmPasswordField extends StatelessWidget {
|
|||||||
required this.newPasswordController,
|
required this.newPasswordController,
|
||||||
required this.missingPasswordError,
|
required this.missingPasswordError,
|
||||||
required this.passwordsDoNotMatchError,
|
required this.passwordsDoNotMatchError,
|
||||||
|
required this.obscureText,
|
||||||
|
required this.onToggleVisibility,
|
||||||
});
|
});
|
||||||
|
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
@@ -19,6 +21,8 @@ class ConfirmPasswordField extends StatelessWidget {
|
|||||||
final TextEditingController newPasswordController;
|
final TextEditingController newPasswordController;
|
||||||
final String missingPasswordError;
|
final String missingPasswordError;
|
||||||
final String passwordsDoNotMatchError;
|
final String passwordsDoNotMatchError;
|
||||||
|
final bool obscureText;
|
||||||
|
final VoidCallback onToggleVisibility;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -26,11 +30,18 @@ class ConfirmPasswordField extends StatelessWidget {
|
|||||||
width: fieldWidth,
|
width: fieldWidth,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
obscureText: true,
|
obscureText: obscureText,
|
||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: confirmPasswordLabel,
|
labelText: confirmPasswordLabel,
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
onPressed: onToggleVisibility,
|
||||||
|
icon: Icon(
|
||||||
|
obscureText ? Icons.visibility_off : Icons.visibility,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) return missingPasswordError;
|
if (value == null || value.isEmpty) return missingPasswordError;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ class PasswordField extends StatelessWidget {
|
|||||||
required this.labelText,
|
required this.labelText,
|
||||||
required this.fieldWidth,
|
required this.fieldWidth,
|
||||||
required this.isEnabled,
|
required this.isEnabled,
|
||||||
|
required this.obscureText,
|
||||||
|
required this.onToggleVisibility,
|
||||||
required this.validator,
|
required this.validator,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -14,6 +16,8 @@ class PasswordField extends StatelessWidget {
|
|||||||
final String labelText;
|
final String labelText;
|
||||||
final double fieldWidth;
|
final double fieldWidth;
|
||||||
final bool isEnabled;
|
final bool isEnabled;
|
||||||
|
final bool obscureText;
|
||||||
|
final VoidCallback onToggleVisibility;
|
||||||
final String? Function(String?) validator;
|
final String? Function(String?) validator;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -22,14 +26,21 @@ class PasswordField extends StatelessWidget {
|
|||||||
width: fieldWidth,
|
width: fieldWidth,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
obscureText: true,
|
obscureText: obscureText,
|
||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: labelText,
|
labelText: labelText,
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
onPressed: onToggleVisibility,
|
||||||
|
icon: Icon(
|
||||||
|
obscureText ? Icons.visibility_off : Icons.visibility,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
validator: validator,
|
validator: validator,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ class PasswordFields extends StatelessWidget {
|
|||||||
required this.fieldWidth,
|
required this.fieldWidth,
|
||||||
required this.gapSmall,
|
required this.gapSmall,
|
||||||
required this.isEnabled,
|
required this.isEnabled,
|
||||||
|
required this.showOldPassword,
|
||||||
|
required this.showNewPassword,
|
||||||
|
required this.showConfirmPassword,
|
||||||
|
required this.onToggleOldPassword,
|
||||||
|
required this.onToggleNewPassword,
|
||||||
|
required this.onToggleConfirmPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
final TextEditingController oldPasswordController;
|
final TextEditingController oldPasswordController;
|
||||||
@@ -31,6 +37,12 @@ class PasswordFields extends StatelessWidget {
|
|||||||
final double fieldWidth;
|
final double fieldWidth;
|
||||||
final double gapSmall;
|
final double gapSmall;
|
||||||
final bool isEnabled;
|
final bool isEnabled;
|
||||||
|
final bool showOldPassword;
|
||||||
|
final bool showNewPassword;
|
||||||
|
final bool showConfirmPassword;
|
||||||
|
final VoidCallback onToggleOldPassword;
|
||||||
|
final VoidCallback onToggleNewPassword;
|
||||||
|
final VoidCallback onToggleConfirmPassword;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -41,6 +53,8 @@ class PasswordFields extends StatelessWidget {
|
|||||||
labelText: oldPasswordLabel,
|
labelText: oldPasswordLabel,
|
||||||
fieldWidth: fieldWidth,
|
fieldWidth: fieldWidth,
|
||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
|
obscureText: !showOldPassword,
|
||||||
|
onToggleVisibility: onToggleOldPassword,
|
||||||
validator: (value) =>
|
validator: (value) =>
|
||||||
(value == null || value.isEmpty) ? missingPasswordError : null,
|
(value == null || value.isEmpty) ? missingPasswordError : null,
|
||||||
),
|
),
|
||||||
@@ -50,6 +64,8 @@ class PasswordFields extends StatelessWidget {
|
|||||||
labelText: newPasswordLabel,
|
labelText: newPasswordLabel,
|
||||||
fieldWidth: fieldWidth,
|
fieldWidth: fieldWidth,
|
||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
|
obscureText: !showNewPassword,
|
||||||
|
onToggleVisibility: onToggleNewPassword,
|
||||||
validator: (value) =>
|
validator: (value) =>
|
||||||
(value == null || value.isEmpty) ? missingPasswordError : null,
|
(value == null || value.isEmpty) ? missingPasswordError : null,
|
||||||
),
|
),
|
||||||
@@ -62,8 +78,10 @@ class PasswordFields extends StatelessWidget {
|
|||||||
newPasswordController: newPasswordController,
|
newPasswordController: newPasswordController,
|
||||||
missingPasswordError: missingPasswordError,
|
missingPasswordError: missingPasswordError,
|
||||||
passwordsDoNotMatchError: passwordsDoNotMatchError,
|
passwordsDoNotMatchError: passwordsDoNotMatchError,
|
||||||
|
obscureText: !showConfirmPassword,
|
||||||
|
onToggleVisibility: onToggleConfirmPassword,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
frontend/pweb/lib/models/password_field_type.dart
Normal file
1
frontend/pweb/lib/models/password_field_type.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
enum PasswordFieldType { old, newPassword, confirmPassword }
|
||||||
1
frontend/pweb/lib/models/visibility.dart
Normal file
1
frontend/pweb/lib/models/visibility.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
enum VisibilityState { hidden, visible }
|
||||||
@@ -4,6 +4,7 @@ import 'package:pshared/provider/account.dart';
|
|||||||
import 'package:pshared/widgets/password/fields.dart';
|
import 'package:pshared/widgets/password/fields.dart';
|
||||||
import 'package:pshared/utils/snackbar.dart';
|
import 'package:pshared/utils/snackbar.dart';
|
||||||
|
|
||||||
|
import 'package:pweb/models/password_field_type.dart';
|
||||||
import 'package:pweb/providers/password_form.dart';
|
import 'package:pweb/providers/password_form.dart';
|
||||||
import 'package:pweb/pages/settings/profile/account/password/form/error_text.dart';
|
import 'package:pweb/pages/settings/profile/account/password/form/error_text.dart';
|
||||||
import 'package:pweb/pages/settings/profile/account/password/form/submit_button.dart';
|
import 'package:pweb/pages/settings/profile/account/password/form/submit_button.dart';
|
||||||
@@ -65,6 +66,18 @@ class PasswordForm extends StatelessWidget {
|
|||||||
fieldWidth: _fieldWidth,
|
fieldWidth: _fieldWidth,
|
||||||
gapSmall: _gapSmall,
|
gapSmall: _gapSmall,
|
||||||
isEnabled: !isFormBusy,
|
isEnabled: !isFormBusy,
|
||||||
|
showOldPassword:
|
||||||
|
formProvider.isPasswordVisible(PasswordFieldType.old),
|
||||||
|
showNewPassword:
|
||||||
|
formProvider.isPasswordVisible(PasswordFieldType.newPassword),
|
||||||
|
showConfirmPassword: formProvider
|
||||||
|
.isPasswordVisible(PasswordFieldType.confirmPassword),
|
||||||
|
onToggleOldPassword: () =>
|
||||||
|
formProvider.togglePasswordVisibility(PasswordFieldType.old),
|
||||||
|
onToggleNewPassword: () => formProvider
|
||||||
|
.togglePasswordVisibility(PasswordFieldType.newPassword),
|
||||||
|
onToggleConfirmPassword: () => formProvider
|
||||||
|
.togglePasswordVisibility(PasswordFieldType.confirmPassword),
|
||||||
),
|
),
|
||||||
const SizedBox(height: _gapMedium),
|
const SizedBox(height: _gapMedium),
|
||||||
PasswordSubmitButton(
|
PasswordSubmitButton(
|
||||||
@@ -72,10 +85,11 @@ class PasswordForm extends StatelessWidget {
|
|||||||
label: savePassword,
|
label: savePassword,
|
||||||
onSubmit: () async {
|
onSubmit: () async {
|
||||||
try {
|
try {
|
||||||
await formProvider.submit(
|
final success = await formProvider.submit(
|
||||||
accountProvider: accountProvider,
|
accountProvider: accountProvider,
|
||||||
errorText: errorText,
|
errorText: errorText,
|
||||||
);
|
);
|
||||||
|
if (!success) return;
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
notifyUser(context, successText);
|
notifyUser(context, successText);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:pshared/provider/account.dart';
|
import 'package:pshared/provider/account.dart';
|
||||||
|
|
||||||
import 'package:pweb/models/edit_state.dart';
|
import 'package:pweb/models/edit_state.dart';
|
||||||
|
import 'package:pshared/api/responses/error/server.dart';
|
||||||
|
import 'package:pweb/models/password_field_type.dart';
|
||||||
|
import 'package:pweb/models/visibility.dart';
|
||||||
|
|
||||||
|
|
||||||
class PasswordFormProvider extends ChangeNotifier {
|
class PasswordFormProvider extends ChangeNotifier {
|
||||||
@@ -11,6 +14,11 @@ class PasswordFormProvider extends ChangeNotifier {
|
|||||||
final newPasswordController = TextEditingController();
|
final newPasswordController = TextEditingController();
|
||||||
final confirmPasswordController = TextEditingController();
|
final confirmPasswordController = TextEditingController();
|
||||||
|
|
||||||
|
final Map<PasswordFieldType, VisibilityState> _visibility = {
|
||||||
|
PasswordFieldType.old: VisibilityState.hidden,
|
||||||
|
PasswordFieldType.newPassword: VisibilityState.hidden,
|
||||||
|
PasswordFieldType.confirmPassword: VisibilityState.hidden,
|
||||||
|
};
|
||||||
EditState _state = EditState.view;
|
EditState _state = EditState.view;
|
||||||
String _errorText = '';
|
String _errorText = '';
|
||||||
bool _disposed = false;
|
bool _disposed = false;
|
||||||
@@ -19,6 +27,8 @@ class PasswordFormProvider extends ChangeNotifier {
|
|||||||
bool get isSaving => _state == EditState.saving;
|
bool get isSaving => _state == EditState.saving;
|
||||||
String get errorText => _errorText;
|
String get errorText => _errorText;
|
||||||
EditState get state => _state;
|
EditState get state => _state;
|
||||||
|
bool isPasswordVisible(PasswordFieldType type) =>
|
||||||
|
_visibility[type] == VisibilityState.visible;
|
||||||
|
|
||||||
void toggleExpanded() {
|
void toggleExpanded() {
|
||||||
if (_state == EditState.saving) return;
|
if (_state == EditState.saving) return;
|
||||||
@@ -26,12 +36,21 @@ class PasswordFormProvider extends ChangeNotifier {
|
|||||||
_setError('');
|
_setError('');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> submit({
|
void togglePasswordVisibility(PasswordFieldType type) {
|
||||||
|
final current = _visibility[type];
|
||||||
|
if (current == null) return;
|
||||||
|
_visibility[type] = current == VisibilityState.hidden
|
||||||
|
? VisibilityState.visible
|
||||||
|
: VisibilityState.hidden;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> submit({
|
||||||
required AccountProvider accountProvider,
|
required AccountProvider accountProvider,
|
||||||
required String errorText,
|
required String errorText,
|
||||||
}) async {
|
}) async {
|
||||||
final currentForm = formKey.currentState;
|
final currentForm = formKey.currentState;
|
||||||
if (currentForm == null || !currentForm.validate()) return;
|
if (currentForm == null || !currentForm.validate()) return false;
|
||||||
|
|
||||||
_setState(EditState.saving);
|
_setState(EditState.saving);
|
||||||
_setError('');
|
_setError('');
|
||||||
@@ -45,14 +64,22 @@ class PasswordFormProvider extends ChangeNotifier {
|
|||||||
oldPasswordController.clear();
|
oldPasswordController.clear();
|
||||||
newPasswordController.clear();
|
newPasswordController.clear();
|
||||||
confirmPasswordController.clear();
|
confirmPasswordController.clear();
|
||||||
|
_setState(EditState.view);
|
||||||
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_setError(errorText);
|
_setError(_errorMessageForException(e, errorText));
|
||||||
rethrow;
|
|
||||||
} finally {
|
|
||||||
_setState(EditState.edit);
|
_setState(EditState.edit);
|
||||||
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _errorMessageForException(Object exception, String fallback) {
|
||||||
|
if (exception is ErrorResponse && exception.details.isNotEmpty) {
|
||||||
|
return exception.details;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
void _setState(EditState value) {
|
void _setState(EditState value) {
|
||||||
if (_state == value || _disposed) return;
|
if (_state == value || _disposed) return;
|
||||||
_state = value;
|
_state = value;
|
||||||
|
|||||||
Reference in New Issue
Block a user