settings page

pull/5/head
Bogdan Kotikov 2023-06-03 00:40:40 +02:00
parent a989878cca
commit 6085297b1c
11 changed files with 345 additions and 191 deletions

View File

@ -229,6 +229,12 @@
"packageUri": "lib/",
"languageVersion": "2.17"
},
{
"name": "flutter_profile_picture",
"rootUri": "file:///Users/bogdan/.pub-cache/hosted/pub.dev/flutter_profile_picture-2.0.0",
"packageUri": "lib/",
"languageVersion": "2.12"
},
{
"name": "flutter_test",
"rootUri": "file:///usr/local/Caskroom/flutter/3.7.7/flutter/packages/flutter_test",
@ -608,7 +614,7 @@
"languageVersion": "2.19"
}
],
"generated": "2023-06-01T16:44:17.796384Z",
"generated": "2023-06-02T11:38:29.193689Z",
"generator": "pub",
"generatorVersion": "2.19.6"
}

View File

@ -142,6 +142,10 @@ flutter_lints
2.17
file:///Users/bogdan/.pub-cache/hosted/pub.dev/flutter_lints-2.0.1/
file:///Users/bogdan/.pub-cache/hosted/pub.dev/flutter_lints-2.0.1/lib/
flutter_profile_picture
2.12
file:///Users/bogdan/.pub-cache/hosted/pub.dev/flutter_profile_picture-2.0.0/
file:///Users/bogdan/.pub-cache/hosted/pub.dev/flutter_profile_picture-2.0.0/lib/
form_builder_validators
2.19
file:///Users/bogdan/.pub-cache/hosted/pub.dev/form_builder_validators-8.6.1/

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.2/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_android-2.0.27/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.2/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.10/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.6/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-06-01 21:59:58.395996","version":"3.7.9"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.2/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_android-2.0.27/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_foundation-2.2.2/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.10/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/bogdan/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.6/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-06-02 13:45:10.283479","version":"3.7.9"}

View File

@ -0,0 +1,148 @@
import 'package:ernaehrung/android/components/form/form_builder_text_field_component.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:hive/hive.dart';
import '../../models/form_builder.dart';
import '../../models/user.dart';
import '../../pages/nav_pages/main_page.dart';
class FormBuilderComponent extends StatefulWidget {
final bool lockTextFields;
const FormBuilderComponent({Key? key, required this.lockTextFields})
: super(key: key);
@override
State<FormBuilderComponent> createState() => _FormBuilderComponentState();
}
class _FormBuilderComponentState extends State<FormBuilderComponent> {
final formKey = GlobalKey<FormBuilderState>();
final List<FormTextField> listOfTextField = [
FormTextField(
"vorname",
TextInputType.text,
30,
"Der Vorname sollte maximal 30 Zeichen lang sein",
"Der Vorname sollte mindestens 2 Zeichen lang sein",
2,
null,
null,
null,
null),
FormTextField(
"nachname",
TextInputType.text,
30,
"Der Nachname sollte maximal 30 Zeichen lang sein",
"Der Nachname sollte mindestens 2 Zeichen lang sein",
2,
null,
null,
null,
null),
FormTextField(
"gewicht",
TextInputType.number,
null,
null,
null,
null,
200,
10,
"Der Gewicht sollte maximal 200 kg sein",
"Der Gewicht sollte mindestens 10 kg sein"),
FormTextField(
"groesse",
TextInputType.number,
null,
null,
null,
null,
230,
60,
"Die Größe sollte maximal 230cm sein",
"Die Größe sollte mindestens 60cm sein"),
FormTextField(
"alter",
TextInputType.number,
null,
null,
null,
null,
99,
6,
"Das Alter sollte maximal 99 Jahre alt sein",
"Das Alter sollte mindestens 6 Jahre alt sein"),
FormTextField(
"kalorien",
TextInputType.number,
null,
null,
null,
null,
30000,
1000,
"Die Kalorienanzahl sollte mindestens 30000 Kcal sein",
"Die Kalorienanzahl sollte mindestens 1000 Kcal sein")
];
@override
Widget build(BuildContext context) {
print("widget enable ${widget.lockTextFields}");
return FormBuilder(
key: formKey,
child: Padding(
padding: const EdgeInsets.all(8),
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
primary: false,
itemCount: listOfTextField.length,
shrinkWrap: true,
itemBuilder: (context, index) {
print(listOfTextField[index]);
return FormBuilderTextFieldComponent(
true, listOfTextField[index]);
}),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(40), //
backgroundColor: const Color(0xFF6E7BFB),
foregroundColor: const Color(0xFFffffff),
shape: const StadiumBorder(),
),
onPressed: () {
final Box box = Hive.box<User>("USER_BOX");
box.put(
"USER",
User(
formKey.currentState?.fields['vorname']?.value,
formKey.currentState?.fields['nachname']?.value,
int.parse(formKey
.currentState?.fields['gewicht']?.value),
int.parse(formKey
.currentState?.fields['groesse']?.value),
int.parse(
formKey.currentState?.fields['alter']?.value),
int.parse(formKey
.currentState?.fields['kalorien']?.value)));
print(box.get("USER"));
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => const MainPage()));
},
child: const Text("Eingaben bestätigen"),
)),
],
)),
));
}
}

