Skip to content

Commit

Permalink
Release 1.14.0 (#260)
Browse files Browse the repository at this point in the history
* Coderefactoring in release 1.13 (#252)

* Fix focus problem

* PicosListCard

* Refactor PicosListCard (2.round)

* Show phone number in patients_list_card.dart (#254)

* Set walkDistance to start with zero (#253)

* Feature/fogot password (#256)

* Add the feature "forgot password?" to the login screen

* Use theme color for "forgot password?"

* Refactor the code in forgot_password_screen.dart

* Resolve Copy paste error

* Use our 'standard' route

* Error handling during login (#255)

* Localizations

* implementation of backend reachability check

* "notReachable" added to "BackendError"

* Typo in comment fixed

* Localizations

* errormessage, errorcode & 'incompleteMessages' introduced

* Changes discarded

* Adjust _createPassword(). (#258)

Reformat the code.

* Adjust pubspec.yaml (#259)

---------

Co-authored-by: mustiwebp <[email protected]>
  • Loading branch information
FaysalSolutions and mustiwebp authored Jan 23, 2024
1 parent 173669e commit 296be1b
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 255 deletions.
8 changes: 7 additions & 1 deletion lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -377,5 +377,11 @@
"rhythmType": "Rhythmus Typ",
"electricalAxisDeviation": "Lagetyp",
"error": "Fehler!",
"loadingFailed": "Laden fehlgeschlagen!"
"loadingFailed": "Laden fehlgeschlagen!",
"forgotPassword": "Passwort vergessen?",
"resetPassword": "Passwort zurücksetzen",
"ifEmailCorrect": "Bei Korrektheit wird eine Mail verschickt!",
"enterMailToResetPW": "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben. Wir senden Ihnen eine E-Mail mit einem Link zum Zurücksetzen des Passwortes!",
"backendNotReachable": "Backend ist nicht erreichbar!",
"incompleteCredentials": "Unvollständige Eingaben!"
}
24 changes: 24 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1514,5 +1514,29 @@
"loadingFailed": "Loading failed!",
"@loadingFailed": {
"description": "Loading failed!"
},
"forgotPassword": "Forgot password?",
"@forgotPassword": {
"description": "Forgot Password?"
},
"resetPassword": "Reset password",
"@resetPassword": {
"description": "Reset password"
},
"ifEmailCorrect": "If correct, an mail will be sent!",
"@ifEmailCorrect": {
"description": "If correct, an mail will be sent!"
},
"enterMailToResetPW": "Please enter the email address you registered with. We will send you an e-mail with a link to reset your password!",
"@enterMailToResetPW": {
"description": "Please enter the email address you registered with. We will send you an e-mail with a link to reset your password!"
},
"backendNotReachable": "Backend is not reachable!",
"@backendNotReachable": {
"description": "Backend is not reachable!"
},
"incompleteCredentials": "Incomplete Credentials",
"@incompleteCredentials": {
"description": "Incomplete Credentials!"
}
}
57 changes: 33 additions & 24 deletions lib/models/patient.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,39 +91,48 @@ class Patient extends AbstractDatabaseObject {

@override
List<Object> get props => <Object>[
firstName,
familyName,
email,
number,
address,
formOfAddress,
];
firstName,
familyName,
email,
number,
address,
formOfAddress,
];

/// Method that returns a random password.
static String _createPassword() {
// A non-negative number for determining the length of the password.
const int length = 8;

const String letters = 'abcdefghijklmnopqrstuvwxyz';
const String capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const String numbers = '0123456789';
Random randomString = Random.secure();

return String.fromCharCodes(
List<int>.generate(
length.abs(),
(int index) => randomString.nextInt(33) + 89,
),
);
String password = '';
password += letters[randomString.nextInt(letters.length)];
password += capitals[randomString.nextInt(capitals.length)];
password += numbers[randomString.nextInt(numbers.length)];

String allCharacters = letters + capitals + numbers;
for (int i = password.length; i < length; i++) {
password += allCharacters[randomString.nextInt(allCharacters.length)];
}

List<int> passwordChars = List<int>.of(password.codeUnits);
passwordChars.shuffle(randomString);
return String.fromCharCodes(passwordChars);
}

@override
Map<String, dynamic> get databaseMapping => <String, dynamic>{
'username': email,
'password': _createPassword(),
'email': email,
'Form': formOfAddress,
'Firstname': firstName,
'Lastname': familyName,
'PhoneNo': number,
'Address': address,
'Role': role,
};
'username': email,
'password': _createPassword(),
'email': email,
'Form': formOfAddress,
'Firstname': firstName,
'Lastname': familyName,
'PhoneNo': number,
'Address': address,
'Role': role,
};
}
3 changes: 3 additions & 0 deletions lib/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import 'package:flutter/cupertino.dart';
import 'package:picos/screens/fogot_password_screen/forgot_password_screen.dart';
import 'package:picos/screens/follow_up_screen/edit_follow_up_screen.dart';
import 'package:picos/screens/follow_up_screen/follow_up_list.dart';
import 'package:picos/screens/legals_screen.dart';
Expand Down Expand Up @@ -102,6 +103,8 @@ class Routes {
const FollowUpList(),
'/follow_up_screen/edit_follow_up_screen': (BuildContext ctx) =>
const EditFollowUpScreen(),
'/forgot_password_screen': (BuildContext ctx) =>
const ForgotPasswordScreen(),
};
}

Expand Down
109 changes: 109 additions & 0 deletions lib/screens/fogot_password_screen/forgot_password_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* This file is part of Picos, a health tracking mobile app
* Copyright (C) 2022 Healthcare IT Solutions GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import 'package:flutter/material.dart';
import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:picos/widgets/picos_body.dart';
import 'package:picos/widgets/picos_screen_frame.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../widgets/picos_ink_well_button.dart';
import '../../widgets/picos_label.dart';
import '../../widgets/picos_text_field.dart';

/// Displays the forgot password screen.
class ForgotPasswordScreen extends StatefulWidget {
/// ForgotPasswordScreen constructor.
const ForgotPasswordScreen({Key? key}) : super(key: key);

@override
State<ForgotPasswordScreen> createState() => _ForgotPasswordScreenState();
}

class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
final TextEditingController emailController = TextEditingController();
final GlobalKey<FormState> formKey = GlobalKey<FormState>();

static final RegExp emailRegex = RegExp('.+@.+', caseSensitive: false);

Future<void> resetPassword(String email) async {
try {
await ParseUser(null, null, email).requestPasswordReset();
if (mounted) {
showSnackBarMessage(AppLocalizations.of(context)!.ifEmailCorrect);
}
} on ParseException catch (e) {
showSnackBarMessage('Error: $e');
}
}

void showSnackBarMessage(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}

void validateAndResetPassword() {
if (formKey.currentState!.validate()) {
resetPassword(emailController.text);
}
}

@override
Widget build(BuildContext context) {
return PicosScreenFrame(
title: AppLocalizations.of(context)!.forgotPassword,
body: PicosBody(
child: Form(
key: formKey,
child: Column(
children: <Widget>[
Text(AppLocalizations.of(context)!.enterMailToResetPW),
const SizedBox(height: 10),
PicosLabel(AppLocalizations.of(context)!.email),
emailInputField(),
resetPasswordButton(),
],
),
),
),
);
}

PicosTextField emailInputField() {
return PicosTextField(
controller: emailController,
hint: AppLocalizations.of(context)!.email,
keyboardType: TextInputType.emailAddress,
validator: (String? value) {
if (value == null || value.isEmpty) {
return AppLocalizations.of(context)!.entryEmail;
} else if (!emailRegex.hasMatch(value)) {
return AppLocalizations.of(context)!.entryValidEmail;
}
return null;
},
);
}

Widget resetPasswordButton() {
return PicosInkWellButton(
text: AppLocalizations.of(context)!.resetPassword,
onTap: validateAndResetPassword,
);
}
}
21 changes: 6 additions & 15 deletions lib/screens/follow_up_screen/edit_follow_up_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,10 @@ class _EditFollowUpScreenState extends State<EditFollowUpScreen> {

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);

if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: PicosScreenFrame(
title: 'V${_followUp.number}',
body: PicosBody(child: _buildForm()),
bottomNavigationBar: _buildBottomNavigationBar(),
),
return PicosScreenFrame(
title: 'V${_followUp.number}',
body: PicosBody(child: _buildForm()),
bottomNavigationBar: _buildBottomNavigationBar(),
);
}

Expand Down Expand Up @@ -402,7 +393,7 @@ class _EditFollowUpScreenState extends State<EditFollowUpScreen> {
initialValue: _distance?.toString(),
decoration: InputDecoration(
labelText:
'${AppLocalizations.of(context)!.walkDistance} (1-600 meter)',
'${AppLocalizations.of(context)!.walkDistance} (0-600 meter)',
border: const OutlineInputBorder(),
focusedBorder: focusedBorder(),
errorText: _isDistanceValid
Expand All @@ -417,7 +408,7 @@ class _EditFollowUpScreenState extends State<EditFollowUpScreen> {
onChanged: (String value) {
setState(() {
int? intValue = int.tryParse(value);
if (intValue == null || (intValue < 1 || intValue > 600)) {
if (intValue == null || (intValue < 0 || intValue > 600)) {
_isDistanceValid = false;
_saveDisabled = true;
} else {
Expand Down
22 changes: 22 additions & 0 deletions lib/screens/login_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,28 @@ class _LoginScreenState extends State<LoginScreen>
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(
'/forgot_password_screen',
);
},
child: Text(
AppLocalizations.of(context)!.forgotPassword,
style: TextStyle(
height: 2,
color: theme.blue,
),
),
),
],
),
),
SizedBox(
width: 200,
child: Row(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,40 +592,31 @@ class _CatalogOfItemsScreenState extends State<CatalogOfItemsScreen>
if (isLoading) {
return const Center(child: CircularProgressIndicator());
} else {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);

if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: PicosScreenFrame(
title: 'Catalog of items',
body: Form(
child: PageView(
controller: controller,
onPageChanged: (int num) {
setState(() {
_currentPage = num;
});
},
children: pages,
),
return PicosScreenFrame(
title: 'Catalog of items',
body: Form(
child: PageView(
controller: controller,
onPageChanged: (int num) {
setState(() {
_currentPage = num;
});
},
children: pages,
),
bottomNavigationBar: PicosAddButtonBar(
leftButton: PicosInkWellButton(
text: AppLocalizations.of(context)!.back,
onTap: previousPage,
buttonColor1: theme.grey3,
buttonColor2: theme.grey1,
),
rightButton: PicosInkWellButton(
onTap: nextPage,
text: _currentPage == lastPage
? AppLocalizations.of(context)!.save
: AppLocalizations.of(context)!.next,
),
),
bottomNavigationBar: PicosAddButtonBar(
leftButton: PicosInkWellButton(
text: AppLocalizations.of(context)!.back,
onTap: previousPage,
buttonColor1: theme.grey3,
buttonColor2: theme.grey1,
),
rightButton: PicosInkWellButton(
onTap: nextPage,
text: _currentPage == lastPage
? AppLocalizations.of(context)!.save
: AppLocalizations.of(context)!.next,
),
),
);
Expand Down
Loading

0 comments on commit 296be1b

Please sign in to comment.