diff --git a/Frontend/patient_manager/lib/components/myTextInput.dart b/Frontend/patient_manager/lib/components/myTextInput.dart index 8ef245e6..8efa7dc9 100644 --- a/Frontend/patient_manager/lib/components/myTextInput.dart +++ b/Frontend/patient_manager/lib/components/myTextInput.dart @@ -33,16 +33,35 @@ class _MyTextFieldState extends State { String? get _errorText { final text = widget.controller.text; + String _errorMessage = ''; if (startup) { return null; - } else if (!widget.required) { - return null; - } else if (text.isEmpty) { - return "${widget.hintText} is required"; - } else if (widget.hintText == "Email" && !isEmailValid(text)) { - return "Enter a valid email address"; } - return null; + if (!widget.required) { + return null; + } + if (text.isEmpty) { + return "${widget.hintText} is required"; + } + if (widget.hintText == "Email" && !isEmailValid(text)) { + _errorMessage += "Enter a valid email address\n"; + } + if (widget.hintText == "Username" && text.length < 8) { + _errorMessage += "• Username must contain at least 8 characters.\n"; + } + if (widget.hintText == "Username" && !isUsernameValid(text)) { + _errorMessage += "• Username can only contain '_' special Chracters.\n"; + } + if (_errorMessage.isEmpty) { + return null; + } + // If there are no error messages, the password is valid + return _errorMessage; + } + + bool isUsernameValid(String Username) { + return RegExp(r'^(?=[a-zA-Z0-9._]{8,20}$)(?!.*[_.]{2})[^_.].*[^_.]$') + .hasMatch(Username); } bool isEmailValid(String email) { diff --git a/Frontend/patient_manager/lib/components/profileUserUpdate.dart b/Frontend/patient_manager/lib/components/profileUserUpdate.dart index d3bbe5de..00582a41 100644 --- a/Frontend/patient_manager/lib/components/profileUserUpdate.dart +++ b/Frontend/patient_manager/lib/components/profileUserUpdate.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:patient_manager/components/myErrorMessage.dart'; import 'package:patient_manager/components/mySuccessMessage.dart'; import 'package:patient_manager/components/myTextInput.dart'; @@ -27,6 +28,7 @@ class _ProfileUserUpdateState extends State { final fnameController = TextEditingController(); final lnameController = TextEditingController(); late bool businessUser; + final FocusNode _focusNode = FocusNode(); bool isFieldsFilled() { if (fnameController.text.isEmpty || @@ -52,30 +54,34 @@ class _ProfileUserUpdateState extends State { } else { profileType = "personal"; } - - var response = await http.put( - Uri.parse("${AppEnviroment.baseApiUrl}/user/update/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "idusers": widget.signedInUser.idUser, - "username": usernameController.text, - "fnam": fnameController.text, - "lname": lnameController.text, - "type": profileType, - }), - ); - //print("Here4"); - //print(response.statusCode); - if (response.statusCode == 200) { - Navigator.of(context) - .popAndPushNamed('/', arguments: widget.signedInUser); - String message = - "${widget.signedInUser.email}'s information has been updated successfully!"; - successPopUp(message); + print("is username valid ${isUsernameValid(usernameController.text)}"); + if (isUsernameValid(usernameController.text) == false) { + usernamePopUp(); } else { - internetConnectionPopUp(); + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/user/update/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "idusers": widget.signedInUser.idUser, + "username": usernameController.text, + "fnam": fnameController.text, + "lname": lnameController.text, + "type": profileType, + }), + ); + //print("Here4"); + //print(response.statusCode); + if (response.statusCode == 200) { + Navigator.of(context) + .popAndPushNamed('/', arguments: widget.signedInUser); + String message = + "${widget.signedInUser.email}'s information has been updated successfully!"; + successPopUp(message); + } else { + internetConnectionPopUp(); + } } } @@ -108,6 +114,33 @@ class _ProfileUserUpdateState extends State { ); } + void usernamePopUp() { + showDialog( + context: context, + builder: (context) { + return const MyErrorMessage(errorType: "Invalid Username"); + }, + ); + } + + bool isUsernameValid(String username) { + return RegExp(r'^(?=[a-zA-Z0-9._]{8,20}$)(?!.*[_.]{2})[^_.].*[^_.]$') + .hasMatch(username); + } + + void submitForm() { + if (isFieldsFilled()) { + updateUserApiCall(); + } else { + showDialog( + context: context, + builder: (context) { + return const MyErrorMessage(errorType: "Input Error"); + }, + ); + } + } + @override void initState() { setState(() { @@ -122,85 +155,86 @@ class _ProfileUserUpdateState extends State { @override Widget build(BuildContext context) { - return Column( - children: [ - const Text( - "Personal profile:", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, + return KeyboardListener( + focusNode: _focusNode, + autofocus: true, + onKeyEvent: (event) async { + if (event is KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.enter) { + submitForm(); + } + }, + child: Column( + children: [ + const Text( + "Personal profile:", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), ), - ), - const SizedBox(height: 15.0), - MyTextField( - controller: usernameController, - hintText: "Username", - editable: true, - required: true, - ), - const SizedBox(height: 10.0), - MyTextField( - controller: fnameController, - hintText: "First Name", - editable: true, - required: true, - ), - const SizedBox(height: 10.0), - MyTextField( - controller: lnameController, - hintText: "Last Name", - editable: true, - required: true, - ), - const SizedBox(height: 10.0), - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Text( - "Activate Business", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20, + const SizedBox(height: 15.0), + MyTextField( + controller: usernameController, + hintText: "Username", + editable: true, + required: true, + ), + const SizedBox(height: 10.0), + MyTextField( + controller: fnameController, + hintText: "First Name", + editable: true, + required: true, + ), + const SizedBox(height: 10.0), + MyTextField( + controller: lnameController, + hintText: "Last Name", + editable: true, + required: true, + ), + const SizedBox(height: 10.0), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Text( + "Activate Business Account", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + ), ), - ), - const SizedBox( - width: 25, - ), - Switch( - value: businessUser, - onChanged: (bool value) { - setState(() { - businessUser = value; - }); + const SizedBox( + width: 25, + ), + Switch( + value: businessUser, + onChanged: (bool value) { + setState(() { + businessUser = value; + }); + }, + ), + ], + ), + const SizedBox(height: 10.0), + SizedBox( + width: 500.0, + height: 100.0, + child: MyButton( + buttonText: "Update", + buttonColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + onTap: () { + submitForm(); }, ), - ], - ), - const SizedBox(height: 10.0), - SizedBox( - width: 500.0, - height: 100.0, - child: MyButton( - buttonText: "Update", - buttonColor: - MzanziInnovationHub.of(context)!.theme.secondaryColor(), - textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), - onTap: () { - if (isFieldsFilled()) { - updateUserApiCall(); - } else { - showDialog( - context: context, - builder: (context) { - return const MyErrorMessage(errorType: "Input Error"); - }, - ); - } - }, ), - ), - ], + ], + ), ); } }