View File

@ -0,0 +1,96 @@
import 'package:basic_utils/basic_utils.dart';
import 'package:ernaehrung/android/models/form_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
class FormBuilderTextFieldComponent extends StatefulWidget {
final bool isSettingsPage;
final FormTextField formTextField;
const FormBuilderTextFieldComponent(this.isSettingsPage, this.formTextField,
{super.key});
@override
State<FormBuilderTextFieldComponent> createState() => _FormBuilderTextFieldComponentState();
}
class _FormBuilderTextFieldComponentState extends State<FormBuilderTextFieldComponent> {
bool enable = false;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: widget.isSettingsPage
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child:
TextFieldChild(widget.isSettingsPage, widget.formTextField, enable: enable)),
enable
? IconButton(
onPressed: () async {
setState(() {
enable = !enable;
});
},
icon: const Icon(Icons.lock_open))
: IconButton(
onPressed: () async {
setState(() {
enable = !enable;
});
},
icon: const Icon(Icons.lock))
],
)
: TextFieldChild(widget.isSettingsPage, widget.formTextField),
);
}
}
class TextFieldChild extends StatelessWidget {
final bool isSettingsPage;
final FormTextField formTextField;
final bool? enable;
const TextFieldChild(this.isSettingsPage, this.formTextField,
{super.key, this.enable = true});
@override
Widget build(BuildContext context) {
return FormBuilderTextField(
name: formTextField.title,
enabled: enable!,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
filled: true,
hintStyle: TextStyle(color: Colors.grey.shade400),
hintText: StringUtils.capitalize(formTextField.title),
labelText: StringUtils.capitalize(formTextField.title),
fillColor: Colors.white70),
keyboardType: TextInputType.number,
maxLength: TextInputType.number == formTextField.textInputType ? 7 : 30,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
TextInputType.number == formTextField.textInputType
? FormBuilderValidators.max(formTextField.numericMax!,
errorText: formTextField.numericMaxErrorMessage)
: FormBuilderValidators.maxLength(30,
errorText: formTextField.maxLengthErrorMessage),
TextInputType.number == formTextField.textInputType
? FormBuilderValidators.min(formTextField.numericMin!,
errorText: formTextField.numericMinErrorMessage)
: FormBuilderValidators.minLength(2,
errorText: formTextField.minLengthErrorMessage)
]),
);
}
}

View File

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
class FormTextField{
final String title;
final TextInputType textInputType;
final num? maxLength;
final String? maxLengthErrorMessage;
final String? minLengthErrorMessage;
final num? minLength;
final num? numericMax;
final num? numericMin;
final String? numericMaxErrorMessage;
final String? numericMinErrorMessage;
FormTextField(
this.title,
this.textInputType,
this.maxLength,
this.maxLengthErrorMessage,
this.minLengthErrorMessage,
this.minLength,
this.numericMax,
this.numericMin,
this.numericMaxErrorMessage,
this.numericMinErrorMessage);
}

View File

@ -2,7 +2,11 @@ import 'package:ernaehrung/android/components/meal_page_text/days_component.dart
import 'package:ernaehrung/android/config/statistics.dart';
import 'package:ernaehrung/android/pages/nav_pages/progress_page.dart';
import 'package:ernaehrung/android/pages/nav_pages/today_page.dart';
import 'package:ernaehrung/android/pages/settings.dart';
import 'package:flutter/material.dart';
import 'package:flutter_profile_picture/flutter_profile_picture.dart';
import 'package:hive/hive.dart';
import '../../models/user.dart';
import 'meal_plan_page.dart';
class MainPage extends StatefulWidget {
@ -25,7 +29,8 @@ class MainPageState extends State<MainPage> {
setState(() {
currentIndex = index;
if (currentIndex == 1) {
StatisticsService.instance.updateStatisticsTodayBoxByTimespan(TimeSpan.day);
StatisticsService.instance
.updateStatisticsTodayBoxByTimespan(TimeSpan.day);
} else if (currentIndex == 2) {
StatisticsService.instance.updateProgressBoxValues();
}
@ -35,10 +40,28 @@ class MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
final Box box = Hive.box<User>("USER_BOX");
return Scaffold(
extendBodyBehindAppBar: false,
appBar: AppBar(
title: Text(pages[currentIndex].title),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(pages[currentIndex].title),
ElevatedButton(
onPressed: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsPage()),
);
},
child: ProfilePicture(
name: "${box.get("FIRST_NAME_FIELD")}",
radius: 16,
fontsize: 14,
))
],
),
backgroundColor: Colors.transparent,
foregroundColor: Colors.grey.shade400,
elevation: 0,

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import '../components/form/form_builder.dart';
class SettingsPage extends StatefulWidget {
const SettingsPage({Key? key}) : super(key: key);
@override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: BackButton(
onPressed: () async => Navigator.of(context).pop(),
),
title: const Text('Einstellungen'),
),
body: const FormBuilderComponent(lockTextFields: true),
);
}
}

View File

@ -1,10 +1,5 @@
import 'package:ernaehrung/android/pages/nav_pages/main_page.dart';
import 'package:ernaehrung/android/components/form/form_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:hive_flutter/hive_flutter.dart';
import '../models/user.dart';
class OnboardingPage extends StatefulWidget {
const OnboardingPage({Key? key}) : super(key: key);
@ -14,193 +9,15 @@ class OnboardingPage extends StatefulWidget {
}
class _OnboardingPageState extends State<OnboardingPage> {
InputDecoration decoration(String hintText) {
return InputDecoration(
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
filled: true,
hintStyle: TextStyle(color: Colors.grey.shade400),
hintText: hintText,
labelText: hintText,
fillColor: Colors.white70);
}
@override
Widget build(BuildContext context) {
final formKey = GlobalKey<FormBuilderState>();
return Scaffold(
appBar: AppBar(
title: const Text("Welcome"),
backgroundColor: Colors.grey.shade100,
),
body: FormBuilder(
key: formKey,
child: Padding(
padding: const EdgeInsets.all(8),
child: SingleChildScrollView(
child: Column(
children: [
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'vorname',
decoration: decoration("Vorname"),
keyboardType: TextInputType.text,
maxLength: 30,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.minLength(2,
errorText:
"Die Name sollte mindestens 2 Zeichen lang sein"),
FormBuilderValidators.maxLength(30,
errorText:
"Die Name sollte maximal 30 Zeichen lang sein")
]),
),
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'nachname',
decoration: decoration("Nachname"),
keyboardType: TextInputType.text,
maxLength: 30,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.minLength(2,
errorText:
"Die Nachname sollte mindestens 2 Zeichen lang sein"),
FormBuilderValidators.maxLength(30,
errorText:
"Die Nachname sollte maximal 30 Zeichen lang sein")
]),
),
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'gewicht',
decoration: decoration("Gewicht"),
keyboardType: TextInputType.number,
maxLength: 7,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.numeric(
errorText:
"Der Gewicht sollte mindestens 10 kg sein"),
FormBuilderValidators.max(200,
errorText:
"Der Gewicht sollte maximal 200 kg sein"),
FormBuilderValidators.min(10,
errorText:
"Der Gewicht sollte mindestens 10 kg sein")
]),
),
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'groesse',
decoration: decoration("Größe"),
keyboardType: TextInputType.number,
maxLength: 7,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.numeric(
errorText: "Die Größe sollte mindestens 60cm sein"),
FormBuilderValidators.max(230,
errorText: "Die Größe sollte maximal 230cm sein"),
FormBuilderValidators.min(60,
errorText: "Die Größe sollte mindestens 60cm sein")
]),
),
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'alter',
decoration: decoration("Alter"),
keyboardType: TextInputType.number,
maxLength: 7,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.numeric(
errorText:
"Das Alter sollte mindestens 6 Jahre alt sein"),
FormBuilderValidators.max(99,
errorText:
"Das Alter sollte maximal 99 Jahre alt sein"),
FormBuilderValidators.min(6,
errorText:
"Das Alter sollte mindestens 6 Jahre alt sein")
]),
),
),
Container(
margin:
const EdgeInsets.symmetric(vertical: 8, horizontal: 0),
child: FormBuilderTextField(
name: 'kalorien',
decoration:
decoration("gewünschte Kalorienzufuhr: min. 1000"),
keyboardType: TextInputType.number,
maxLength: 7,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
FormBuilderValidators.numeric(
errorText:
"Die Kalorienanzahl sollte mindestens 1000 Kcal sein"),
FormBuilderValidators.max(30000),
FormBuilderValidators.min(1000,
errorText:
"Die Kalorienanzahl sollte mindestens 1000 Kcal sein")
]),
),
),
Container(
margin: const EdgeInsets.symmetric(
vertical: 8, horizontal: 0),
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(40), //
backgroundColor: const Color(0xFF6E7BFB),
foregroundColor: const Color(0xFFffffff),
shape: const StadiumBorder(),
),
onPressed: () {
final Box box = Hive.box<User>("USER_BOX");
box.put("USER", User(
formKey.currentState?.fields['vorname']?.value,
formKey.currentState?.fields['nachname']?.value,
int.parse(formKey.currentState?.fields['gewicht']?.value),
int.parse(formKey.currentState?.fields['groesse']?.value),
int.parse(formKey.currentState?.fields['alter']?.value),
int.parse(formKey.currentState?.fields['kalorien']?.value)
));
Navigator
.of(context)
.pushReplacement(MaterialPageRoute(builder: (BuildContext context) => const MainPage()));
},
child: const Text("Eingaben bestätigen"),
)),
],
),
),
)),
body: const FormBuilderComponent(lockTextFields: false,)
);
}
}

View File

@ -299,6 +299,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_profile_picture:
dependency: "direct main"
description:
name: flutter_profile_picture
sha256: "067caecef0d7162d3858eaca3c5859cbbb21b3e5704c2bc5b96b50ffe267f45d"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
flutter_test:
dependency: "direct dev"
description: flutter

View File

@ -49,6 +49,7 @@ dependencies:
basic_utils: ^5.5.4
flutter_form_builder: ^8.0.0
form_builder_validators: ^8.0.0
flutter_profile_picture: ^2.0.0
dev_dependencies: