From 8f3244f6079aab92a064fc4e15e55a742a7f7f28 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 28 Feb 2024 11:08:57 +0300 Subject: [PATCH 01/39] refactor(diary): Usnused imports and deprecated metods removed --- lib/widgets/custom_bottom_bar.dart | 1 + lib/widgets/custom_image_view.dart | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/custom_bottom_bar.dart b/lib/widgets/custom_bottom_bar.dart index 67ae4e3f..c32781a2 100644 --- a/lib/widgets/custom_bottom_bar.dart +++ b/lib/widgets/custom_bottom_bar.dart @@ -1,6 +1,7 @@ import 'package:eatvio_app/core/app_export.dart'; import 'package:flutter/material.dart'; +// ignore: must_be_immutable class CustomBottomBar extends StatefulWidget { CustomBottomBar({this.onChanged}); diff --git a/lib/widgets/custom_image_view.dart b/lib/widgets/custom_image_view.dart index 5bed7a28..03bd0cbf 100644 --- a/lib/widgets/custom_image_view.dart +++ b/lib/widgets/custom_image_view.dart @@ -96,7 +96,6 @@ class CustomImageView extends StatelessWidget { height: height, width: width, fit: fit ?? BoxFit.contain, - color: color, ), ); case ImageType.file: From b389a2a13feb5430cf7b61bca47251e255646e17 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 28 Feb 2024 11:57:23 +0300 Subject: [PATCH 02/39] refactor(test): Flutter Analyze fix --- .env.example | 2 ++ lib/core/utils/size_utils.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..98d26074 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +SERVER_ROOT='https://ohngeeri3ien-dev3.eatvio.ru/api' +STORAGE_URL='https://ohngeeri3ien-dev3.eatvio.ru/storage/' \ No newline at end of file diff --git a/lib/core/utils/size_utils.dart b/lib/core/utils/size_utils.dart index ddc30061..8911620b 100644 --- a/lib/core/utils/size_utils.dart +++ b/lib/core/utils/size_utils.dart @@ -3,7 +3,8 @@ import 'package:flutter/material.dart'; // This functions are responsible to make UI responsive across all the mobile devices. -MediaQueryData mediaQueryData = MediaQueryData.fromWindow(ui.window); +// ignore: deprecated_member_use +MediaQueryData mediaQueryData = MediaQueryData.fromView(ui.window); // These are the Viewport values of your Figma Design. // These are used in the code as a reference to create your UI Responsively. From f0e9202b86d991c2e325908aa1c321855fd59bc3 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 28 Feb 2024 17:32:42 +0300 Subject: [PATCH 03/39] (debug)diary: Some debugging for API --- .../bloc/diary_edit_bloc.dart | 19 +++++++------------ .../diary_edit_screen/diary_edit_screen.dart | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 1796418f..8228a099 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -40,7 +40,7 @@ class DiaryEditBloc extends Bloc { ) async { try { final token = - "laravel_sanctum_Q22zOtJhQUcJnh0kseZFblFv5XAPaKbG3gTM5hga71ecbb49"; + "laravel_sanctum_1lPFtd9tpGmHYS243C4K7YF8BrVhxxgXm8cTmjuZda1da694"; final response = await http.get( Uri.parse(dotenv.env['SERVER_ROOT']! + '/diary/index'), headers: { @@ -61,7 +61,6 @@ class DiaryEditBloc extends Bloc { ); final diary = jsonDecode(response.body)['diary']; if (diary is Map) { - print(diary['meals'][1].runtimeType); final String diaryDate = diary['date'] ?? DateTime.now().toString(); // Продолжайте обработку данных дневника @@ -145,8 +144,6 @@ class DiaryEditBloc extends Bloc { var updatedState = currentState.copyWith(selectedSatiety: event.selectedElement); - emit(updatedState); // Передаем обновленное состояние в emit - // Отправляем данные по HTTP маршруту и ждем ответ var response = await sendSatietyData( currentState.token, @@ -155,8 +152,8 @@ class DiaryEditBloc extends Bloc { currentState.diaryId); if (response.statusCode == 200) { - currentState.selectedSatiety = event.selectedElement; - emit(currentState); // Передаем обновленное состояние в emit + updatedState.selectedSatiety = event.selectedElement; + emit(updatedState); // Передаем обновленное состояние в emit } } } @@ -167,21 +164,19 @@ class DiaryEditBloc extends Bloc { int? mealID, int diaryID, ) async { - String url = - dotenv.env['SERVER_ROOT']! + '$diaryID/meal/$mealID/satiety/fill'; + String url = dotenv.env['SERVER_ROOT']! + + '/diary/$diaryID/meal/$mealID/satiety/fill'; final credentials = { 'satiety': selectedSatiety, - 'meal_id': mealID, - 'diary_id': diaryID, }; - + print(json.encode(credentials)); var response = await http.post(Uri.parse(url), headers: { 'Authorization': 'Bearer $token', }, body: json.encode(credentials), encoding: utf8); - + print(response.body); return response; } diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 2bc07d97..8686b834 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -198,7 +198,7 @@ class DiaryEditScreen extends StatelessWidget { ); } - _buildMeal(BuildContext context, DiaryEditLoadedState state) { + Padding _buildMeal(BuildContext context, DiaryEditLoadedState state) { final digitsOnly = FilteringTextInputFormatter.digitsOnly; return Padding( padding: EdgeInsets.symmetric(horizontal: 16.h), @@ -734,7 +734,7 @@ class DiaryEditScreen extends StatelessWidget { )); } - Widget _buildWakupRetire(BuildContext context, DiaryEditLoadedState state) { + Padding _buildWakupRetire(BuildContext context, DiaryEditLoadedState state) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.h), child: Container( From 8eea92c4c6546fa98bd2b141326987c120520d1d Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 29 Feb 2024 21:27:06 +0300 Subject: [PATCH 04/39] feat(diary): More work on API methods --- .../bloc/diary_edit_bloc.dart | 45 +++++++++---------- .../bloc/diary_edit_event.dart | 7 +-- .../diary_edit_screen/diary_edit_screen.dart | 7 ++- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 8228a099..62433ab0 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -90,7 +90,7 @@ class DiaryEditBloc extends Bloc { // Если текущее состояние - начальное, создаем новое загруженное состояние emit(DiaryEditLoadedState( currentMeal: SelectionPopupModel( - id: 0, title: "Прием пищи 1", isSelected: true), + id: 1, title: "Прием пищи 1", isSelected: true), wakeupExpanded: true, moodExpanded: true, token: token, @@ -208,11 +208,9 @@ class DiaryEditBloc extends Bloc { int diaryID, ) async { String url = - dotenv.env['SERVER_ROOT']! + '/$diaryID/meal/$mealID/mood/fill'; + dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/fill'; final credentials = { 'mood': selectedMood, - 'meal_id': mealID, - 'diary_id': diaryID, }; var response = await http.post(Uri.parse(url), @@ -248,10 +246,9 @@ class DiaryEditBloc extends Bloc { TimeOfDay wakeup, int diaryID, ) async { - String url = dotenv.env['SERVER_ROOT']! + '/diary/???'; + String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/wakeUp/fill'; final credentials = { 'wakeup': wakeup, - 'diary_id': diaryID, }; var response = await http.post(Uri.parse(url), @@ -312,8 +309,8 @@ class DiaryEditBloc extends Bloc { currentState.currentMeal?.id, currentState.diaryId); if (response.statusCode == 200) { - currentState.retireController = event.time; - emit(currentState); // Передаем обновленное состояние в emit + updatedState.mealTimeController = event.time; + emit(updatedState); // Передаем обновленное состояние в emit } } } @@ -393,34 +390,32 @@ class DiaryEditBloc extends Bloc { // Отправляем данные по HTTP маршруту и ждем ответ var response = await sendPortionData( currentState.token, - event.name, - event.portion, - event.quantity, + currentState.productNameController?.text, + 'pcs', + int.parse(currentState.productQuantityController!.text), currentState.currentMeal!.id, currentState.diaryId); if (response.statusCode == 200) { - emit(currentState); // Передаем обновленное состояние в emit + emit(updatedState); // Передаем обновленное состояние в emit } } } Future sendPortionData( String? token, - String name, + String? name, String portion, - int quantity, + int? quantity, int? mealID, int diaryID, ) async { - String url = - dotenv.env['SERVER_ROOT']! + '/$diaryID/meal/$mealID/portions/create'; + String url = dotenv.env['SERVER_ROOT']! + + 'diary/$diaryID/meal/$mealID/portions/create'; final credentials = { - 'name': name, + 'product_name': name, 'portion': portion, 'quantity': quantity, - 'meal_id': mealID, - 'diary_id': diaryID, }; var response = await http.post(Uri.parse(url), @@ -502,12 +497,12 @@ class DiaryEditBloc extends Bloc { List fillMealList() { return [ - SelectionPopupModel(id: 0, title: "Прием пищи 1", isSelected: true), - SelectionPopupModel(id: 1, title: "Прием пищи 2"), - SelectionPopupModel(id: 2, title: "Прием пищи 3"), - SelectionPopupModel(id: 3, title: "Прием пищи 4"), - SelectionPopupModel(id: 4, title: "Прием пищи 5"), - SelectionPopupModel(id: 5, title: "Прием пищи 6"), + SelectionPopupModel(id: 1, title: "Прием пищи 1", isSelected: true), + SelectionPopupModel(id: 2, title: "Прием пищи 2"), + SelectionPopupModel(id: 3, title: "Прием пищи 3"), + SelectionPopupModel(id: 4, title: "Прием пищи 4"), + SelectionPopupModel(id: 5, title: "Прием пищи 5"), + SelectionPopupModel(id: 6, title: "Прием пищи 6"), ]; } } diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart index 206e5957..ed6f8e2f 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_event.dart @@ -79,12 +79,9 @@ class ToggleWakeupExpandedEvent extends DiaryEditEvent { } class AddPortionEvent extends DiaryEditEvent { - AddPortionEvent(this.name, this.quantity, this.portion); - final String name; - final int quantity; - final String portion; + AddPortionEvent(); @override - List get props => [name, quantity, portion]; + List get props => []; } class RemovePortionEvent extends DiaryEditEvent { diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 8686b834..f61fff96 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -144,11 +144,14 @@ class DiaryEditScreen extends StatelessWidget { } /// Section Widget - Widget _buildAddProduct(BuildContext context) { + Widget _buildAddProduct(BuildContext context, DiaryEditLoadedState state) { return CustomOutlinedButton( text: "Добавить продукт", margin: EdgeInsets.symmetric(horizontal: 10.h), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, + onPressed: () { + context.read().add(AddPortionEvent()); + }, ); } @@ -311,7 +314,7 @@ class DiaryEditScreen extends StatelessWidget { ), ), SizedBox(height: 30.v), - _buildAddProduct(context), + _buildAddProduct(context, state), SizedBox(height: 30.v), ...state.portions! .map((portion) => _buildProduct(context, portion)) From 65f94c535a38983678bd4d3d04a5fa01598ea79f Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 29 Feb 2024 22:10:08 +0300 Subject: [PATCH 05/39] feat(diary): Filtering finished --- .../diary/diary_edit_screen/bloc/diary_edit_bloc.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 62433ab0..cb54d630 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -445,6 +445,7 @@ class DiaryEditBloc extends Bloc { 'Authorization': 'Bearer $token', }, ); + print(response.body); final productNutritionalValues = jsonDecode(response.body)['productNutritionalValue']; if (productNutritionalValues is Map) { From 56355f4e3152744fcc0de3acbbb37d262e62c9d4 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 29 Feb 2024 22:29:22 +0300 Subject: [PATCH 06/39] feat(diary): Saving filtering value to the state --- .../diary_edit_screen/bloc/diary_edit_bloc.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index cb54d630..1aef9ac7 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -432,6 +432,7 @@ class DiaryEditBloc extends Bloc { ProductInput event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; + print(currentState.productNameController!.text); String? token = currentState.token; final credentials = { 'name': event.input, @@ -445,16 +446,18 @@ class DiaryEditBloc extends Bloc { 'Authorization': 'Bearer $token', }, ); - print(response.body); final productNutritionalValues = - jsonDecode(response.body)['productNutritionalValue']; - if (productNutritionalValues is Map) { + jsonDecode(response.body)['product_nutritional_value']; + if (productNutritionalValues is List) { var updatedState = currentState.copyWith( - autocompleteList: productNutritionalValues.values - .map((value) => value['name']) + autocompleteList: productNutritionalValues + .map((product) => product['name']) .toList()); + print(updatedState.autocompleteList); emit(updatedState); + } else { + print("Ошибка в декодировании ответа из API"); } } } From 173b131eda3e4806a86ba9a1e7e0b5629c8802c7 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 29 Feb 2024 23:06:06 +0300 Subject: [PATCH 07/39] Autocomplete class --- lib/widgets/custom_autocomplete.dart | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 lib/widgets/custom_autocomplete.dart diff --git a/lib/widgets/custom_autocomplete.dart b/lib/widgets/custom_autocomplete.dart new file mode 100644 index 00000000..81e91454 --- /dev/null +++ b/lib/widgets/custom_autocomplete.dart @@ -0,0 +1,82 @@ +import 'package:eatvio_app/core/app_export.dart'; +import 'package:flutter/material.dart'; + +class CustomTextFormField extends StatelessWidget { + // ... + + final AutocompleteOptions autocompleteOptions; + + const CustomTextFormField({ + // ... (остальные параметры) + required this.autocompleteOptions, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: autocompleteFieldWidget, + ) + : autocompleteFieldWidget; + } + + Widget get autocompleteFieldWidget => SizedBox( + width: width ?? double.maxFinite, + child: Autocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + if (textEditingValue.text == '') { + return const Iterable.empty(); + } + return autocompleteOptions.options.where((String option) { + return option + .toLowerCase() + .contains(textEditingValue.text.toLowerCase()); + }); + }, + onSelected: (String value) { + controller?.text = value; + onChanged?.call(value); + }, + fieldViewBuilder: (BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted) { + return TextFormField( + controller: textEditingController, + focusNode: focusNode, + autofocus: autofocus!, + style: textStyle ?? theme.textTheme.titleMedium, + obscureText: obscureText!, + textInputAction: textInputAction, + maxLines: maxLines ?? 1, + decoration: decoration, + validator: validator, + keyboardType: keyboardType, + onSaved: onSaved, + onChanged: onChanged, + inputFormatters: inputFormatters, + initialValue: initialValue, + onFieldSubmitted: (_) => onFieldSubmitted(), + ); + }, + optionsViewBuilder: (BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options) { + return Material( + elevation: 4.0, + child: ListView( + children: options.map((String option) { + return ListTile( + title: Text(option), + onTap: () { + onSelected(option); + }, + ); + }).toList(), + ), + ); + }, + ), + ); +} From ea78cc8f91f7ff4fc9b194d754bb7ef3975e0a81 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Fri, 1 Mar 2024 11:57:28 +0300 Subject: [PATCH 08/39] Tried to implement autocomplete --- .../bloc/diary_edit_bloc.dart | 2 - .../diary_edit_screen/diary_edit_screen.dart | 39 +++++++++++++------ lib/widgets/custom_autocomplete.dart | 4 +- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 1aef9ac7..907684ce 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -432,7 +432,6 @@ class DiaryEditBloc extends Bloc { ProductInput event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; - print(currentState.productNameController!.text); String? token = currentState.token; final credentials = { 'name': event.input, @@ -454,7 +453,6 @@ class DiaryEditBloc extends Bloc { .map((product) => product['name']) .toList()); - print(updatedState.autocompleteList); emit(updatedState); } else { print("Ошибка в декодировании ответа из API"); diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index f61fff96..51022b28 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -3,12 +3,14 @@ import 'models/diary_edit_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; + import 'package:image_picker/image_picker.dart'; import 'package:eatvio_app/core/app_export.dart'; import 'package:eatvio_app/widgets/custom_edit_text_form_field.dart'; import 'package:eatvio_app/widgets/custom_edit_drop_down.dart'; import 'package:eatvio_app/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/widgets/custom_scale_element.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; // ignore: must_be_immutable class DiaryEditScreen extends StatelessWidget { @@ -279,17 +281,32 @@ class DiaryEditScreen extends StatelessWidget { })), SizedBox(height: 20.v), Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: CustomTextFormField( - hintText: "Введите названия продукта", - controller: state.productNameController, - onChanged: (value) { - if (value.length > 3) { - context.read().add(ProductInput(value)); - } - }, - ), - ), + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: TypeAheadField( + controller: state.productNameController, + suggestionsCallback: (search) => state.autocompleteList, + builder: (context, controller, focusNode) { + return CustomTextFormField( + hintText: "Введите названия продукта", + controller: controller, + onChanged: (value) { + print(state.autocompleteList); + if (value.length > 3) { + context + .read() + .add(ProductInput(value)); + } + }, + ); + }, + itemBuilder: (context, product) { + return ListTile( + title: Text(product), + subtitle: Text(product), + ); + }, + onSelected: (product) {}, + )), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), diff --git a/lib/widgets/custom_autocomplete.dart b/lib/widgets/custom_autocomplete.dart index 81e91454..a0560c1c 100644 --- a/lib/widgets/custom_autocomplete.dart +++ b/lib/widgets/custom_autocomplete.dart @@ -1,6 +1,6 @@ import 'package:eatvio_app/core/app_export.dart'; import 'package:flutter/material.dart'; - +/* class CustomTextFormField extends StatelessWidget { // ... @@ -79,4 +79,4 @@ class CustomTextFormField extends StatelessWidget { }, ), ); -} +}*/ From 8132e296d20f041eb058c0a47933005ad1ae2884 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Fri, 1 Mar 2024 15:09:40 +0300 Subject: [PATCH 09/39] feat(diary): Custom autocomplete --- .../diary_edit_screen/diary_edit_screen.dart | 90 +++++++++++++------ 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 51022b28..7da97ef9 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -281,32 +281,70 @@ class DiaryEditScreen extends StatelessWidget { })), SizedBox(height: 20.v), Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: TypeAheadField( - controller: state.productNameController, - suggestionsCallback: (search) => state.autocompleteList, - builder: (context, controller, focusNode) { - return CustomTextFormField( - hintText: "Введите названия продукта", - controller: controller, - onChanged: (value) { - print(state.autocompleteList); - if (value.length > 3) { - context - .read() - .add(ProductInput(value)); - } - }, - ); - }, - itemBuilder: (context, product) { - return ListTile( - title: Text(product), - subtitle: Text(product), - ); - }, - onSelected: (product) {}, - )), + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: RawAutocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + if (textEditingValue.text == '') { + return const Iterable.empty(); + } + return Future>.value(state.autocompleteList + ?.map((dynamic item) => item as String) + .toList() + .where((String option) { + return true; + })); + }, + fieldViewBuilder: ( + BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted, + ) { + return CustomTextFormField( + hintText: "Введите названия продукта", + controller: state.productNameController, + onChanged: (value) { + print(state.autocompleteList); + if (value.length > 3) { + context + .read() + .add(ProductInput(value)); + } + }, + ); + }, + optionsViewBuilder: ( + BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options, + ) { + return Align( + alignment: Alignment.topLeft, + child: Material( + elevation: 4.0, + child: SizedBox( + height: 200.0, + child: ListView.builder( + padding: const EdgeInsets.all(8.0), + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + final String option = options.elementAt(index); + return GestureDetector( + onTap: () { + onSelected(option); + }, + child: ListTile( + title: Text(option), + ), + ); + }, + ), + ), + ), + ); + }, + ), + ), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), From e6b7e7894098b80d68060658bb0613a146999bf1 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Fri, 1 Mar 2024 17:14:55 +0300 Subject: [PATCH 10/39] feat(diary): Debugginng for autocomplete (TODO: Pass the TextEditingController to the builder from the state) --- .../diary_edit_screen/diary_edit_screen.dart | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 7da97ef9..70e79daf 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -205,6 +205,11 @@ class DiaryEditScreen extends StatelessWidget { Padding _buildMeal(BuildContext context, DiaryEditLoadedState state) { final digitsOnly = FilteringTextInputFormatter.digitsOnly; + const List _options = [ + 'aardvark', + 'bobcat', + 'chameleon', + ]; return Padding( padding: EdgeInsets.symmetric(horizontal: 16.h), child: Container( @@ -301,10 +306,12 @@ class DiaryEditScreen extends StatelessWidget { VoidCallback onFieldSubmitted, ) { return CustomTextFormField( - hintText: "Введите названия продукта", + hintText: "Введите название продукта", controller: state.productNameController, onChanged: (value) { - print(state.autocompleteList); + /*print(state.autocompleteList + ?.map((dynamic item) => item as String) + .toList());*/ if (value.length > 3) { context .read() @@ -343,9 +350,60 @@ class DiaryEditScreen extends StatelessWidget { ), ); }, + onSelected: (String selection) { + // Обработка выбранного варианта автозаполнения + }, ), ), SizedBox(height: 20.v), + RawAutocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + return _options.where((String option) { + return option.contains(textEditingValue.text.toLowerCase()); + }); + }, fieldViewBuilder: ( + BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted, + ) { + return TextFormField( + controller: textEditingController, + focusNode: focusNode, + onFieldSubmitted: (String value) { + onFieldSubmitted(); + }, + ); + }, optionsViewBuilder: ( + BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options, + ) { + return Align( + alignment: Alignment.topLeft, + child: Material( + elevation: 4.0, + child: SizedBox( + height: 200.0, + child: ListView.builder( + padding: const EdgeInsets.all(8.0), + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + final String option = options.elementAt(index); + return GestureDetector( + onTap: () { + onSelected(option); + }, + child: ListTile( + title: Text(option), + ), + ); + }, + ), + ), + ), + ); + }), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: Row( From 6c03971f183042ccc8000fa226c9d29b34b3faca Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 10:12:01 +0300 Subject: [PATCH 11/39] feat(diary): Comments and autocomplete finished --- .../bloc/diary_edit_bloc.dart | 47 ++++++++++++++----- .../diary_edit_screen/diary_edit_screen.dart | 3 +- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 907684ce..da42241b 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:ffi'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; @@ -302,16 +303,7 @@ class DiaryEditBloc extends Bloc { var currentState = state as DiaryEditLoadedState; var updatedState = currentState.copyWith(mealTimeController: event.time); - emit(updatedState); // Передаем обновленное состояние в emit - - // Отправляем данные по HTTP маршруту и ждем ответ - var response = await sendMealTimeData(currentState.token, event.time, - currentState.currentMeal?.id, currentState.diaryId); - - if (response.statusCode == 200) { - updatedState.mealTimeController = event.time; - emit(updatedState); // Передаем обновленное состояние в emit - } + emit(updatedState); } } @@ -469,7 +461,40 @@ class DiaryEditBloc extends Bloc { print(imageUrl); } - FutureOr _addComment(AddComment event, Emitter emit) {} + FutureOr _addComment( + AddComment event, Emitter emit) async { + if (state is DiaryEditLoadedState) { + var currentState = state as DiaryEditLoadedState; + var updatedState = + currentState.copyWith(commentController: event.comment); + + // Отправляем данные по HTTP маршруту и ждем ответ + var response = await sendCommentData( + currentState.token, event.comment, currentState.diaryId); + + if (response.statusCode == 200) { + emit(updatedState); // Передаем обновленное состояние в emit + } + } + } + + Future sendCommentData( + String? token, String comment, int diaryID) async { + String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; + final credentials = { + 'comment': comment, + }; + + var response = await http.post(Uri.parse(url), + headers: { + 'Authorization': 'Bearer $token', + }, + body: json.encode(credentials), + encoding: utf8); + + return response; + } + Future uploadImageToServer(String imagePath) async { var request = http.MultipartRequest( 'POST', diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 70e79daf..e4cb6f56 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -359,7 +359,8 @@ class DiaryEditScreen extends StatelessWidget { RawAutocomplete( optionsBuilder: (TextEditingValue textEditingValue) { return _options.where((String option) { - return option.contains(textEditingValue.text.toLowerCase()); + return option.contains( + state.productNameController!.text.toLowerCase()); }); }, fieldViewBuilder: ( BuildContext context, From 1fa05eae5fa3d32cc4d170f4cdf539bf9cec56a0 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 14:04:09 +0300 Subject: [PATCH 12/39] Impoved autocomplete and partial encoding error fix --- .../bloc/diary_edit_bloc.dart | 6 +- .../diary_edit_screen/diary_edit_screen.dart | 171 ++++++------------ 2 files changed, 58 insertions(+), 119 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index da42241b..81e7f5dc 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -170,7 +170,6 @@ class DiaryEditBloc extends Bloc { final credentials = { 'satiety': selectedSatiety, }; - print(json.encode(credentials)); var response = await http.post(Uri.parse(url), headers: { 'Authorization': 'Bearer $token', @@ -465,8 +464,9 @@ class DiaryEditBloc extends Bloc { AddComment event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; - var updatedState = - currentState.copyWith(commentController: event.comment); + var updatedState = currentState.copyWith( + commentController: TextEditingController(text: event.comment), + ); // Отправляем данные по HTTP маршруту и ждем ответ var response = await sendCommentData( diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index e4cb6f56..5bf9881c 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -205,11 +205,9 @@ class DiaryEditScreen extends StatelessWidget { Padding _buildMeal(BuildContext context, DiaryEditLoadedState state) { final digitsOnly = FilteringTextInputFormatter.digitsOnly; - const List _options = [ - 'aardvark', - 'bobcat', - 'chameleon', - ]; + List _options = + state.autocompleteList!.map((dynamic item) => item as String).toList(); + print(_options); return Padding( padding: EdgeInsets.symmetric(horizontal: 16.h), child: Container( @@ -288,123 +286,64 @@ class DiaryEditScreen extends StatelessWidget { Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: RawAutocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - if (textEditingValue.text == '') { - return const Iterable.empty(); - } - return Future>.value(state.autocompleteList - ?.map((dynamic item) => item as String) - .toList() - .where((String option) { - return true; - })); - }, - fieldViewBuilder: ( - BuildContext context, - TextEditingController textEditingController, - FocusNode focusNode, - VoidCallback onFieldSubmitted, - ) { - return CustomTextFormField( - hintText: "Введите название продукта", - controller: state.productNameController, - onChanged: (value) { - /*print(state.autocompleteList + optionsBuilder: (TextEditingValue textEditingValue) { + return _options.where((String option) { + return true; + }); + }, fieldViewBuilder: ( + BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted, + ) { + return CustomTextFormField( + hintText: "Введите название продукта", + controller: textEditingController, + focusNode: focusNode, + onChanged: (value) { + /*print(state.autocompleteList ?.map((dynamic item) => item as String) .toList());*/ - if (value.length > 3) { - context - .read() - .add(ProductInput(value)); - } - }, - ); - }, - optionsViewBuilder: ( - BuildContext context, - AutocompleteOnSelected onSelected, - Iterable options, - ) { - return Align( - alignment: Alignment.topLeft, - child: Material( - elevation: 4.0, - child: SizedBox( - height: 200.0, - child: ListView.builder( - padding: const EdgeInsets.all(8.0), - itemCount: options.length, - itemBuilder: (BuildContext context, int index) { - final String option = options.elementAt(index); - return GestureDetector( - onTap: () { - onSelected(option); - }, - child: ListTile( - title: Text(option), - ), - ); - }, - ), + if (value.length > 3) { + context.read().add(ProductInput(value)); + } + }, + /*onFieldSubmitted: (String value) { + onFieldSubmitted(); + },*/ + ); + }, optionsViewBuilder: ( + BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options, + ) { + return Align( + alignment: Alignment.topLeft, + child: Material( + elevation: 4.0, + child: SizedBox( + height: 200.0, + child: ListView.builder( + padding: const EdgeInsets.all(8.0), + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + final String option = options.elementAt(index); + return GestureDetector( + onTap: () { + onSelected(option); + }, + child: ListTile( + title: Text(option), + ), + ); + }, ), ), - ); - }, - onSelected: (String selection) { - // Обработка выбранного варианта автозаполнения - }, - ), + ), + ); + }), ), SizedBox(height: 20.v), - RawAutocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - return _options.where((String option) { - return option.contains( - state.productNameController!.text.toLowerCase()); - }); - }, fieldViewBuilder: ( - BuildContext context, - TextEditingController textEditingController, - FocusNode focusNode, - VoidCallback onFieldSubmitted, - ) { - return TextFormField( - controller: textEditingController, - focusNode: focusNode, - onFieldSubmitted: (String value) { - onFieldSubmitted(); - }, - ); - }, optionsViewBuilder: ( - BuildContext context, - AutocompleteOnSelected onSelected, - Iterable options, - ) { - return Align( - alignment: Alignment.topLeft, - child: Material( - elevation: 4.0, - child: SizedBox( - height: 200.0, - child: ListView.builder( - padding: const EdgeInsets.all(8.0), - itemCount: options.length, - itemBuilder: (BuildContext context, int index) { - final String option = options.elementAt(index); - return GestureDetector( - onTap: () { - onSelected(option); - }, - child: ListTile( - title: Text(option), - ), - ); - }, - ), - ), - ), - ); - }), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: Row( From 8bde4d43a9b97e7f337753542f3a6bd306f30f00 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 14:44:52 +0300 Subject: [PATCH 13/39] feat(diary): Encoding error fix for satiety --- .../auth/auth_screen/auth_screen.dart | 2 +- .../bloc/diary_edit_bloc.dart | 54 ++++++++++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/lib/presentation/auth/auth_screen/auth_screen.dart b/lib/presentation/auth/auth_screen/auth_screen.dart index 4cbef203..213e8c29 100644 --- a/lib/presentation/auth/auth_screen/auth_screen.dart +++ b/lib/presentation/auth/auth_screen/auth_screen.dart @@ -87,7 +87,7 @@ class AuthScreen extends StatelessWidget { state.emailController!.text, state.passwordController!.text); if (errors.isEmpty) { - final credentials = { + final Map credentials = { 'email': state.emailController!.text, 'password': state.passwordController!.text, }; diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 81e7f5dc..e1844ed9 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'dart:ffi'; - +import 'package:intl/intl.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import '/core/app_export.dart'; @@ -45,6 +44,7 @@ class DiaryEditBloc extends Bloc { final response = await http.get( Uri.parse(dotenv.env['SERVER_ROOT']! + '/diary/index'), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, ); @@ -57,6 +57,7 @@ class DiaryEditBloc extends Bloc { final response = await http.get( Uri.parse(dotenv.env['SERVER_ROOT']! + '/diary/show/$diaryId'), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, ); @@ -167,11 +168,12 @@ class DiaryEditBloc extends Bloc { ) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/satiety/fill'; - final credentials = { + final Map credentials = { 'satiety': selectedSatiety, }; var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), @@ -209,12 +211,13 @@ class DiaryEditBloc extends Bloc { ) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/fill'; - final credentials = { + final Map credentials = { 'mood': selectedMood, }; var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), @@ -227,7 +230,7 @@ class DiaryEditBloc extends Bloc { WakeupEvent event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; - var updatedState = + var updatedState = //инициализируем новое состояние currentState.copyWith(wakeupController: event.selectedTime); // Отправляем данные по HTTP маршруту и ждем ответ @@ -235,6 +238,7 @@ class DiaryEditBloc extends Bloc { currentState.token, event.selectedTime, currentState.diaryId); if (response.statusCode == 200) { + //Чекаем статус ответа updatedState.wakeupController = event.selectedTime; emit(updatedState); // Передаем обновленное состояние в emit } @@ -247,17 +251,22 @@ class DiaryEditBloc extends Bloc { int diaryID, ) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/wakeUp/fill'; - final credentials = { - 'wakeup': wakeup, + final formatter = DateFormat('HH:mm'); + final wakeupString = + formatter.format(DateTime(2022, 1, 1, wakeup.hour, wakeup.minute)); + final Map credentials = { + 'wakeup': wakeupString, }; - - var response = await http.post(Uri.parse(url), - headers: { - 'Authorization': 'Bearer $token', - }, - body: json.encode(credentials), - encoding: utf8); - + var response = await http.post( + Uri.parse(url), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: json.encode(credentials), + encoding: utf8, + ); + print(response.body); return response; } @@ -282,12 +291,13 @@ class DiaryEditBloc extends Bloc { Future sendRetireData( String? token, TimeOfDay retire, int diaryID) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; - final credentials = { + final Map credentials = { 'retire': retire, }; var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), @@ -313,7 +323,7 @@ class DiaryEditBloc extends Bloc { int diaryID, ) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/???'; - final credentials = { + final Map credentials = { 'time': mealTime, 'meal_id': mealID, 'diary_id': diaryID, @@ -321,6 +331,7 @@ class DiaryEditBloc extends Bloc { var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), @@ -403,7 +414,7 @@ class DiaryEditBloc extends Bloc { ) async { String url = dotenv.env['SERVER_ROOT']! + 'diary/$diaryID/meal/$mealID/portions/create'; - final credentials = { + final Map credentials = { 'product_name': name, 'portion': portion, 'quantity': quantity, @@ -411,6 +422,7 @@ class DiaryEditBloc extends Bloc { var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), @@ -424,7 +436,7 @@ class DiaryEditBloc extends Bloc { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; String? token = currentState.token; - final credentials = { + final Map credentials = { 'name': event.input, }; final uri = Uri.parse(dotenv.env['SERVER_ROOT']! + @@ -433,6 +445,7 @@ class DiaryEditBloc extends Bloc { final response = await http.get( uri, headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, ); @@ -481,12 +494,13 @@ class DiaryEditBloc extends Bloc { Future sendCommentData( String? token, String comment, int diaryID) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; - final credentials = { + final Map credentials = { 'comment': comment, }; var response = await http.post(Uri.parse(url), headers: { + 'Content-Type': 'application/json', 'Authorization': 'Bearer $token', }, body: json.encode(credentials), From d21cd39e9ed9c83f4ba8d6678b9d1f4b9057b3bb Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 14:54:07 +0300 Subject: [PATCH 14/39] feat(diary): Encoding error fix for mood --- .../diary/diary_edit_screen/bloc/diary_edit_bloc.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index e1844ed9..d73ffe6f 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -210,7 +210,7 @@ class DiaryEditBloc extends Bloc { int diaryID, ) async { String url = - dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/fill'; + dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/meal/$mealID/mood/fill'; final Map credentials = { 'mood': selectedMood, }; @@ -222,6 +222,7 @@ class DiaryEditBloc extends Bloc { }, body: json.encode(credentials), encoding: utf8); + print(response.body); return response; } @@ -291,8 +292,11 @@ class DiaryEditBloc extends Bloc { Future sendRetireData( String? token, TimeOfDay retire, int diaryID) async { String url = dotenv.env['SERVER_ROOT']! + '/diary/$diaryID/retire/fill'; + final formatter = DateFormat('HH:mm'); + final retireString = + formatter.format(DateTime(2022, 1, 1, retire.hour, retire.minute)); final Map credentials = { - 'retire': retire, + 'retire': retireString, }; var response = await http.post(Uri.parse(url), From d47081493e880629e52892a8d90947bf7c870616 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 15:07:46 +0300 Subject: [PATCH 15/39] feat(diary): Encoding error fix finished --- .../diary/diary_edit_screen/bloc/diary_edit_bloc.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index d73ffe6f..41648dae 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -178,7 +178,6 @@ class DiaryEditBloc extends Bloc { }, body: json.encode(credentials), encoding: utf8); - print(response.body); return response; } @@ -222,7 +221,6 @@ class DiaryEditBloc extends Bloc { }, body: json.encode(credentials), encoding: utf8); - print(response.body); return response; } From 5a56836d92e9e54571a08579040bafcddc246a6b Mon Sep 17 00:00:00 2001 From: maxxkim Date: Mon, 4 Mar 2024 17:05:15 +0300 Subject: [PATCH 16/39] feat(diary): Add portion finished --- .../bloc/diary_edit_bloc.dart | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart index 41648dae..569164b1 100644 --- a/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart +++ b/lib/presentation/diary/diary_edit_screen/bloc/diary_edit_bloc.dart @@ -381,15 +381,8 @@ class DiaryEditBloc extends Bloc { AddPortionEvent event, Emitter emit) async { if (state is DiaryEditLoadedState) { var currentState = state as DiaryEditLoadedState; + int? id = currentState.currentMeal?.id; - var updatedState = currentState.copyWith( - currentMeal: currentState.diaryEditModelObj?.mealList[id ?? 0], - portions: currentState.meals?[id ?? 0]['portions'], - mealTimeController: - toTime(currentState.meals?[id ?? 0]['time'] ?? "1$id:00"), - selectedMood: currentState.meals?[id ?? 0]['mood'], - selectedSatiety: currentState.meals?[id ?? 0]['satiety']); - emit(updatedState); // Передаем обновленное состояние в emit // Отправляем данные по HTTP маршруту и ждем ответ var response = await sendPortionData( @@ -399,8 +392,10 @@ class DiaryEditBloc extends Bloc { int.parse(currentState.productQuantityController!.text), currentState.currentMeal!.id, currentState.diaryId); - if (response.statusCode == 200) { + var updatedState = currentState.copyWith( + portions: currentState.meals?[id ?? 0]['portions'], + ); emit(updatedState); // Передаем обновленное состояние в emit } } @@ -415,13 +410,13 @@ class DiaryEditBloc extends Bloc { int diaryID, ) async { String url = dotenv.env['SERVER_ROOT']! + - 'diary/$diaryID/meal/$mealID/portions/create'; + '/diary/$diaryID/meal/$mealID/portions/create'; final Map credentials = { 'product_name': name, 'portion': portion, 'quantity': quantity, }; - + print(credentials); var response = await http.post(Uri.parse(url), headers: { 'Content-Type': 'application/json', @@ -430,6 +425,7 @@ class DiaryEditBloc extends Bloc { body: json.encode(credentials), encoding: utf8); + print(response.body); return response; } @@ -455,6 +451,7 @@ class DiaryEditBloc extends Bloc { jsonDecode(response.body)['product_nutritional_value']; if (productNutritionalValues is List) { var updatedState = currentState.copyWith( + productNameController: TextEditingController(text: event.input), autocompleteList: productNutritionalValues .map((product) => product['name']) .toList()); From 94ffa3040b912966942ac4e3b6c4aa92f15d9161 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 11:05:58 +0300 Subject: [PATCH 17/39] refactor(diary): Removed unused imports --- .../diary/diary_edit_screen/diary_edit_screen.dart | 7 ++++--- lib/widgets/custom_autocomplete.dart | 2 -- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 5bf9881c..0068e333 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -10,7 +10,6 @@ import 'package:eatvio_app/widgets/custom_edit_text_form_field.dart'; import 'package:eatvio_app/widgets/custom_edit_drop_down.dart'; import 'package:eatvio_app/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/widgets/custom_scale_element.dart'; -import 'package:flutter_typeahead/flutter_typeahead.dart'; // ignore: must_be_immutable class DiaryEditScreen extends StatelessWidget { @@ -304,7 +303,7 @@ class DiaryEditScreen extends StatelessWidget { /*print(state.autocompleteList ?.map((dynamic item) => item as String) .toList());*/ - if (value.length > 3) { + if (value.length > 2) { context.read().add(ProductInput(value)); } }, @@ -474,7 +473,9 @@ class DiaryEditScreen extends StatelessWidget { bottom: 3.v, ), child: Text( - portion['quantity'] + portion['portion'], + portion['quantity'].toString() + + ' ' + + portion['portion'].toString(), ), ), Spacer(), diff --git a/lib/widgets/custom_autocomplete.dart b/lib/widgets/custom_autocomplete.dart index a0560c1c..66e042dc 100644 --- a/lib/widgets/custom_autocomplete.dart +++ b/lib/widgets/custom_autocomplete.dart @@ -1,5 +1,3 @@ -import 'package:eatvio_app/core/app_export.dart'; -import 'package:flutter/material.dart'; /* class CustomTextFormField extends StatelessWidget { // ... From e72367c6565b458062e28d97eceea66f732be938 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 11:12:10 +0300 Subject: [PATCH 18/39] refactor(diary): Flutter analyze mediaQueryData issue fix attempt --- lib/core/utils/pref_utils.dart | 2 -- lib/core/utils/size_utils.dart | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/core/utils/pref_utils.dart b/lib/core/utils/pref_utils.dart index 5238073f..9c49a3d2 100644 --- a/lib/core/utils/pref_utils.dart +++ b/lib/core/utils/pref_utils.dart @@ -1,5 +1,3 @@ -//ignore: unused_import -import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class PrefUtils { diff --git a/lib/core/utils/size_utils.dart b/lib/core/utils/size_utils.dart index 8911620b..a6de3e67 100644 --- a/lib/core/utils/size_utils.dart +++ b/lib/core/utils/size_utils.dart @@ -1,10 +1,9 @@ -import 'dart:ui' as ui; import 'package:flutter/material.dart'; // This functions are responsible to make UI responsive across all the mobile devices. -// ignore: deprecated_member_use -MediaQueryData mediaQueryData = MediaQueryData.fromView(ui.window); +MediaQueryData mediaQueryData = MediaQueryData.fromView( + WidgetsBinding.instance.platformDispatcher.views.single); // These are the Viewport values of your Figma Design. // These are used in the code as a reference to create your UI Responsively. From d5a5ac3ebe17fc553069ae0f6da90380ab782517 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 08:18:24 +0000 Subject: [PATCH 19/39] Update .env --- .env.example => .env | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .env.example => .env (100%) diff --git a/.env.example b/.env similarity index 100% rename from .env.example rename to .env From 0f37f378a3d22f5498334775a073929ca3c96a1b Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 12:46:01 +0300 Subject: [PATCH 20/39] refactor(diary): Refactoring flutter analyze finished. Started refactoring Run Code Metrics --- .../language_select_screen.dart | 60 ++++---- lib/widgets/app_bar/appbar_leading_image.dart | 8 +- lib/widgets/app_bar/appbar_subtitle.dart | 8 +- .../app_bar/appbar_title_circleimage.dart | 8 +- lib/widgets/app_bar/appbar_title_image.dart | 8 +- lib/widgets/app_bar/exit_button.dart | 8 +- lib/widgets/custom_bottom_bar.dart | 129 ++++++++---------- lib/widgets/custom_text_form_field.dart | 118 +++++++++------- lib/widgets/next_step_button.dart | 78 ++++++----- 9 files changed, 225 insertions(+), 200 deletions(-) diff --git a/lib/presentation/registration/language_select_screen/language_select_screen.dart b/lib/presentation/registration/language_select_screen/language_select_screen.dart index cd8b9b4b..56e644a0 100644 --- a/lib/presentation/registration/language_select_screen/language_select_screen.dart +++ b/lib/presentation/registration/language_select_screen/language_select_screen.dart @@ -64,23 +64,22 @@ class LanguageSelectScreen extends StatelessWidget { languageSelectModelObj, ) { return CustomDropDown( - icon: Container( - margin: - EdgeInsets.fromLTRB(30.h, 11.v, 17.h, 11.v), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(1.h)), - child: CustomImageView( - imagePath: ImageConstant.imgFavorite, - height: 12.adaptSize, - width: 12.adaptSize)), - hintText: "Не выбрано".tr, - items: - languageSelectModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context - .read() - .add(ChangeDropDownEvent(value: value)); - }); + icon: Container( + margin: EdgeInsets.fromLTRB(30.h, 11.v, 17.h, 11.v), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(1.h), + ), + child: CustomImageView( + imagePath: ImageConstant.imgFavorite, + height: 12.adaptSize, + width: 12.adaptSize, + ), + ), + hintText: "Не выбрано".tr, + items: languageSelectModelObj?.dropdownItemList ?? [], + onChanged: (value) => + _onDropDownChanged(context, value), + ); }), Spacer(flex: 63), ])), @@ -92,15 +91,24 @@ class LanguageSelectScreen extends StatelessWidget { margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.languageSelectModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.credentialsScreen, - arguments: sheet, - ); - }); + onPressed: _saveAndPush(state, context)); }))); } + + void Function()? _saveAndPush( + LanguageSelectState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.languageSelectModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.credentialsScreen, + arguments: sheet, + ); + }; + } + + void _onDropDownChanged(BuildContext context, value) { + context.read().add(ChangeDropDownEvent(value: value)); + } } diff --git a/lib/widgets/app_bar/appbar_leading_image.dart b/lib/widgets/app_bar/appbar_leading_image.dart index 5c9ff8e4..003d9f03 100644 --- a/lib/widgets/app_bar/appbar_leading_image.dart +++ b/lib/widgets/app_bar/appbar_leading_image.dart @@ -21,9 +21,7 @@ class AppbarLeadingImage extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - onTap: () { - onTap!.call(); - }, + onTap: onTapCall, child: Padding( padding: margin ?? EdgeInsets.zero, child: CustomImageView( @@ -35,4 +33,8 @@ class AppbarLeadingImage extends StatelessWidget { ), ); } + + void onTapCall() { + onTap!.call(); + } } diff --git a/lib/widgets/app_bar/appbar_subtitle.dart b/lib/widgets/app_bar/appbar_subtitle.dart index 69c1b639..58779324 100644 --- a/lib/widgets/app_bar/appbar_subtitle.dart +++ b/lib/widgets/app_bar/appbar_subtitle.dart @@ -21,9 +21,7 @@ class AppbarSubtitle extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( - onTap: () { - onTap!.call(); - }, + onTap: onTapCall, child: Padding( padding: margin ?? EdgeInsets.zero, child: Text( @@ -35,4 +33,8 @@ class AppbarSubtitle extends StatelessWidget { ), ); } + + void onTapCall() { + onTap!.call(); + } } diff --git a/lib/widgets/app_bar/appbar_title_circleimage.dart b/lib/widgets/app_bar/appbar_title_circleimage.dart index ee412291..66f82ef9 100644 --- a/lib/widgets/app_bar/appbar_title_circleimage.dart +++ b/lib/widgets/app_bar/appbar_title_circleimage.dart @@ -22,9 +22,7 @@ class AppbarTitleCircleimage extends StatelessWidget { Widget build(BuildContext context) { return InkWell( borderRadius: BorderRadiusStyle.circleBorder8, - onTap: () { - onTap!.call(); - }, + onTap: onTapCall, child: Padding( padding: margin ?? EdgeInsets.zero, child: CustomImageView( @@ -39,4 +37,8 @@ class AppbarTitleCircleimage extends StatelessWidget { ), ); } + + void onTapCall() { + onTap!.call(); + } } diff --git a/lib/widgets/app_bar/appbar_title_image.dart b/lib/widgets/app_bar/appbar_title_image.dart index 3ccfd581..e15f1c52 100644 --- a/lib/widgets/app_bar/appbar_title_image.dart +++ b/lib/widgets/app_bar/appbar_title_image.dart @@ -21,9 +21,7 @@ class AppbarTitleImage extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - onTap: () { - onTap!.call(); - }, + onTap: onTapCall, child: Padding( padding: margin ?? EdgeInsets.zero, child: CustomImageView( @@ -35,4 +33,8 @@ class AppbarTitleImage extends StatelessWidget { ), ); } + + void onTapCall() { + onTap!.call(); + } } diff --git a/lib/widgets/app_bar/exit_button.dart b/lib/widgets/app_bar/exit_button.dart index a93c9a84..ee0d27dd 100644 --- a/lib/widgets/app_bar/exit_button.dart +++ b/lib/widgets/app_bar/exit_button.dart @@ -21,9 +21,7 @@ class ExitButton extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( - onTap: () { - onTap!.call(); - }, + onTap: onTapCall, child: Padding( padding: margin ?? EdgeInsets.zero, child: Text( @@ -35,4 +33,8 @@ class ExitButton extends StatelessWidget { ), ); } + + void onTapCall() { + onTap!.call(); + } } diff --git a/lib/widgets/custom_bottom_bar.dart b/lib/widgets/custom_bottom_bar.dart index c32781a2..45928ebd 100644 --- a/lib/widgets/custom_bottom_bar.dart +++ b/lib/widgets/custom_bottom_bar.dart @@ -65,60 +65,63 @@ class CustomBottomBarState extends State { elevation: 0, currentIndex: selectedIndex, type: BottomNavigationBarType.fixed, - items: List.generate(bottomMenuList.length, (index) { - return BottomNavigationBarItem( - icon: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CustomImageView( - imagePath: bottomMenuList[index].icon, - height: 24.v, - width: 19.h, - color: appTheme.blueGray400, - ), - Padding( - padding: EdgeInsets.only(top: 8.v), - child: Text( - bottomMenuList[index].title ?? "", - style: - CustomTextStyles.bodySmallMulishBluegray80012.copyWith( - color: appTheme.blueGray800, - ), - ), - ), - ], - ), - activeIcon: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CustomImageView( - imagePath: bottomMenuList[index].activeIcon, - height: 24.adaptSize, - width: 24.adaptSize, - color: theme.colorScheme.primary, - ), - Padding( - padding: EdgeInsets.only(top: 9.v), - child: Text( - bottomMenuList[index].title ?? "", - style: CustomTextStyles.bodySmallMulishPrimary.copyWith( - color: theme.colorScheme.primary, - ), - ), - ), - ], - ), - label: '', - ); - }), - onTap: (index) { - selectedIndex = index; - widget.onChanged?.call(bottomMenuList[index].type); - setState(() {}); - }, + items: List.generate(bottomMenuList.length, bottomMenu), + onTap: changeMeny, ), ); } + + void changeMeny(index) { + selectedIndex = index; + widget.onChanged?.call(bottomMenuList[index].type); + setState(() {}); + } + + BottomNavigationBarItem bottomMenu(index) { + return BottomNavigationBarItem( + icon: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CustomImageView( + imagePath: bottomMenuList[index].icon, + height: 24.v, + width: 19.h, + color: appTheme.blueGray400, + ), + Padding( + padding: EdgeInsets.only(top: 8.v), + child: Text( + bottomMenuList[index].title ?? "", + style: CustomTextStyles.bodySmallMulishBluegray80012.copyWith( + color: appTheme.blueGray800, + ), + ), + ), + ], + ), + activeIcon: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CustomImageView( + imagePath: bottomMenuList[index].activeIcon, + height: 24.adaptSize, + width: 24.adaptSize, + color: theme.colorScheme.primary, + ), + Padding( + padding: EdgeInsets.only(top: 9.v), + child: Text( + bottomMenuList[index].title ?? "", + style: CustomTextStyles.bodySmallMulishPrimary.copyWith( + color: theme.colorScheme.primary, + ), + ), + ), + ], + ), + label: '', + ); + } } enum BottomBarEnum { @@ -141,27 +144,3 @@ class BottomMenuModel { BottomBarEnum type; } - -class DefaultWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - color: Colors.white, - padding: EdgeInsets.all(10), - child: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Please replace the respective Widget here', - style: TextStyle( - fontSize: 18, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/widgets/custom_text_form_field.dart b/lib/widgets/custom_text_form_field.dart index a96c5a1c..65ee6920 100644 --- a/lib/widgets/custom_text_form_field.dart +++ b/lib/widgets/custom_text_form_field.dart @@ -81,67 +81,79 @@ class CustomTextFormField extends StatelessWidget { final void Function(String?)? onSaved; + To resolve the error "Avoid returning widgets from a getter," you can refactor the textFormFieldWidget and decoration getters into regular methods and then call those methods within the build method. Here's the refactored code: + +dart + +class CustomTextFormField extends StatelessWidget { + // ... other properties remain the same + @override Widget build(BuildContext context) { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: textFormFieldWidget, + child: _buildTextFormFieldWidget(), ) - : textFormFieldWidget; + : _buildTextFormFieldWidget(); } - Widget get textFormFieldWidget => SizedBox( - width: width ?? double.maxFinite, - child: TextFormField( - controller: controller, - focusNode: focusNode ?? FocusNode(), - autofocus: autofocus!, - style: textStyle ?? theme.textTheme.titleMedium, - obscureText: obscureText!, - textInputAction: textInputAction, - maxLines: maxLines ?? 1, - decoration: decoration, - validator: validator, - keyboardType: keyboardType, - onSaved: onSaved, - inputFormatters: inputFormatters, - ), - ); - InputDecoration get decoration => InputDecoration( - hintText: hintText ?? "", - hintStyle: hintStyle ?? theme.textTheme.bodyLarge, - prefixIcon: prefix, - prefixIconConstraints: prefixConstraints, - suffixIcon: suffix, - suffixIconConstraints: suffixConstraints, - isDense: true, - contentPadding: contentPadding ?? EdgeInsets.all(6.h), - fillColor: fillColor ?? theme.colorScheme.onPrimary, - filled: filled, - border: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), + Widget _buildTextFormFieldWidget() { + return SizedBox( + width: width ?? double.maxFinite, + child: TextFormField( + controller: controller, + focusNode: focusNode ?? FocusNode(), + autofocus: autofocus!, + style: textStyle ?? theme.textTheme.titleMedium, + obscureText: obscureText!, + textInputAction: textInputAction, + maxLines: maxLines ?? 1, + decoration: _buildInputDecoration(), + validator: validator, + keyboardType: keyboardType, + onSaved: onSaved, + inputFormatters: inputFormatters, + ), + ); + } + + InputDecoration _buildInputDecoration() { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? theme.textTheme.bodyLarge, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? EdgeInsets.all(6.h), + fillColor: fillColor ?? theme.colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, ), - enabledBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, ), - focusedBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, ), - ); -} + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/next_step_button.dart b/lib/widgets/next_step_button.dart index ce972835..455f8f94 100644 --- a/lib/widgets/next_step_button.dart +++ b/lib/widgets/next_step_button.dart @@ -31,43 +31,59 @@ class NextStepButton extends BaseButton { ); final BoxDecoration? decoration; - final Widget? leftIcon; - final Widget? rightIcon; - final Widget? label; @override Widget build(BuildContext context) { - return alignment != null + return (alignment != null) ? Align( - alignment: alignment ?? Alignment.center, - child: buildOutlinedButtonWidget, - ) - : buildOutlinedButtonWidget; - } - - Widget get buildOutlinedButtonWidget => Container( - height: this.height ?? 30.v, - width: this.width ?? double.maxFinite, - margin: margin, - decoration: decoration, - child: OutlinedButton( - style: buttonStyle, - onPressed: isDisabled ?? false ? null : onPressed ?? () {}, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - leftIcon ?? const SizedBox.shrink(), - Text( - text, - style: buttonTextStyle ?? theme.textTheme.titleSmall, + alignment: alignment!, + child: Container( + height: this.height ?? 30.v, + width: this.width ?? double.maxFinite, + margin: margin, + decoration: decoration, + child: OutlinedButton( + style: buttonStyle, + onPressed: isDisabled ?? false ? null : onPressed ?? () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + leftIcon ?? const SizedBox.shrink(), + Text( + text, + style: buttonTextStyle ?? theme.textTheme.titleSmall, + ), + rightIcon ?? const SizedBox.shrink(), + ], + ), ), - rightIcon ?? const SizedBox.shrink(), - ], - ), - ), - ); + ), + ) + : Container( + height: this.height ?? 30.v, + width: this.width ?? double.maxFinite, + margin: margin, + decoration: decoration, + child: OutlinedButton( + style: buttonStyle, + onPressed: isDisabled ?? false ? null : onPressed ?? () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + leftIcon ?? const SizedBox.shrink(), + Text( + text, + style: buttonTextStyle ?? theme.textTheme.titleSmall, + ), + rightIcon ?? const SizedBox.shrink(), + ], + ), + ), + ); + } } From cb17172cb04bf01ab2bd2e214fac9ae64df1e573 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 12:58:37 +0300 Subject: [PATCH 21/39] refactor(diary): Refactoring metrics for CustomOutlinedButton --- lib/widgets/custom_text_form_field.dart | 162 ++++++++++++++++-------- 1 file changed, 107 insertions(+), 55 deletions(-) diff --git a/lib/widgets/custom_text_form_field.dart b/lib/widgets/custom_text_form_field.dart index 65ee6920..0d11d1f3 100644 --- a/lib/widgets/custom_text_form_field.dart +++ b/lib/widgets/custom_text_form_field.dart @@ -34,91 +34,143 @@ class CustomTextFormField extends StatelessWidget { ); final Alignment? alignment; - final double? width; - final TextEditingController? controller; - final FocusNode? focusNode; - final bool? autofocus; - final TextStyle? textStyle; - final bool? obscureText; - final List? inputFormatters; - final TextInputAction? textInputAction; - final TextInputType? textInputType; - final int? maxLines; - final String? hintText; - final TextStyle? hintStyle; - final Widget? prefix; - final BoxConstraints? prefixConstraints; - final Widget? suffix; - final BoxConstraints? suffixConstraints; - final EdgeInsets? contentPadding; - final InputBorder? borderDecoration; - final Color? fillColor; - final bool? filled; - final TextInputType? keyboardType; - final FormFieldValidator? validator; - final void Function(String?)? onSaved; - To resolve the error "Avoid returning widgets from a getter," you can refactor the textFormFieldWidget and decoration getters into regular methods and then call those methods within the build method. Here's the refactored code: - -dart - -class CustomTextFormField extends StatelessWidget { - // ... other properties remain the same - @override Widget build(BuildContext context) { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: _buildTextFormFieldWidget(), + child: SizedBox( + width: width ?? double.maxFinite, + child: TextFormField( + controller: controller, + focusNode: focusNode ?? FocusNode(), + autofocus: autofocus!, + style: textStyle ?? theme.textTheme.titleMedium, + obscureText: obscureText!, + textInputAction: textInputAction, + maxLines: maxLines ?? 1, + decoration: InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? theme.textTheme.bodyLarge, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? EdgeInsets.all(6.h), + fillColor: fillColor ?? theme.colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + ), + keyboardType: keyboardType, + validator: validator, + onSaved: onSaved, + inputFormatters: inputFormatters, + ), + ), ) - : _buildTextFormFieldWidget(); + : SizedBox( + width: width ?? double.maxFinite, + child: TextFormField( + controller: controller, + focusNode: focusNode ?? FocusNode(), + autofocus: autofocus!, + style: textStyle ?? theme.textTheme.titleMedium, + obscureText: obscureText!, + textInputAction: textInputAction, + maxLines: maxLines ?? 1, + decoration: InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? theme.textTheme.bodyLarge, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? EdgeInsets.all(6.h), + fillColor: fillColor ?? theme.colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: BorderRadius.circular(8.h), + borderSide: BorderSide( + color: appTheme.blueA400, + width: 1, + ), + ), + ), + keyboardType: keyboardType, + validator: validator, + onSaved: onSaved, + inputFormatters: inputFormatters, + ), + ); } - - Widget _buildTextFormFieldWidget() { - return SizedBox( - width: width ?? double.maxFinite, - child: TextFormField( - controller: controller, - focusNode: focusNode ?? FocusNode(), - autofocus: autofocus!, - style: textStyle ?? theme.textTheme.titleMedium, - obscureText: obscureText!, - textInputAction: textInputAction, - maxLines: maxLines ?? 1, - decoration: _buildInputDecoration(), - validator: validator, - keyboardType: keyboardType, - onSaved: onSaved, - inputFormatters: inputFormatters, - ), - ); - } - - InputDecoration _buildInputDecoration() { +} + /* InputDecoration _buildInputDecoration() { return InputDecoration( hintText: hintText ?? "", hintStyle: hintStyle ?? theme.textTheme.bodyLarge, @@ -156,4 +208,4 @@ class CustomTextFormField extends StatelessWidget { ), ); } -} \ No newline at end of file +}*/ \ No newline at end of file From 9251e65d132b4f34f8f73c0fd6fee224b4d142e3 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 14:20:32 +0300 Subject: [PATCH 22/39] refactor(diary): More refactoring --- lib/widgets/custom_icon_button.dart | 60 +++++++++----------- lib/widgets/custom_image_view.dart | 28 +++++----- lib/widgets/custom_outlined_button.dart | 73 ++++++++++++++++++++----- 3 files changed, 99 insertions(+), 62 deletions(-) diff --git a/lib/widgets/custom_icon_button.dart b/lib/widgets/custom_icon_button.dart index cdf5b5b5..55766f18 100644 --- a/lib/widgets/custom_icon_button.dart +++ b/lib/widgets/custom_icon_button.dart @@ -10,22 +10,14 @@ class CustomIconButton extends StatelessWidget { this.decoration, this.child, this.onTap, - }) : super( - key: key, - ); + }) : super(key: key); final Alignment? alignment; - final double? height; - final double? width; - final EdgeInsetsGeometry? padding; - final BoxDecoration? decoration; - final Widget? child; - final VoidCallback? onTap; @override @@ -33,40 +25,40 @@ class CustomIconButton extends StatelessWidget { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: iconButtonWidget, + child: _buildIconButtonWidget(), ) - : iconButtonWidget; + : _buildIconButtonWidget(); } - Widget get iconButtonWidget => SizedBox( - height: height ?? 0, - width: width ?? 0, - child: IconButton( - padding: EdgeInsets.zero, - icon: Container( - height: height ?? 0, - width: width ?? 0, - padding: padding ?? EdgeInsets.zero, - decoration: decoration ?? - BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(9), - border: Border.all( - color: Colors.blueGrey, - width: 1, - ), - ), - child: child, - ), - onPressed: onTap, + _buildIconButtonWidget() { + return SizedBox( + height: height ?? 0, + width: width ?? 0, + child: IconButton( + padding: EdgeInsets.zero, + icon: Container( + height: height ?? 0, + width: width ?? 0, + padding: padding ?? EdgeInsets.zero, + decoration: decoration ?? + BoxDecoration( + color: Colors.black, + borderRadius: const BorderRadius.all(Radius.circular(9)), + border: const Border.fromBorderSide( + BorderSide(color: Colors.blueGrey, width: 1)), + ), + child: child, ), - ); + onPressed: onTap, + ), + ); + } } /// Extension on [CustomIconButton] to facilitate inclusion of all types of border style etc extension IconButtonStyleHelper on CustomIconButton { static BoxDecoration get fillBlueA => BoxDecoration( color: Colors.blue, - borderRadius: BorderRadius.circular(14), + borderRadius: const BorderRadius.all(Radius.circular(14)), ); } diff --git a/lib/widgets/custom_image_view.dart b/lib/widgets/custom_image_view.dart index 03bd0cbf..07b9a5d9 100644 --- a/lib/widgets/custom_image_view.dart +++ b/lib/widgets/custom_image_view.dart @@ -42,19 +42,21 @@ class CustomImageView extends StatelessWidget { return alignment != null ? Align( alignment: alignment!, - child: _buildWidget(), + child: Padding( + padding: margin ?? EdgeInsets.zero, + child: InkWell( + onTap: onTap, + child: _buildCircleImage(), + ), + ), ) - : _buildWidget(); - } - - Widget _buildWidget() { - return Padding( - padding: margin ?? EdgeInsets.zero, - child: InkWell( - onTap: onTap, - child: _buildCircleImage(), - ), - ); + : Padding( + padding: margin ?? EdgeInsets.zero, + child: InkWell( + onTap: onTap, + child: _buildCircleImage(), + ), + ); } ///build the image with border radius @@ -84,7 +86,7 @@ class CustomImageView extends StatelessWidget { } } - Widget _buildImageView() { + _buildImageView() { if (imagePath != null) { switch (imagePath!.imageType) { case ImageType.svg: diff --git a/lib/widgets/custom_outlined_button.dart b/lib/widgets/custom_outlined_button.dart index 4fb4a85c..f2ffd707 100644 --- a/lib/widgets/custom_outlined_button.dart +++ b/lib/widgets/custom_outlined_button.dart @@ -31,43 +31,86 @@ class CustomOutlinedButton extends BaseButton { ); final BoxDecoration? decoration; - final Widget? leftIcon; - final Widget? rightIcon; - final Widget? label; @override Widget build(BuildContext context) { - return alignment != null - ? Align( - alignment: alignment ?? Alignment.center, - child: buildOutlinedButtonWidget, - ) - : buildOutlinedButtonWidget; - } - - Widget get buildOutlinedButtonWidget => Container( + if (alignment != null) { + return Align( + alignment: alignment ?? Alignment.center, + child: Container( + height: this.height ?? 30.v, + width: this.width ?? double.maxFinite, + margin: margin, + decoration: decoration, + child: OutlinedButton( + style: buttonStyle!, + onPressed: isDisabled ?? false ? null : onPressed ?? () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + leftIcon ?? SizedBox.shrink(), + Text( + text, + style: buttonTextStyle ?? CustomTextStyles.titleSmallBold, + ), + rightIcon ?? SizedBox.shrink(), + ], + ), + ), + ), + ); + } else { + return Container( height: this.height ?? 30.v, width: this.width ?? double.maxFinite, margin: margin, decoration: decoration, child: OutlinedButton( - style: buttonStyle, + style: buttonStyle!, onPressed: isDisabled ?? false ? null : onPressed ?? () {}, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - leftIcon ?? const SizedBox.shrink(), + leftIcon ?? SizedBox.shrink(), Text( text, style: buttonTextStyle ?? CustomTextStyles.titleSmallBold, ), - rightIcon ?? const SizedBox.shrink(), + rightIcon ?? SizedBox.shrink(), ], ), ), ); + } + } + + /*Widget _buildOutlinedButtonWidget() { + return Container( + height: this.height ?? 30.v, + width: this.width ?? double.maxFinite, + margin: margin, + decoration: decoration, + child: OutlinedButton( + style: buttonStyle!, + onPressed: isDisabled ?? false ? null : onPressed ?? () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + leftIcon ?? SizedBox.shrink(), + Text( + text, + style: buttonTextStyle ?? CustomTextStyles.titleSmallBold, + ), + rightIcon ?? SizedBox.shrink(), + ], + ), + ), + ); + }*/ } From 247d4b9fee52ad907d68bb4d6fb11e749b720369 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 14:28:08 +0300 Subject: [PATCH 23/39] refactor(diary): Refactoring again --- lib/widgets/custom_edit_text_form_field.dart | 107 +++++++++---------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/lib/widgets/custom_edit_text_form_field.dart b/lib/widgets/custom_edit_text_form_field.dart index 5b27a43f..2032ee9e 100644 --- a/lib/widgets/custom_edit_text_form_field.dart +++ b/lib/widgets/custom_edit_text_form_field.dart @@ -92,61 +92,60 @@ class CustomTextFormField extends StatelessWidget { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: textFormFieldWidget, + child: _buildTextFormFieldWidget(context), ) - : textFormFieldWidget; + : _buildTextFormFieldWidget(context); } - Widget get textFormFieldWidget => SizedBox( - width: width ?? double.maxFinite, - child: TextFormField( - controller: controller, - focusNode: focusNode ?? FocusNode(), - autofocus: autofocus!, - style: textStyle ?? theme.textTheme.titleMedium, - obscureText: obscureText!, - textInputAction: textInputAction, - maxLines: maxLines ?? 1, - decoration: decoration, - validator: validator, - keyboardType: keyboardType, - onSaved: onSaved, - onChanged: onChanged, - inputFormatters: inputFormatters, - initialValue: initialValue, - ), - ); - InputDecoration get decoration => InputDecoration( - hintText: hintText ?? "", - hintStyle: hintStyle ?? theme.textTheme.bodyLarge, - prefixIcon: prefix, - prefixIconConstraints: prefixConstraints, - suffixIcon: suffix, - suffixIconConstraints: suffixConstraints, - isDense: true, - contentPadding: contentPadding ?? EdgeInsets.all(6.h), - fillColor: fillColor ?? theme.colorScheme.onPrimary, - filled: filled, - border: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide(color: Colors.grey, width: 1), - ), - enabledBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - focusedBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - ); + _buildTextFormFieldWidget(BuildContext context) { + return SizedBox( + width: width ?? double.maxFinite, + child: TextFormField( + controller: controller, + focusNode: focusNode ?? FocusNode(), + autofocus: autofocus!, + style: textStyle ?? Theme.of(context).textTheme.titleMedium, + obscureText: obscureText!, + textInputAction: textInputAction, + maxLines: maxLines ?? 1, + decoration: _buildInputDecoration(context), + validator: validator, + keyboardType: keyboardType, + onSaved: onSaved, + onChanged: onChanged, + inputFormatters: inputFormatters, + initialValue: initialValue, + ), + ); + } + + InputDecoration _buildInputDecoration(BuildContext context) { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? Theme.of(context).textTheme.bodyLarge, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? EdgeInsets.all(6), + fillColor: fillColor ?? Theme.of(context).colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + ); + } } From 700bef25764db43deae870b0f2eb16b1493f6c3b Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 14:32:15 +0300 Subject: [PATCH 24/39] refactor(diary): Refactoring once more --- lib/widgets/custom_edit_drop_down.dart | 132 +++++++++---------- lib/widgets/custom_edit_text_form_field.dart | 1 - 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/lib/widgets/custom_edit_drop_down.dart b/lib/widgets/custom_edit_drop_down.dart index 59c58593..7f56bbd8 100644 --- a/lib/widgets/custom_edit_drop_down.dart +++ b/lib/widgets/custom_edit_drop_down.dart @@ -73,75 +73,73 @@ class CustomDropDown extends StatelessWidget { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: dropDownWidget, + child: _buildDropDownWidget(context), ) - : dropDownWidget; + : _buildDropDownWidget(context); } - Widget get dropDownWidget => SizedBox( - width: width ?? double.maxFinite, - child: DropdownButtonFormField( - focusNode: focusNode ?? FocusNode(), - icon: icon, - autofocus: autofocus!, - style: textStyle ?? theme.textTheme.titleMedium, - items: items?.map((SelectionPopupModel item) { - return DropdownMenuItem( - value: item, - child: Text( - item.title, - overflow: TextOverflow.ellipsis, - style: hintStyle ?? theme.textTheme.titleMedium, - ), - ); - }).toList(), - decoration: decoration, - validator: validator, - value: defaultValue, - onChanged: (value) { - onChanged!(value!); - }, - ), - ); - InputDecoration get decoration => InputDecoration( - hintText: hintText ?? "", - hintStyle: hintStyle ?? theme.textTheme.titleMedium, - prefixIcon: prefix, - prefixIconConstraints: prefixConstraints, - suffixIcon: suffix, - suffixIconConstraints: suffixConstraints, - isDense: true, - contentPadding: contentPadding ?? - EdgeInsets.only( - left: 6.h, - top: 6.v, - bottom: 6.v, + _buildDropDownWidget(BuildContext context) { + return SizedBox( + width: width ?? double.maxFinite, + child: DropdownButtonFormField( + focusNode: focusNode ?? FocusNode(), + icon: icon, + autofocus: autofocus!, + style: textStyle ?? Theme.of(context).textTheme.titleMedium, + items: items?.map((SelectionPopupModel item) { + return DropdownMenuItem( + value: item, + child: Text( + item.title, + overflow: TextOverflow.ellipsis, + style: hintStyle ?? Theme.of(context).textTheme.titleMedium, ), - fillColor: fillColor ?? theme.colorScheme.onPrimary, - filled: filled, - border: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - enabledBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - focusedBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: Colors.grey, - width: 1, - ), - ), - ); + ); + }).toList(), + decoration: _buildInputDecoration(context), + validator: validator, + value: defaultValue, + onChanged: onDropDownChanged, + ), + ); + } + + void onDropDownChanged(value) { + onChanged!(value!); + } + + InputDecoration _buildInputDecoration(BuildContext context) { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? Theme.of(context).textTheme.titleMedium, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? + EdgeInsets.only( + left: 6, + top: 6, + bottom: 6, + ), + fillColor: fillColor ?? Theme.of(context).colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: Colors.grey, width: 1), + ), + ); + } } diff --git a/lib/widgets/custom_edit_text_form_field.dart b/lib/widgets/custom_edit_text_form_field.dart index 2032ee9e..aeeb19e7 100644 --- a/lib/widgets/custom_edit_text_form_field.dart +++ b/lib/widgets/custom_edit_text_form_field.dart @@ -1,4 +1,3 @@ -import 'package:eatvio_app/core/app_export.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; From 2f338b04d1d1a7936576882ad73999b796a2ff40 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 14:34:27 +0300 Subject: [PATCH 25/39] refactor(diary): Refactoring returns --- lib/widgets/custom_drop_down.dart | 130 +++++++++++++++--------------- 1 file changed, 64 insertions(+), 66 deletions(-) diff --git a/lib/widgets/custom_drop_down.dart b/lib/widgets/custom_drop_down.dart index dd5afc7d..55f1231f 100644 --- a/lib/widgets/custom_drop_down.dart +++ b/lib/widgets/custom_drop_down.dart @@ -70,74 +70,72 @@ class CustomDropDown extends StatelessWidget { return alignment != null ? Align( alignment: alignment ?? Alignment.center, - child: dropDownWidget, + child: _buildDropDownWidget(context), ) - : dropDownWidget; + : _buildDropDownWidget(context); } - Widget get dropDownWidget => SizedBox( - width: width ?? double.maxFinite, - child: DropdownButtonFormField( - focusNode: focusNode ?? FocusNode(), - icon: icon, - autofocus: autofocus!, - style: textStyle ?? theme.textTheme.titleMedium, - items: items?.map((SelectionPopupModel item) { - return DropdownMenuItem( - value: item, - child: Text( - item.title, - overflow: TextOverflow.ellipsis, - style: hintStyle ?? theme.textTheme.titleMedium, - ), - ); - }).toList(), - decoration: decoration, - validator: validator, - onChanged: (value) { - onChanged!(value!); - }, - ), - ); - InputDecoration get decoration => InputDecoration( - hintText: hintText ?? "", - hintStyle: hintStyle ?? theme.textTheme.titleMedium, - prefixIcon: prefix, - prefixIconConstraints: prefixConstraints, - suffixIcon: suffix, - suffixIconConstraints: suffixConstraints, - isDense: true, - contentPadding: contentPadding ?? - EdgeInsets.only( - left: 6.h, - top: 6.v, - bottom: 6.v, + _buildDropDownWidget(BuildContext context) { + return SizedBox( + width: width ?? double.maxFinite, + child: DropdownButtonFormField( + focusNode: focusNode ?? FocusNode(), + icon: icon, + autofocus: autofocus!, + style: textStyle ?? Theme.of(context).textTheme.titleMedium, + items: items?.map((SelectionPopupModel item) { + return DropdownMenuItem( + value: item, + child: Text( + item.title, + overflow: TextOverflow.ellipsis, + style: hintStyle ?? Theme.of(context).textTheme.titleMedium, ), - fillColor: fillColor ?? theme.colorScheme.onPrimary, - filled: filled, - border: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), - ), - enabledBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), - ), - focusedBorder: borderDecoration ?? - OutlineInputBorder( - borderRadius: BorderRadius.circular(8.h), - borderSide: BorderSide( - color: appTheme.blueA400, - width: 1, - ), - ), - ); + ); + }).toList(), + decoration: _buildInputDecoration(context), + validator: validator, + onChanged: onDropDownChanged, + ), + ); + } + + void onDropDownChanged(value) { + onChanged!(value!); + } + + InputDecoration _buildInputDecoration(BuildContext context) { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: hintStyle ?? Theme.of(context).textTheme.titleMedium, + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + isDense: true, + contentPadding: contentPadding ?? + EdgeInsets.only( + left: 6, + top: 6, + bottom: 6, + ), + fillColor: fillColor ?? Theme.of(context).colorScheme.onPrimary, + filled: filled, + border: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: appTheme.blueA400, width: 1), + ), + enabledBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: appTheme.blueA400, width: 1), + ), + focusedBorder: borderDecoration ?? + OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide(color: appTheme.blueA400, width: 1), + ), + ); + } } From 5d7467db5141f8111ccf741f2b48e7915a5245fd Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 14:44:04 +0300 Subject: [PATCH 26/39] refactor(diary): Revenge of the Refactoring --- .../weight_screen/weight_screen.dart | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/presentation/registration/weight_screen/weight_screen.dart b/lib/presentation/registration/weight_screen/weight_screen.dart index ab936350..64cec0a3 100644 --- a/lib/presentation/registration/weight_screen/weight_screen.dart +++ b/lib/presentation/registration/weight_screen/weight_screen.dart @@ -77,11 +77,7 @@ class _WeightScreenState extends State { width: 12.adaptSize)), hintText: "Не выбрано", items: weightModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context - .read() - .add(ChangeDropDownEvent(value: value)); - }); + onChanged: _onDropDownChanged); }) ]) ]), @@ -93,29 +89,19 @@ class _WeightScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.weightModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.heightScreen, - arguments: sheet, - ); - }); + onPressed: onTapNext(context, state)); }), ])))); } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapArrowLeft(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } @@ -125,10 +111,23 @@ class _WeightScreenState extends State { NavigatorService.goBack(); } + onTapNext(BuildContext context, state) { + UserRegistrationSheet sheet = state.weightModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.heightScreen, + arguments: sheet, + ); + } + /// Navigates to the allergiesScreen when the action is triggered. navigateToHeight(BuildContext context) { NavigatorService.pushNamed( AppRoutes.heightScreen, ); } + + void _onDropDownChanged(value) { + context.read().add(ChangeDropDownEvent(value: value)); + } } From 1c3fc731f72f8d983d8e60666aa78f2a8cc3baae Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 15:14:19 +0300 Subject: [PATCH 27/39] refactor(diary): Refactoring forever --- .../registration/name_screen/name_screen.dart | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/presentation/registration/name_screen/name_screen.dart b/lib/presentation/registration/name_screen/name_screen.dart index cc234a77..05759a47 100644 --- a/lib/presentation/registration/name_screen/name_screen.dart +++ b/lib/presentation/registration/name_screen/name_screen.dart @@ -82,58 +82,19 @@ class NameScreen extends StatelessWidget { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - List errors = validateFields( - state.firstNameController!.text, - state.lastNameController!.text); - if (errors.isEmpty) { - UserRegistrationSheet sheet = - state.nameModelObj!.userRegistrationSheet; - sheet.firstName = state.firstNameController!.text; - sheet.lastName = state.lastNameController!.text; - Navigator.pushNamed( - context, - AppRoutes.genderScreen, - arguments: sheet, - ); - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - }); + onPressed: _onTapNext(context, state)); }), ])))); } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapArrowLeft(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } @@ -143,6 +104,45 @@ class NameScreen extends StatelessWidget { NavigatorService.goBack(); } + _onTapNext(BuildContext context, state) { + List errors = validateFields( + state.firstNameController!.text, state.lastNameController!.text); + if (errors.isEmpty) { + UserRegistrationSheet sheet = state.nameModelObj!.userRegistrationSheet; + sheet.firstName = state.firstNameController!.text; + sheet.lastName = state.lastNameController!.text; + Navigator.pushNamed( + context, + AppRoutes.genderScreen, + arguments: sheet, + ); + } else { + String errorMessage = ''; + + for (var error in errors) { + errorMessage += error + '\n\n'; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text(errorMessage), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + } + } + + onTapOk(BuildContext context) { + Navigator.pop(context); + } + List validateFields( String firstName, String lastName, From 59db676f7aeda593be02081dde88a174ed732811 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 15:18:09 +0300 Subject: [PATCH 28/39] refactor(diary): Refatoring --- .../medicine_intake_screen.dart | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/lib/presentation/registration/medicine_intake_screen/medicine_intake_screen.dart b/lib/presentation/registration/medicine_intake_screen/medicine_intake_screen.dart index fc0766f6..51df64aa 100644 --- a/lib/presentation/registration/medicine_intake_screen/medicine_intake_screen.dart +++ b/lib/presentation/registration/medicine_intake_screen/medicine_intake_screen.dart @@ -74,52 +74,63 @@ class _MedicineIntakeScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = state - .medicineIntakeModelObj!.userRegistrationSheet; - sheet.aboutTakingPils = - state.enterInformationController!.text; - Navigator.pushNamed( - context, - AppRoutes.bloodPressureScreen, - arguments: sheet, - ); - }); + onPressed: onTapNext(state, context)); }), BlocBuilder( builder: (context, state) { return GestureDetector( - onTap: () { - UserRegistrationSheet sheet = - state.medicineIntakeModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.bloodPressureScreen, - arguments: sheet, - ); - }, + onTap: onTapSkip(state, context), child: Text("skip".tr, style: theme.textTheme.bodyLarge), ); }), ])))); } + onTapSkip(MedicineIntakeState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.medicineIntakeModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.bloodPressureScreen, + arguments: sheet, + ); + }; + } + + onTapNext(MedicineIntakeState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.medicineIntakeModelObj!.userRegistrationSheet; + sheet.aboutTakingPils = state.enterInformationController!.text; + Navigator.pushNamed( + context, + AppRoutes.bloodPressureScreen, + arguments: sheet, + ); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 31.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildTextFormField(BuildContext context) { + _buildTextFormField(BuildContext context) { return Column(children: [ Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI), From 2723861b0465e21c61216e0cd1fa377cd43b1e81 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 15:26:35 +0300 Subject: [PATCH 29/39] refactor(diary): Another efatoring --- .../favorite_sports_screen.dart | 62 ++++++++++-------- .../gender_screen/gender_screen.dart | 63 ++++++++++++------- .../height_screen/height_screen.dart | 45 +++++++------ 3 files changed, 102 insertions(+), 68 deletions(-) diff --git a/lib/presentation/registration/favorite_sports_screen/favorite_sports_screen.dart b/lib/presentation/registration/favorite_sports_screen/favorite_sports_screen.dart index 8374c74b..cb23b28f 100644 --- a/lib/presentation/registration/favorite_sports_screen/favorite_sports_screen.dart +++ b/lib/presentation/registration/favorite_sports_screen/favorite_sports_screen.dart @@ -71,31 +71,12 @@ class _FavoriteSportsScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = state - .favoriteSportsModelObj! - .userRegistrationSheet; - sheet.aboutSportHobbies = - state.enterinformationController!.text; - Navigator.pushNamed( - context, - AppRoutes.favoriteFoodsScreen, - arguments: sheet, - ); - }); + onPressed: onTapContinue(state, context)); }), BlocBuilder( builder: (context, state) { return GestureDetector( - onTap: () { - UserRegistrationSheet sheet = state - .favoriteSportsModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.favoriteFoodsScreen, - arguments: sheet, - ); - }, + onTap: onTapSkip(state, context), child: Text("skip".tr, style: theme.textTheme.bodyLarge), ); @@ -103,21 +84,50 @@ class _FavoriteSportsScreenState extends State { ])))); } - PreferredSizeWidget _buildAppBar(BuildContext context) { + onTapSkip(FavoriteSportsState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.favoriteSportsModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.favoriteFoodsScreen, + arguments: sheet, + ); + }; + } + + onTapContinue(FavoriteSportsState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.favoriteSportsModelObj!.userRegistrationSheet; + sheet.aboutSportHobbies = state.enterinformationController!.text; + Navigator.pushNamed( + context, + AppRoutes.favoriteFoodsScreen, + arguments: sheet, + ); + }; + } + + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildTextFormFieldSection(BuildContext context) { + _buildTextFormFieldSection(BuildContext context) { return Column(children: [ Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI), diff --git a/lib/presentation/registration/gender_screen/gender_screen.dart b/lib/presentation/registration/gender_screen/gender_screen.dart index 34dcc859..1db99ac0 100644 --- a/lib/presentation/registration/gender_screen/gender_screen.dart +++ b/lib/presentation/registration/gender_screen/gender_screen.dart @@ -63,10 +63,7 @@ class _GenderScreenState extends State { title: Text('Мужской'), value: 'male', groupValue: state.selectedRadioValue, - onChanged: (value) { - BlocProvider.of(context) - .add(GenderSelectEvent(value: 'male')); - }, + onChanged: onMale(context), secondary: Image.asset( 'assets/images/img_male.png', width: 40, @@ -77,10 +74,7 @@ class _GenderScreenState extends State { title: Text('Женский'), value: 'female', groupValue: state.selectedRadioValue, - onChanged: (value) { - BlocProvider.of(context) - .add(GenderSelectEvent(value: 'female')); - }, + onChanged: onFemale(context), secondary: Image.asset( 'assets/images/img_female.png', width: 40, @@ -95,37 +89,58 @@ class _GenderScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.genderModelObj!.userRegistrationSheet; - sheet.gender = state.selectedRadioValue!; - Navigator.pushNamed( - context, - AppRoutes.dateOfBirthScreen, - arguments: sheet, - ); - }); + onPressed: onTapNext(state, context)); }), ])))); }); } + onTapNext(GenderState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = state.genderModelObj!.userRegistrationSheet; + sheet.gender = state.selectedRadioValue!; + Navigator.pushNamed( + context, + AppRoutes.dateOfBirthScreen, + arguments: sheet, + ); + }; + } + + onMale(BuildContext context) { + return (value) { + BlocProvider.of(context) + .add(GenderSelectEvent(value: 'male')); + }; + } + + onFemale(BuildContext context) { + return (value) { + BlocProvider.of(context) + .add(GenderSelectEvent(value: 'female')); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - NavigatorService.pushNamed( - AppRoutes.dateOfBirthScreen, - ); - }), + onTap: onTapBack()), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack() { + return () { + NavigatorService.pushNamed( + AppRoutes.dateOfBirthScreen, + ); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); diff --git a/lib/presentation/registration/height_screen/height_screen.dart b/lib/presentation/registration/height_screen/height_screen.dart index 574bf488..9cb66c29 100644 --- a/lib/presentation/registration/height_screen/height_screen.dart +++ b/lib/presentation/registration/height_screen/height_screen.dart @@ -77,11 +77,7 @@ class _HeightScreenState extends State { width: 12.adaptSize)), hintText: "170", items: heightModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context - .read() - .add(ChangeDropDownEvent(value: value)); - }); + onChanged: newMethod(context)); }) ]) ]), @@ -93,33 +89,46 @@ class _HeightScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.heightModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.bloodPressureScreen, - arguments: sheet, - ); - }); + onPressed: onTapNext(state, context)); }), ])))); } + newMethod(BuildContext context) { + return (value) { + context.read().add(ChangeDropDownEvent(value: value)); + }; + } + + onTapNext(HeightState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = state.heightModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.bloodPressureScreen, + arguments: sheet, + ); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); From ba10b5bdb88dadfbd120c480b77de50653da27e5 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 16:42:23 +0300 Subject: [PATCH 30/39] Refactoring --- .../auth/auth_screen/auth_screen.dart | 156 ++++++++++-------- .../my_profile_screen/my_profile_screen.dart | 2 +- .../my_profile_screen/my_settings_screen.dart | 2 +- .../additional_information_screen.dart | 2 +- .../allergies_screen/allergies_screen.dart | 2 +- .../blood_pressure_screen.dart | 44 ++--- .../body_circumferences_screen.dart | 104 ++++++------ .../city_of_living_screen.dart | 58 ++++--- .../credentials_screen.dart | 95 ++++++----- .../date_of_birth_screen.dart | 70 +++++--- .../favorite_foods_screen.dart | 66 ++++---- 11 files changed, 337 insertions(+), 264 deletions(-) diff --git a/lib/presentation/auth/auth_screen/auth_screen.dart b/lib/presentation/auth/auth_screen/auth_screen.dart index 213e8c29..483e0ff5 100644 --- a/lib/presentation/auth/auth_screen/auth_screen.dart +++ b/lib/presentation/auth/auth_screen/auth_screen.dart @@ -64,94 +64,106 @@ class AuthScreen extends StatelessWidget { margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - Navigator.pushNamed( - context, AppRoutes.languageSelectScreen); - }), + onPressed: onTapNoAccount(context)), NextStepButton( text: "Тест дневника".toUpperCase(), margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - Navigator.pushNamed(context, AppRoutes.diaryEdit); - }), + onPressed: onTapDiaryTest(context)), BlocBuilder(builder: (context, state) { return NextStepButton( text: "authentificate".tr.toUpperCase(), margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () async { - List errors = validateFields( - state.emailController!.text, - state.passwordController!.text); - if (errors.isEmpty) { - final Map credentials = { - 'email': state.emailController!.text, - 'password': state.passwordController!.text, - }; - final response = await http.post( - Uri.parse(dotenv.env['SERVER_ROOT']! + '/login'), - headers: {'Content-Type': 'application/json'}, - body: json.encode(credentials), - encoding: utf8); - if (response.statusCode == 200) { - var res = await jsonDecode(response.body); - final box = await Hive.openBox('token'); - final token = res['token']; - box.put('token', token); - Navigator.pushNamed( - context, - AppRoutes.myProfile, - ); - } else { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text('wrong_credentials'.tr), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - }); + onPressed: onTapAuth(state, context)); }), ]))); } + onTapAuth(AuthState state, BuildContext context) { + return () async { + List errors = validateFields( + state.emailController!.text, state.passwordController!.text); + if (errors.isEmpty) { + final Map credentials = { + 'email': state.emailController!.text, + 'password': state.passwordController!.text, + }; + final response = await http.post( + Uri.parse(dotenv.env['SERVER_ROOT']! + '/login'), + headers: {'Content-Type': 'application/json'}, + body: json.encode(credentials), + encoding: utf8); + if (response.statusCode == 200) { + var res = await jsonDecode(response.body); + final box = await Hive.openBox('token'); + final token = res['token']; + box.put('token', token); + Navigator.pushNamed( + context, + AppRoutes.myProfile, + ); + } else { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text('wrong_credentials'.tr), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + } + } else { + String errorMessage = ''; + + for (var error in errors) { + errorMessage += error + '\n\n'; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text(errorMessage), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + } + }; + } + + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } + + onTapDiaryTest(BuildContext context) { + return () { + Navigator.pushNamed(context, AppRoutes.diaryEdit); + }; + } + + onTapNoAccount(BuildContext context) { + return () { + Navigator.pushNamed(context, AppRoutes.languageSelectScreen); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, centerTitle: true, diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index 3fe87cf2..585fc08d 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -84,7 +84,7 @@ class MyProfileScreen extends StatelessWidget { } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context, String username) { + _buildAppBar(BuildContext context, String username) { return CustomAppBar( height: 54.v, leadingWidth: 28.h, diff --git a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart index 78201e77..2927282e 100644 --- a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart @@ -70,7 +70,7 @@ class MySettingsScreen extends StatelessWidget { } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context, String username) { + _buildAppBar(BuildContext context, String username) { return CustomAppBar( height: 54.v, leadingWidth: 28.h, diff --git a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart index 0f6e122f..2e2201ff 100644 --- a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart +++ b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart @@ -90,7 +90,7 @@ class AdditionalInformationScreen extends StatelessWidget { } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 31.h, leading: AppbarLeadingImage( diff --git a/lib/presentation/registration/allergies_screen/allergies_screen.dart b/lib/presentation/registration/allergies_screen/allergies_screen.dart index ee78724c..358b6aec 100644 --- a/lib/presentation/registration/allergies_screen/allergies_screen.dart +++ b/lib/presentation/registration/allergies_screen/allergies_screen.dart @@ -98,7 +98,7 @@ class _AllergiesScreenState extends State { } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 31.h, leading: AppbarLeadingImage( diff --git a/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart b/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart index 47c83a35..ab76f1cc 100644 --- a/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart +++ b/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart @@ -43,24 +43,30 @@ class _BloodPressureScreenState extends State { padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 9.v), child: Column(children: [ SizedBox(height: 7.v), - Padding( - padding: EdgeInsets.symmetric(horizontal: 4.h), - child: Container( - height: 16.v, - width: 343.h, - decoration: BoxDecoration( - color: theme.colorScheme.onPrimary, - borderRadius: BorderRadius.circular(8.h), - border: Border.all( - color: theme.colorScheme.primary, - width: 1.h)), - child: ClipRRect( - borderRadius: BorderRadius.circular(8.h), - child: LinearProgressIndicator( - value: 0.62, - backgroundColor: theme.colorScheme.onPrimary, - valueColor: AlwaysStoppedAnimation( - appTheme.blueA400))))), + Container( + height: 16.v, + width: 343.h, + padding: EdgeInsets.symmetric( + horizontal: + 4.h), // Apply padding directly to the Container + decoration: BoxDecoration( + color: theme.colorScheme.onPrimary, + borderRadius: BorderRadius.circular(8.h), + border: Border.all( + color: theme.colorScheme.primary, + width: 1.h, + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(8.h), + child: LinearProgressIndicator( + value: 0.62, + backgroundColor: theme.colorScheme.onPrimary, + valueColor: + AlwaysStoppedAnimation(appTheme.blueA400), + ), + ), + ), SizedBox(height: 21.v), SizedBox( width: 224.h, @@ -234,7 +240,7 @@ class _BloodPressureScreenState extends State { } /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( diff --git a/lib/presentation/registration/body_circumferences_screen/body_circumferences_screen.dart b/lib/presentation/registration/body_circumferences_screen/body_circumferences_screen.dart index 77f48b43..17ce3dfb 100644 --- a/lib/presentation/registration/body_circumferences_screen/body_circumferences_screen.dart +++ b/lib/presentation/registration/body_circumferences_screen/body_circumferences_screen.dart @@ -105,68 +105,76 @@ class BodyCircumferencesScreen extends StatelessWidget { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - List errors = validateFields( - state.chestCircumferenceController!.text, - state.waistCircumferenceController!.text, - state.hipCircumferenceController!.text); - if (errors.isEmpty) { - UserRegistrationSheet sheet = state - .bodyCircumferencesModelObj! - .userRegistrationSheet; - sheet.chestCircumference = - state.chestCircumferenceController!.text; - sheet.waistCircumference = - state.waistCircumferenceController!.text; - sheet.hipCircumference = - state.hipCircumferenceController!.text; - Navigator.pushNamed( - context, - AppRoutes.weightScreen, - arguments: sheet, - ); - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - }); + onPressed: onTapContinue(state, context)); }), ])))); } + onTapContinue(BodyCircumferencesState state, BuildContext context) { + return () { + List errors = validateFields( + state.chestCircumferenceController!.text, + state.waistCircumferenceController!.text, + state.hipCircumferenceController!.text); + if (errors.isEmpty) { + UserRegistrationSheet sheet = + state.bodyCircumferencesModelObj!.userRegistrationSheet; + sheet.chestCircumference = state.chestCircumferenceController!.text; + sheet.waistCircumference = state.waistCircumferenceController!.text; + sheet.hipCircumference = state.hipCircumferenceController!.text; + Navigator.pushNamed( + context, + AppRoutes.weightScreen, + arguments: sheet, + ); + } else { + String errorMessage = ''; + + for (var error in errors) { + errorMessage += error + '\n\n'; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text(errorMessage), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + } + }; + } + + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); diff --git a/lib/presentation/registration/city_of_living_screen/city_of_living_screen.dart b/lib/presentation/registration/city_of_living_screen/city_of_living_screen.dart index 1e14a9c1..eac52021 100644 --- a/lib/presentation/registration/city_of_living_screen/city_of_living_screen.dart +++ b/lib/presentation/registration/city_of_living_screen/city_of_living_screen.dart @@ -71,11 +71,7 @@ class CityOfLivingScreen extends StatelessWidget { width: 12.adaptSize)), hintText: "Не выбрано".tr, items: cityOfLivingModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context - .read() - .add(ChangeDropDownEvent(value: value)); - }); + onChanged: onDropDownChange(context)); }), SizedBox(height: 22.v), Text("city".tr, style: theme.textTheme.bodyLarge), @@ -97,11 +93,7 @@ class CityOfLivingScreen extends StatelessWidget { hintText: "Не выбрано".tr, items: cityOfLivingModelObj?.dropdownItemList1 ?? [], - onChanged: (value) { - context - .read() - .add(ChangeDropDown1Event(value: value)); - }); + onChanged: onDropDownChangeCity(context)); }), Spacer(flex: 65), BlocBuilder( @@ -111,33 +103,53 @@ class CityOfLivingScreen extends StatelessWidget { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.cityOfLivingModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.bodyCircumferencesScreen, - arguments: sheet, - ); - }); + onPressed: onTapContinue(state, context)); }), ])))); } + onTapContinue(CityOfLivingState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.cityOfLivingModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.bodyCircumferencesScreen, + arguments: sheet, + ); + }; + } + + onDropDownChangeCity(BuildContext context) { + return (value) { + context.read().add(ChangeDropDown1Event(value: value)); + }; + } + + onDropDownChange(BuildContext context) { + return (value) { + context.read().add(ChangeDropDownEvent(value: value)); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); diff --git a/lib/presentation/registration/credentials_screen/credentials_screen.dart b/lib/presentation/registration/credentials_screen/credentials_screen.dart index 07607b4f..48979999 100644 --- a/lib/presentation/registration/credentials_screen/credentials_screen.dart +++ b/lib/presentation/registration/credentials_screen/credentials_screen.dart @@ -107,55 +107,62 @@ class CredentialsScreen extends StatelessWidget { margin: EdgeInsets.only(left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - List errors = validateFields( - state.emailController!.text, - state.nameController!.text, - state.passwordController!.text, - state.passwordConfirmationController!.text); - if (errors.isEmpty) { - UserRegistrationSheet sheet = - state.credentialsModelObj!.userRegistrationSheet; - sheet.email = state.emailController!.text; - sheet.name = state.nameController!.text; - sheet.password = state.passwordController!.text; - sheet.passwordConfirmation = - state.passwordConfirmationController!.text; - Navigator.pushNamed( - context, - AppRoutes.nameScreen, - arguments: sheet, - ); - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - }); + onPressed: onTapContinue(state, context)); }), ]))); } + onTapContinue(CredentialsState state, BuildContext context) { + return () { + List errors = validateFields( + state.emailController!.text, + state.nameController!.text, + state.passwordController!.text, + state.passwordConfirmationController!.text); + if (errors.isEmpty) { + UserRegistrationSheet sheet = + state.credentialsModelObj!.userRegistrationSheet; + sheet.email = state.emailController!.text; + sheet.name = state.nameController!.text; + sheet.password = state.passwordController!.text; + sheet.passwordConfirmation = state.passwordConfirmationController!.text; + Navigator.pushNamed( + context, + AppRoutes.nameScreen, + arguments: sheet, + ); + } else { + String errorMessage = ''; + + for (var error in errors) { + errorMessage += error + '\n\n'; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text(errorMessage), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + } + }; + } + + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, centerTitle: true, diff --git a/lib/presentation/registration/date_of_birth_screen/date_of_birth_screen.dart b/lib/presentation/registration/date_of_birth_screen/date_of_birth_screen.dart index 49ef2848..df859872 100644 --- a/lib/presentation/registration/date_of_birth_screen/date_of_birth_screen.dart +++ b/lib/presentation/registration/date_of_birth_screen/date_of_birth_screen.dart @@ -69,37 +69,45 @@ class _DateOfBirthScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = state - .dateOfBirthModelObj!.userRegistrationSheet; - sheet.birthdate = selectedDate.toString(); - Navigator.pushNamed( - context, - AppRoutes.cityOfLivingScreen, - arguments: sheet, - ); - }); + onPressed: onTapContinue(state, context)); }), ])))); }); } + onTapContinue(DateOfBirthState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.dateOfBirthModelObj!.userRegistrationSheet; + sheet.birthdate = selectedDate.toString(); + Navigator.pushNamed( + context, + AppRoutes.cityOfLivingScreen, + arguments: sheet, + ); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 29.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildDateInput(BuildContext context) { + _buildDateInput(BuildContext context) { return Container( width: 343.h, padding: EdgeInsets.symmetric(horizontal: 4.h, vertical: 1.v), @@ -119,9 +127,7 @@ class _DateOfBirthScreenState extends State { Align( alignment: Alignment.center, child: GestureDetector( - onTap: () { - openDatePickerDialog(context); - }, + onTap: onTapCalendar(context), child: Text( '${selectedDate.day}.${selectedDate.month}.${selectedDate.year}', style: theme.textTheme.titleMedium))), @@ -129,6 +135,12 @@ class _DateOfBirthScreenState extends State { ])); } + onTapCalendar(BuildContext context) { + return () { + openDatePickerDialog(context); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); @@ -139,15 +151,21 @@ class _DateOfBirthScreenState extends State { /// This function returns a `Future` that completes with `void`. Future openDatePickerDialog(BuildContext context) async { DateTime? dateTime = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1924), - lastDate: DateTime( - DateTime.now().year, DateTime.now().month, DateTime.now().day)); + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1924), + lastDate: DateTime( + DateTime.now().year, + DateTime.now().month, + DateTime.now().day, + ), + ); if (dateTime != null) { - setState(() { - selectedDate = dateTime; - }); + if (mounted) { + setState(() { + selectedDate = dateTime; + }); + } } } } diff --git a/lib/presentation/registration/favorite_foods_screen/favorite_foods_screen.dart b/lib/presentation/registration/favorite_foods_screen/favorite_foods_screen.dart index 1e189d19..4dc1ce60 100644 --- a/lib/presentation/registration/favorite_foods_screen/favorite_foods_screen.dart +++ b/lib/presentation/registration/favorite_foods_screen/favorite_foods_screen.dart @@ -76,54 +76,64 @@ class _FavoriteFoodsScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 40.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = state - .favoriteFoodsModelObj!.userRegistrationSheet; - sheet.favoriteFoods = - state.favoriteFoodsController!.text; - sheet.unfavoriteFoods = - state.unfavoriteFoodsController!.text; - Navigator.pushNamed( - context, - AppRoutes.additionalInformationScreen, - arguments: sheet, - ); - }); + onPressed: onTapContinue(state, context)); }), BlocBuilder( builder: (context, state) { return GestureDetector( - onTap: () { - UserRegistrationSheet sheet = - state.favoriteFoodsModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.additionalInformationScreen, - arguments: sheet, - ); - }, + onTap: onTapSkip(state, context), child: Text("skip".tr, style: theme.textTheme.bodyLarge), ); }), ])))); } + onTapSkip(FavoriteFoodsState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.favoriteFoodsModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.additionalInformationScreen, + arguments: sheet, + ); + }; + } + + onTapContinue(FavoriteFoodsState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.favoriteFoodsModelObj!.userRegistrationSheet; + sheet.favoriteFoods = state.favoriteFoodsController!.text; + sheet.unfavoriteFoods = state.unfavoriteFoodsController!.text; + Navigator.pushNamed( + context, + AppRoutes.additionalInformationScreen, + arguments: sheet, + ); + }; + } + /// Section Widget - PreferredSizeWidget _buildAppBar(BuildContext context) { + _buildAppBar(BuildContext context) { return CustomAppBar( leadingWidth: 31.h, leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildTextFormFieldFav(BuildContext context) { + _buildTextFormFieldFav(BuildContext context) { return Column(children: [ Text("favorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI), SizedBox(height: 2.v), @@ -140,7 +150,7 @@ class _FavoriteFoodsScreenState extends State { } /// Section Widget - Widget _buildTextFormFieldUnfav(BuildContext context) { + _buildTextFormFieldUnfav(BuildContext context) { return Column(children: [ Text("unfavorite_foods".tr, style: CustomTextStyles.titleMediumSegoeUI), SizedBox(height: 2.v), From 3cf61ce5cae6ed14294df75c230aa7b84c6b3a59 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 17:22:14 +0300 Subject: [PATCH 31/39] refactor(diary): Some more refactoring --- .../blood_pressure_screen.dart | 142 ++++++++++-------- 1 file changed, 81 insertions(+), 61 deletions(-) diff --git a/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart b/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart index ab76f1cc..f0c26a10 100644 --- a/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart +++ b/lib/presentation/registration/blood_pressure_screen/blood_pressure_screen.dart @@ -136,11 +136,7 @@ class _BloodPressureScreenState extends State { items: bloodPressureModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context - .read() - .add(ChangeHypoDownEvent(value: value)); - }); + onChanged: onChangeHyper(context)); })), SizedBox(height: 22.v), Text("do_you_have_hypertension_tendency".tr, @@ -167,10 +163,7 @@ class _BloodPressureScreenState extends State { items: bloodPressureModelObj?.dropdownItemList ?? [], - onChanged: (value) { - context.read().add( - ChangeHyperDropDownEvent(value: value)); - }); + onChanged: onChangeHypo(context)); })), Spacer(), BlocBuilder( @@ -180,65 +173,88 @@ class _BloodPressureScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - List errors = validateFields( - state.upPressureController!.text, - state.downPressureController!.text); - if (errors.isEmpty) { - UserRegistrationSheet sheet = state - .bloodPressureModelObj!.userRegistrationSheet; - sheet.bloodPressureUp = - state.upPressureController!.text; - sheet.bloodPressureDown = - state.downPressureController!.text; - Navigator.pushNamed( - context, - AppRoutes.favoriteSportsScreen, - arguments: sheet, - ); - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - } - }); + onPressed: onTapContinue(state, context)); }), BlocBuilder( builder: (context, state) { return GestureDetector( - onTap: () { - UserRegistrationSheet sheet = - state.bloodPressureModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.allergiesScreen, - arguments: sheet, - ); - }, + onTap: onTapSkip(state, context), child: Text("skip".tr, style: theme.textTheme.bodyLarge), ); }), ])))); } + onTapSkip(BloodPressureState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.bloodPressureModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.allergiesScreen, + arguments: sheet, + ); + }; + } + + onTapContinue(BloodPressureState state, BuildContext context) { + return () { + List errors = validateFields( + state.upPressureController!.text, state.downPressureController!.text); + if (errors.isEmpty) { + UserRegistrationSheet sheet = + state.bloodPressureModelObj!.userRegistrationSheet; + sheet.bloodPressureUp = state.upPressureController!.text; + sheet.bloodPressureDown = state.downPressureController!.text; + Navigator.pushNamed( + context, + AppRoutes.favoriteSportsScreen, + arguments: sheet, + ); + } else { + String errorMessage = ''; + + for (var error in errors) { + errorMessage += error + '\n\n'; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text(errorMessage), + actions: [ + TextButton( + onPressed: onTapOK(context), + child: Text('OK'), + ), + ], + ), + ); + } + }; + } + + onTapOK(BuildContext context) { + return () { + Navigator.pop(context); + }; + } + + onChangeHypo(BuildContext context) { + return (value) { + context + .read() + .add(ChangeHyperDropDownEvent(value: value)); + }; + } + + onChangeHyper(BuildContext context) { + return (value) { + context.read().add(ChangeHypoDownEvent(value: value)); + }; + } + /// Section Widget _buildAppBar(BuildContext context) { return CustomAppBar( @@ -246,13 +262,17 @@ class _BloodPressureScreenState extends State { leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Navigates to the previous screen. onTapArrowLeft(BuildContext context) { NavigatorService.goBack(); From 3019a5a26407fa303df4ee31c63b81db287d7d17 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Tue, 5 Mar 2024 17:35:48 +0300 Subject: [PATCH 32/39] refactor(diary): Even more refactoring --- .../additional_information_screen.dart | 65 +++++++++++-------- .../allergies_screen/allergies_screen.dart | 59 ++++++++++------- .../app_navigation_screen.dart | 8 +-- 3 files changed, 75 insertions(+), 57 deletions(-) diff --git a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart index 2e2201ff..345af298 100644 --- a/lib/presentation/registration/additional_information_screen/additional_information_screen.dart +++ b/lib/presentation/registration/additional_information_screen/additional_information_screen.dart @@ -66,29 +66,32 @@ class AdditionalInformationScreen extends StatelessWidget { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () async { - UserRegistrationSheet sheet = state - .additionalInformationModelObj! - .userRegistrationSheet; - sheet.additionalInfo = state.editTextController!.text; - final response = await http.post( - Uri.parse(dotenv.env['SERVER_ROOT']! + '/register'), - headers: {'Content-Type': 'application/json'}, - body: json.encode(sheet), - ); - var res = await jsonDecode(response.body); - final box = await Hive.openBox('token'); - final token = res['token']; - box.put('token', token); - Navigator.pushNamed( - context, - AppRoutes.myProfile, - ); - }); + onPressed: onTapFinish(state, context)); }), ])))); } + onTapFinish(AdditionalInformationState state, BuildContext context) { + return () async { + UserRegistrationSheet sheet = + state.additionalInformationModelObj!.userRegistrationSheet; + sheet.additionalInfo = state.editTextController!.text; + final response = await http.post( + Uri.parse(dotenv.env['SERVER_ROOT']! + '/register'), + headers: {'Content-Type': 'application/json'}, + body: json.encode(sheet), + ); + var res = await jsonDecode(response.body); + final box = await Hive.openBox('token'); + final token = res['token']; + box.put('token', token); + Navigator.pushNamed( + context, + AppRoutes.myProfile, + ); + }; + } + /// Section Widget _buildAppBar(BuildContext context) { return CustomAppBar( @@ -96,15 +99,19 @@ class AdditionalInformationScreen extends StatelessWidget { leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildTextFormField(BuildContext context) { + _buildTextFormField(BuildContext context) { return SizedBox( height: 257.v, width: 343.h, @@ -147,12 +154,14 @@ class AdditionalInformationScreen extends StatelessWidget { title: const Text('Регистрация завершена!'), content: const Text('1'), actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Ok')) + TextButton(onPressed: onTapOk(context), child: const Text('Ok')) ], )); } + + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } } diff --git a/lib/presentation/registration/allergies_screen/allergies_screen.dart b/lib/presentation/registration/allergies_screen/allergies_screen.dart index 358b6aec..9f4c6b03 100644 --- a/lib/presentation/registration/allergies_screen/allergies_screen.dart +++ b/lib/presentation/registration/allergies_screen/allergies_screen.dart @@ -67,36 +67,43 @@ class _AllergiesScreenState extends State { margin: EdgeInsets.only( left: 16.h, right: 16.h, bottom: 50.v), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - UserRegistrationSheet sheet = - state.allergiesModelObj!.userRegistrationSheet; - sheet.aboutAllergy = - state.enterInformationController!.text; - Navigator.pushNamed( - context, - AppRoutes.medicineIntakeScreen, - arguments: sheet, - ); - }); + onPressed: onTapContinue(state, context)); }), BlocBuilder( builder: (context, state) { return GestureDetector( - onTap: () { - UserRegistrationSheet sheet = - state.allergiesModelObj!.userRegistrationSheet; - Navigator.pushNamed( - context, - AppRoutes.medicineIntakeScreen, - arguments: sheet, - ); - }, + onTap: onTapSkip(state, context), child: Text("skip".tr, style: theme.textTheme.bodyLarge), ); }), ])))); } + onTapSkip(AllergiesState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.allergiesModelObj!.userRegistrationSheet; + Navigator.pushNamed( + context, + AppRoutes.medicineIntakeScreen, + arguments: sheet, + ); + }; + } + + onTapContinue(AllergiesState state, BuildContext context) { + return () { + UserRegistrationSheet sheet = + state.allergiesModelObj!.userRegistrationSheet; + sheet.aboutAllergy = state.enterInformationController!.text; + Navigator.pushNamed( + context, + AppRoutes.medicineIntakeScreen, + arguments: sheet, + ); + }; + } + /// Section Widget _buildAppBar(BuildContext context) { return CustomAppBar( @@ -104,15 +111,19 @@ class _AllergiesScreenState extends State { leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 18.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), centerTitle: true, title: AppbarTitleImage(imagePath: ImageConstant.imgLogoEatvio)); } + onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + /// Section Widget - Widget _buildTextFormField(BuildContext context) { + _buildTextFormField(BuildContext context) { return Column(children: [ Text("fill_in_information".tr, style: CustomTextStyles.titleMediumSegoeUI), diff --git a/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart b/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart index 5dd89c25..ec34e364 100644 --- a/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart +++ b/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart @@ -151,7 +151,7 @@ class _AppNavigationScreenState extends State { } /// Section Widget - Widget _buildAppNavigation(BuildContext context) { + _buildAppNavigation(BuildContext context) { return Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), @@ -205,15 +205,13 @@ class _AppNavigationScreenState extends State { } /// Common widget - Widget _buildScreenTitle( + _buildScreenTitle( BuildContext context, { required String screenTitle, Function? onTapScreenTitle, }) { return GestureDetector( - onTap: () { - onTapScreenTitle!.call(); - }, + onTap: onTapScreenTitle!.call(), child: Container( decoration: BoxDecoration( color: Color(0XFFFFFFFF), From 00b1452cefdc378363b8fe7ceb5010cf3d38222e Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 11:44:20 +0300 Subject: [PATCH 33/39] refactor(diary): Refactoring for settings done --- .../my_profile_screen/my_settings_screen.dart | 619 +----------------- lib/widgets/custom_about_list.dart | 56 ++ lib/widgets/custom_expandable_list.dart | 360 ++++++++++ lib/widgets/custom_hyper_switch.dart | 55 ++ lib/widgets/custom_hypo_switch.dart | 55 ++ lib/widgets/custom_language_drop_down.dart | 48 ++ lib/widgets/custom_notification_screen.dart | 45 ++ lib/widgets/custom_section_title.dart | 19 + 8 files changed, 664 insertions(+), 593 deletions(-) create mode 100644 lib/widgets/custom_about_list.dart create mode 100644 lib/widgets/custom_expandable_list.dart create mode 100644 lib/widgets/custom_hyper_switch.dart create mode 100644 lib/widgets/custom_hypo_switch.dart create mode 100644 lib/widgets/custom_language_drop_down.dart create mode 100644 lib/widgets/custom_notification_screen.dart create mode 100644 lib/widgets/custom_section_title.dart diff --git a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart index 2927282e..a95b0434 100644 --- a/lib/presentation/profile/my_profile_screen/my_settings_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_settings_screen.dart @@ -5,14 +5,12 @@ import 'package:eatvio_app/widgets/app_bar/appbar_subtitle.dart'; import 'package:eatvio_app/widgets/app_bar/appbar_leading_image.dart'; import 'package:eatvio_app/widgets/app_bar/custom_app_bar.dart'; import 'package:eatvio_app/widgets/custom_bottom_bar.dart'; -import 'package:intl/intl.dart'; -import 'package:eatvio_app/widgets/next_step_button.dart'; +import 'package:eatvio_app/widgets/custom_about_list.dart'; +import 'package:eatvio_app/widgets/custom_expandable_list.dart'; +import 'package:eatvio_app/widgets/custom_notification_screen.dart'; +import 'package:eatvio_app/widgets/custom_section_title.dart'; +import 'package:eatvio_app/widgets/custom_language_drop_down.dart'; import 'package:flutter/material.dart'; -import 'dart:convert'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:hive/hive.dart'; -import 'package:flutter/services.dart'; -import 'package:http/http.dart' as http; class MySettingsScreen extends StatelessWidget { static Widget builder(BuildContext context) { @@ -43,27 +41,25 @@ class MySettingsScreen extends StatelessWidget { ); } - Widget _buildSetingsScreen(BuildContext context, MyProfileLoadedState state) { + _buildSetingsScreen(BuildContext context, MyProfileLoadedState state) { mediaQueryData = MediaQuery.of(context); - return SafeArea( + SafeArea( child: Scaffold( appBar: _buildAppBar(context, "my_settings".tr), body: Padding( padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - child: Column( - children: [ - SectionTitle('Язык'), - LanguageDropdown(), - SectionTitle('Уведомления'), - NotificationSwitch('Уведомление об обновлениях'), - NotificationSwitch('Напоминания о заполнении'), - SectionTitle('Дополнительная информация'), - ExpandableList('Персональные данные'), - AboutList('О нас', ['ООО Итвио', '2023-н.в.']), - ], - ), + child: ListView( + children: [ + SectionTitle('Язык'), + LanguageDropdown(), + SectionTitle('Уведомления'), + NotificationSwitch('Уведомление об обновлениях'), + NotificationSwitch('Напоминания о заполнении'), + SectionTitle('Дополнительная информация'), + ExpandableList('Персональные данные'), + AboutList('О нас', ['ООО Итвио', '2023-н.в.']), + ], ), ), bottomNavigationBar: _buildBottomBar(context))); @@ -77,9 +73,7 @@ class MySettingsScreen extends StatelessWidget { leading: AppbarLeadingImage( imagePath: ImageConstant.imgArrowLeft, margin: EdgeInsets.only(left: 16.h, top: 15.v, bottom: 15.v), - onTap: () { - onTapArrowLeft(context); - }), + onTap: onTapBack(context)), title: Padding( padding: EdgeInsets.only(left: 20.h), child: Row(children: [ @@ -90,7 +84,13 @@ class MySettingsScreen extends StatelessWidget { ); } - Widget _buildBottomBar(BuildContext context) { + Function onTapBack(BuildContext context) { + return () { + onTapArrowLeft(context); + }; + } + + _buildBottomBar(BuildContext context) { return CustomBottomBar(onChanged: (BottomBarEnum type) {}); } @@ -98,570 +98,3 @@ class MySettingsScreen extends StatelessWidget { NavigatorService.goBack(); } } - -class SectionTitle extends StatelessWidget { - final String title; - - SectionTitle(this.title); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - title, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18), - ), - ); - } -} - -class LanguageDropdown extends StatefulWidget { - @override - _LanguageDropdownState createState() => _LanguageDropdownState(); -} - -class _LanguageDropdownState extends State { - String selectedLanguage = 'Русский'; - - @override - Widget build(BuildContext context) { - return DropdownButton( - value: selectedLanguage, - onChanged: (newValue) { - setState(() { - selectedLanguage = newValue!; - }); - }, - isDense: false, // Установите isDense в false - selectedItemBuilder: (BuildContext context) { - return ['Русский'].map((String language) { - return Align( - alignment: Alignment.center, // Выравнивание текста по центру - child: Text( - language, - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - ); - }).toList(); - }, - items: ['Русский'].map((String language) { - return DropdownMenuItem( - value: language, - child: Text(language), - ); - }).toList(), - ); - } -} - -class NotificationSwitch extends StatefulWidget { - final String title; - - NotificationSwitch(this.title); - - @override - _NotificationSwitchState createState() => _NotificationSwitchState(); -} - -class _NotificationSwitchState extends State { - bool switchValue = false; - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.title, - style: TextStyle( - color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), - ), - Switch( - value: switchValue, - onChanged: (value) { - setState(() { - switchValue = value; - }); - }, - inactiveThumbColor: appTheme.blueA400, - inactiveTrackColor: Colors.white, - activeTrackColor: appTheme.blueA400, - activeColor: Colors.white, - ), - ], - ); - } -} - -class HyperSwitch extends StatefulWidget { - final String title; - final MyProfileLoadedState? state; - HyperSwitch(this.title, this.state); - - @override - _HyperState createState() => _HyperState(); -} - -class _HyperState extends State { - bool switchValue = false; - - @override - void initState() { - super.initState(); - if (widget.state?.hyperFormController == '1') { - switchValue = true; - } - } - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.title, - style: TextStyle( - color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), - ), - Switch( - value: switchValue, - onChanged: (value) { - setState(() { - switchValue = value; - widget.state!.hyperFormController = value ? "1" : "0"; - }); - }, - inactiveThumbColor: appTheme.blueA400, - inactiveTrackColor: Colors.white, - activeTrackColor: appTheme.blueA400, - activeColor: Colors.white, - ), - ], - ); - } -} - -class HypoSwitch extends StatefulWidget { - final String title; - final MyProfileLoadedState? state; - HypoSwitch(this.title, this.state); - - @override - _HypoState createState() => _HypoState(); -} - -class _HypoState extends State { - bool switchValue = false; - - @override - void initState() { - super.initState(); - if (widget.state?.hypoFormController == '1') { - switchValue = true; - } - } - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.title, - style: TextStyle( - color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), - ), - Switch( - value: switchValue, - onChanged: (value) { - setState(() { - switchValue = value; - widget.state!.hypoFormController = value ? "1" : "0"; - }); - }, - inactiveThumbColor: appTheme.blueA400, - inactiveTrackColor: Colors.white, - activeTrackColor: appTheme.blueA400, - activeColor: Colors.white, - ), - ], - ); - } -} - -class ExpandableList extends StatefulWidget { - final String title; - - ExpandableList(this.title); - - @override - _ExpandableListState createState() => _ExpandableListState(); -} - -class _ExpandableListState extends State { - bool isExpanded = false; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - GestureDetector( - onTap: () { - setState(() { - isExpanded = !isExpanded; - }); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.title, - style: TextStyle( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.bold), - ), - Icon(isExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), - ], - ), - ), - if (isExpanded) - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: BlocBuilder( - builder: (context, state) { - if (state is MyProfileInitialState) { - // Это начальное состояние, данные ещё не загружены. - return CircularProgressIndicator( - color: Colors.white, - backgroundColor: Colors.white, - ); - } else if (state is MyProfileLoadedState) { - // Данные загружены, можно строить форму. - return _buildForm(context, state); - } else if (state is MyProfileErrorState) { - // Произошла ошибка при загрузке данных. - return Center(child: Text(state.errorMessage)); - } else { - // Другие состояния, если они есть. - return Container(); // Пустой контейнер для необработанных состояний. - } - }), - ), - Divider(), - ], - ); - } - - Widget _buildForm(BuildContext context, MyProfileLoadedState state) { - List cities = [ - 'Москва', - 'Санкт-Петербург', - 'Новосибирск', - 'Екатеринбург', - 'Нижний Новгород', - 'Казань', - 'Челябинск', - 'Омск', - 'Самара', - 'Ростов-на-Дону', - 'Уфа', - 'Красноярск', - 'Воронеж', - 'Пермь', - 'Волгоград', - 'Краснодар', - 'Саратов', - 'Тюмень', - 'Тольятти', - 'Ижевск', - 'Барнаул', - 'Ульяновск', - 'Иркутск', - 'Хабаровск', - 'Ярославль', - 'Владивосток', - 'Махачкала', - 'Томск', - 'Оренбург', - 'Кемерово', - ]; - List countries = [ - 'Россия', - ]; - final digitsOnly = FilteringTextInputFormatter.digitsOnly; - return Column(children: [ - TextField( - controller: state.firstNameFormController, - decoration: InputDecoration(labelText: 'first_name'.tr), - ), - TextField( - controller: state.lastNameFormController, - decoration: InputDecoration(labelText: 'last_name'.tr), - ), - TextField( - decoration: InputDecoration(labelText: 'date_of_birth'.tr), - controller: state.dateFormController, - onTap: () { - showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(1900), - lastDate: DateTime.now(), - ).then((selectedDate) { - if (selectedDate != null) { - setState(() { - state.dateFormController!.text = - DateFormat('dd-MM-yyyy').format(selectedDate); - }); - } - }); - }), - DropdownButtonFormField( - value: state.selectedCountry, - hint: Text(state.selectedCountry ?? "Не выбрано"), - onChanged: (newValue) { - // Обработчик изменения выбранной страны - setSelectedCountry(state, newValue); - }, - items: countries.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - decoration: InputDecoration(labelText: 'country'.tr), - ), - DropdownButtonFormField( - hint: Text(state.selectedCity ?? "Не выбрано"), - value: state.selectedCity, - onChanged: (newValue) { - // Обработчик изменения выбранного города - setSelectedCity(state, newValue); - }, - items: cities.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - decoration: InputDecoration(labelText: 'city_of_living'.tr), - ), - TextField( - controller: state.weightFormController, - decoration: InputDecoration(labelText: 'weight_measurements'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.heightFormController, - decoration: InputDecoration(labelText: 'height_measurements'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.chestCircumferenceFormController, - decoration: InputDecoration(labelText: 'chest_circumference'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.waistCircumferenceFormController, - decoration: InputDecoration(labelText: 'waist_circumference'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.hipCircumferenceFormController, - decoration: InputDecoration(labelText: 'hip_circumference'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.upPressureFormController, - decoration: InputDecoration(labelText: 'up_pressure'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.downPressureFormController, - decoration: InputDecoration(labelText: 'down_pressure'.tr), - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly]), - TextField( - controller: state.allergiesFormController, - decoration: InputDecoration(labelText: 'allergies_presence'.tr), - maxLines: null, - ), - TextField( - controller: state.pillsFormController, - decoration: InputDecoration(labelText: 'do_you_take_pills'.tr), - maxLines: null, - ), - TextField( - controller: state.sportsFormController, - decoration: InputDecoration(labelText: 'your_favorite_sports'.tr), - maxLines: null, - ), - TextField( - controller: state.favoriteFormController, - decoration: InputDecoration(labelText: 'favorite_foods'.tr), - maxLines: null, - ), - TextField( - controller: state.unfavoriteFormController, - decoration: InputDecoration(labelText: 'unfavorite_foods'.tr), - maxLines: null, - ), - TextField( - controller: state.additionalFormController, - decoration: InputDecoration(labelText: 'additional_information'.tr), - maxLines: null, - ), - Row( - children: [ - HypoSwitch('do_you_have_hypotension_tendency'.tr, state), - ], - ), - Row( - children: [ - HyperSwitch('do_you_have_hypertension_tendency'.tr, state), - ], - ), - NextStepButton( - onPressed: () { - sendProfileData(state); - }, - buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - text: "save".tr.toUpperCase(), - margin: EdgeInsets.only(top: 20.h, bottom: 20.h)), - ]); - } - - void setSelectedCity(MyProfileLoadedState? state, String? newValue) { - setState(() { - state!.selectedCity = newValue; - }); - } - - void setSelectedCountry(MyProfileLoadedState? state, String? newValue) { - setState(() { - state!.selectedCountry = newValue; - }); - } - - Future sendProfileData(MyProfileLoadedState? state) async { - try { - // Создаем JSON объект с данными профиля - Map profileData = { - 'first_name': state?.firstNameFormController?.text, - 'last_name': state?.lastNameFormController?.text, - 'chest_circumference': state?.chestCircumferenceFormController?.text, - 'waist_circumference': state?.waistCircumferenceFormController?.text, - 'hip_circumference': state?.hipCircumferenceFormController?.text, - 'birthdate': state?.dateFormController?.text, - 'height': state?.heightFormController?.text, - 'weight': state?.weightFormController?.text, - 'blood_pressure_up': state?.upPressureFormController?.text, - 'blood_pressure_down': state?.downPressureFormController?.text, - 'about_alergy': state?.allergiesFormController?.text, - 'about_taking_pils': state?.pillsFormController?.text, - 'about_sport_hobbies': state?.sportsFormController?.text, - 'favorite_foods': state?.favoriteFormController?.text, - 'unfavorite_foods': state?.unfavoriteFormController?.text, - 'additional_info': state?.additionalFormController?.text, - 'country': state?.selectedCountry ?? 'Россия', - 'city': state?.selectedCity ?? 'Москва', - 'has_hypo': state?.hypoFormController, - 'has_hyper': state?.hyperFormController, - }; - final box = await Hive.openBox('token'); - final token = box.get('token'); - String apiUrl = dotenv.env['SERVER_ROOT']! + '/profile/update'; - http.Response response = await http.post( - Uri.parse(apiUrl), - body: json.encode(profileData), - encoding: utf8, - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }, - ); - - print(response.body); - if (response.statusCode == 200) { - Navigator.pushNamed( - context, - AppRoutes.myProfile, - ); - } else { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text('Ошибка при отправке данных профиля'.tr), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('OK'), - ), - ], - ), - ); - throw Exception('Ошибка при отправке данных профиля'); - } - } catch (error) { - throw Exception('Ошибка при отправке данных профиля: $error'); - } - } -} - -class AboutList extends StatefulWidget { - final String title; - final List items; - - AboutList(this.title, this.items); - - @override - _AboutListState createState() => _AboutListState(); -} - -class _AboutListState extends State { - bool isExpanded = false; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - GestureDetector( - onTap: () { - setState(() { - isExpanded = !isExpanded; - }); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.title, - style: TextStyle( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.bold), - ), - Icon(isExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), - ], - ), - ), - if (isExpanded) - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Column( - //children: widget.items.map((item) => Text(item)).toList(), - children: [Text(widget.items.join('\n'))]), - ), - Divider(), - ], - ); - } -} diff --git a/lib/widgets/custom_about_list.dart b/lib/widgets/custom_about_list.dart new file mode 100644 index 00000000..f4b91b2c --- /dev/null +++ b/lib/widgets/custom_about_list.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class AboutList extends StatefulWidget { + final String title; + final List items; + + AboutList(this.title, this.items); + + @override + _AboutListState createState() => _AboutListState(); +} + +class _AboutListState extends State { + bool isExpanded = false; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + GestureDetector( + onTap: toggleList(), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.bold), + ), + Icon(isExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), + ], + ), + ), + if (isExpanded) + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Column( + //children: widget.items.map((item) => Text(item)).toList(), + children: [Text(widget.items.join('\n'))]), + ), + Divider(), + ], + ); + } + + toggleList() { + return () { + setState(() { + isExpanded = !isExpanded; + }); + }; + } +} diff --git a/lib/widgets/custom_expandable_list.dart b/lib/widgets/custom_expandable_list.dart new file mode 100644 index 00000000..db4cdab0 --- /dev/null +++ b/lib/widgets/custom_expandable_list.dart @@ -0,0 +1,360 @@ +import 'package:flutter/material.dart'; +import 'package:eatvio_app/core/app_export.dart'; +import 'package:eatvio_app/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart'; +import 'package:eatvio_app/widgets/custom_hyper_switch.dart'; +import 'package:eatvio_app/widgets/custom_hypo_switch.dart'; +import 'package:intl/intl.dart'; +import 'package:eatvio_app/widgets/next_step_button.dart'; +import 'dart:convert'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:hive/hive.dart'; +import 'package:flutter/services.dart'; +import 'package:http/http.dart' as http; + +class ExpandableList extends StatefulWidget { + final String title; + + ExpandableList(this.title); + + @override + _ExpandableListState createState() => _ExpandableListState(); +} + +class _ExpandableListState extends State { + bool isExpanded = false; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + GestureDetector( + onTap: toggleExpand(), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.bold), + ), + Icon(isExpanded ? Icons.arrow_drop_up : Icons.arrow_drop_down), + ], + ), + ), + if (isExpanded) + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: BlocBuilder( + builder: (context, state) { + if (state is MyProfileInitialState) { + // Это начальное состояние, данные ещё не загружены. + return CircularProgressIndicator( + color: Colors.white, + backgroundColor: Colors.white, + ); + } else if (state is MyProfileLoadedState) { + // Данные загружены, можно строить форму. + return _buildForm(context, state); + } else if (state is MyProfileErrorState) { + // Произошла ошибка при загрузке данных. + return Center(child: Text(state.errorMessage)); + } else { + // Другие состояния, если они есть. + return Container(); // Пустой контейнер для необработанных состояний. + } + }), + ), + Divider(), + ], + ); + } + + toggleExpand() { + return () { + setState(() { + isExpanded = !isExpanded; + }); + }; + } + + Widget _buildForm(BuildContext context, MyProfileLoadedState state) { + List cities = [ + 'Москва', + 'Санкт-Петербург', + 'Новосибирск', + 'Екатеринбург', + 'Нижний Новгород', + 'Казань', + 'Челябинск', + 'Омск', + 'Самара', + 'Ростов-на-Дону', + 'Уфа', + 'Красноярск', + 'Воронеж', + 'Пермь', + 'Волгоград', + 'Краснодар', + 'Саратов', + 'Тюмень', + 'Тольятти', + 'Ижевск', + 'Барнаул', + 'Ульяновск', + 'Иркутск', + 'Хабаровск', + 'Ярославль', + 'Владивосток', + 'Махачкала', + 'Томск', + 'Оренбург', + 'Кемерово', + ]; + List countries = [ + 'Россия', + ]; + final digitsOnly = FilteringTextInputFormatter.digitsOnly; + return Column(children: [ + TextField( + controller: state.firstNameFormController, + decoration: InputDecoration(labelText: 'first_name'.tr), + ), + TextField( + controller: state.lastNameFormController, + decoration: InputDecoration(labelText: 'last_name'.tr), + ), + TextField( + decoration: InputDecoration(labelText: 'date_of_birth'.tr), + controller: state.dateFormController, + onTap: inputTime(context, state)), + DropdownButtonFormField( + value: state.selectedCountry, + hint: Text(state.selectedCountry ?? "Не выбрано"), + onChanged: setCountry(state), + items: countries.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + decoration: InputDecoration(labelText: 'country'.tr), + ), + DropdownButtonFormField( + hint: Text(state.selectedCity ?? "Не выбрано"), + value: state.selectedCity, + onChanged: setCity(state), + items: cities.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + decoration: InputDecoration(labelText: 'city_of_living'.tr), + ), + TextField( + controller: state.weightFormController, + decoration: InputDecoration(labelText: 'weight_measurements'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.heightFormController, + decoration: InputDecoration(labelText: 'height_measurements'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.chestCircumferenceFormController, + decoration: InputDecoration(labelText: 'chest_circumference'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.waistCircumferenceFormController, + decoration: InputDecoration(labelText: 'waist_circumference'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.hipCircumferenceFormController, + decoration: InputDecoration(labelText: 'hip_circumference'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.upPressureFormController, + decoration: InputDecoration(labelText: 'up_pressure'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.downPressureFormController, + decoration: InputDecoration(labelText: 'down_pressure'.tr), + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly]), + TextField( + controller: state.allergiesFormController, + decoration: InputDecoration(labelText: 'allergies_presence'.tr), + maxLines: null, + ), + TextField( + controller: state.pillsFormController, + decoration: InputDecoration(labelText: 'do_you_take_pills'.tr), + maxLines: null, + ), + TextField( + controller: state.sportsFormController, + decoration: InputDecoration(labelText: 'your_favorite_sports'.tr), + maxLines: null, + ), + TextField( + controller: state.favoriteFormController, + decoration: InputDecoration(labelText: 'favorite_foods'.tr), + maxLines: null, + ), + TextField( + controller: state.unfavoriteFormController, + decoration: InputDecoration(labelText: 'unfavorite_foods'.tr), + maxLines: null, + ), + TextField( + controller: state.additionalFormController, + decoration: InputDecoration(labelText: 'additional_information'.tr), + maxLines: null, + ), + Row( + children: [ + HypoSwitch('do_you_have_hypotension_tendency'.tr, state), + ], + ), + Row( + children: [ + HyperSwitch('do_you_have_hypertension_tendency'.tr, state), + ], + ), + NextStepButton( + onPressed: sendData(state), + buttonStyle: CustomButtonStyles.outlinePrimaryTL15, + text: "save".tr.toUpperCase(), + margin: EdgeInsets.only(top: 20.h, bottom: 20.h)), + ]); + } + + sendData(MyProfileLoadedState state) { + return () { + sendProfileData(state); + }; + } + + setCity(MyProfileLoadedState state) { + return (newValue) { + // Обработчик изменения выбранного города + setSelectedCity(state, newValue); + }; + } + + setCountry(MyProfileLoadedState state) { + return (newValue) { + // Обработчик изменения выбранной страны + setSelectedCountry(state, newValue); + }; + } + + inputTime(BuildContext context, MyProfileLoadedState state) { + return () { + showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1900), + lastDate: DateTime.now(), + ).then((selectedDate) { + if (selectedDate != null) { + setState(() { + state.dateFormController!.text = + DateFormat('dd-MM-yyyy').format(selectedDate); + }); + } + }); + }; + } + + void setSelectedCity(MyProfileLoadedState? state, String? newValue) { + setState(() { + state!.selectedCity = newValue; + }); + } + + void setSelectedCountry(MyProfileLoadedState? state, String? newValue) { + setState(() { + state!.selectedCountry = newValue; + }); + } + + Future sendProfileData(MyProfileLoadedState? state) async { + try { + // Создаем JSON объект с данными профиля + Map profileData = { + 'first_name': state?.firstNameFormController?.text, + 'last_name': state?.lastNameFormController?.text, + 'chest_circumference': state?.chestCircumferenceFormController?.text, + 'waist_circumference': state?.waistCircumferenceFormController?.text, + 'hip_circumference': state?.hipCircumferenceFormController?.text, + 'birthdate': state?.dateFormController?.text, + 'height': state?.heightFormController?.text, + 'weight': state?.weightFormController?.text, + 'blood_pressure_up': state?.upPressureFormController?.text, + 'blood_pressure_down': state?.downPressureFormController?.text, + 'about_alergy': state?.allergiesFormController?.text, + 'about_taking_pils': state?.pillsFormController?.text, + 'about_sport_hobbies': state?.sportsFormController?.text, + 'favorite_foods': state?.favoriteFormController?.text, + 'unfavorite_foods': state?.unfavoriteFormController?.text, + 'additional_info': state?.additionalFormController?.text, + 'country': state?.selectedCountry ?? 'Россия', + 'city': state?.selectedCity ?? 'Москва', + 'has_hypo': state?.hypoFormController, + 'has_hyper': state?.hyperFormController, + }; + final box = await Hive.openBox('token'); + final token = box.get('token'); + String apiUrl = dotenv.env['SERVER_ROOT']! + '/profile/update'; + http.Response response = await http.post( + Uri.parse(apiUrl), + body: json.encode(profileData), + encoding: utf8, + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + ); + + print(response.body); + if (response.statusCode == 200) { + Navigator.pushNamed( + context, + AppRoutes.myProfile, + ); + } else { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Ошибка'), + content: Text('Ошибка при отправке данных профиля'.tr), + actions: [ + TextButton( + onPressed: onTapOk(context), + child: Text('OK'), + ), + ], + ), + ); + throw Exception('Ошибка при отправке данных профиля'); + } + } catch (error) { + throw Exception('Ошибка при отправке данных профиля: $error'); + } + } + + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } +} diff --git a/lib/widgets/custom_hyper_switch.dart b/lib/widgets/custom_hyper_switch.dart new file mode 100644 index 00000000..92ebf000 --- /dev/null +++ b/lib/widgets/custom_hyper_switch.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:eatvio_app/core/app_export.dart'; +import 'package:eatvio_app/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart'; + +class HyperSwitch extends StatefulWidget { + final String title; + final MyProfileLoadedState? state; + HyperSwitch(this.title, this.state); + + @override + _HyperState createState() => _HyperState(); +} + +class _HyperState extends State { + bool switchValue = false; + + @override + void initState() { + super.initState(); + if (widget.state?.hyperFormController == '1') { + switchValue = true; + } + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), + ), + Switch( + value: switchValue, + onChanged: toggleSwitch(), + inactiveThumbColor: appTheme.blueA400, + inactiveTrackColor: Colors.white, + activeTrackColor: appTheme.blueA400, + activeColor: Colors.white, + ), + ], + ); + } + + toggleSwitch() { + return (value) { + setState(() { + switchValue = value; + widget.state!.hyperFormController = value ? "1" : "0"; + }); + }; + } +} diff --git a/lib/widgets/custom_hypo_switch.dart b/lib/widgets/custom_hypo_switch.dart new file mode 100644 index 00000000..1c625feb --- /dev/null +++ b/lib/widgets/custom_hypo_switch.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:eatvio_app/core/app_export.dart'; +import 'package:eatvio_app/presentation/profile/my_profile_screen/bloc/my_profile_bloc.dart'; + +class HypoSwitch extends StatefulWidget { + final String title; + final MyProfileLoadedState? state; + HypoSwitch(this.title, this.state); + + @override + _HypoState createState() => _HypoState(); +} + +class _HypoState extends State { + bool switchValue = false; + + @override + void initState() { + super.initState(); + if (widget.state?.hypoFormController == '1') { + switchValue = true; + } + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), + ), + Switch( + value: switchValue, + onChanged: toggleSwitch(), + inactiveThumbColor: appTheme.blueA400, + inactiveTrackColor: Colors.white, + activeTrackColor: appTheme.blueA400, + activeColor: Colors.white, + ), + ], + ); + } + + toggleSwitch() { + return (value) { + setState(() { + switchValue = value; + widget.state!.hypoFormController = value ? "1" : "0"; + }); + }; + } +} diff --git a/lib/widgets/custom_language_drop_down.dart b/lib/widgets/custom_language_drop_down.dart new file mode 100644 index 00000000..7f0e3e0f --- /dev/null +++ b/lib/widgets/custom_language_drop_down.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +class LanguageDropdown extends StatefulWidget { + @override + _LanguageDropdownState createState() => _LanguageDropdownState(); +} + +class _LanguageDropdownState extends State { + String selectedLanguage = 'Русский'; + + @override + Widget build(BuildContext context) { + return DropdownButton( + value: selectedLanguage, + onChanged: selectLanguage(), + isDense: false, // Установите isDense в false + selectedItemBuilder: getList(), + items: ['Русский'].map((String language) { + return DropdownMenuItem( + value: language, + child: Text(language), + ); + }).toList(), + ); + } + + getList() { + return (BuildContext context) { + return ['Русский'].map((String language) { + return Align( + alignment: Alignment.center, // Выравнивание текста по центру + child: Text( + language, + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + ); + }).toList(); + }; + } + + selectLanguage() { + return (newValue) { + setState(() { + selectedLanguage = newValue!; + }); + }; + } +} diff --git a/lib/widgets/custom_notification_screen.dart b/lib/widgets/custom_notification_screen.dart new file mode 100644 index 00000000..bb778441 --- /dev/null +++ b/lib/widgets/custom_notification_screen.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:eatvio_app/core/app_export.dart'; + +class NotificationSwitch extends StatefulWidget { + final String title; + + NotificationSwitch(this.title); + + @override + _NotificationSwitchState createState() => _NotificationSwitchState(); +} + +class _NotificationSwitchState extends State { + bool switchValue = false; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.black, fontSize: 14, fontWeight: FontWeight.bold), + ), + Switch( + value: switchValue, + onChanged: toggleSwitch(), + inactiveThumbColor: appTheme.blueA400, + inactiveTrackColor: Colors.white, + activeTrackColor: appTheme.blueA400, + activeColor: Colors.white, + ), + ], + ); + } + + toggleSwitch() { + return (value) { + setState(() { + switchValue = value; + }); + }; + } +} diff --git a/lib/widgets/custom_section_title.dart b/lib/widgets/custom_section_title.dart new file mode 100644 index 00000000..282f3d6a --- /dev/null +++ b/lib/widgets/custom_section_title.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class SectionTitle extends StatelessWidget { + final String title; + + SectionTitle(this.title); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + title, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + ); + } +} From 47cf17c927eb980ec6748ca0285c0edaca280ba6 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 11:57:48 +0300 Subject: [PATCH 34/39] refactor(diary): Refactoring continues --- .../my_profile_screen/my_profile_screen.dart | 317 +++++++++--------- lib/widgets/custom_expandable_list.dart | 2 +- lib/widgets/custom_outlined_button.dart | 2 +- 3 files changed, 166 insertions(+), 155 deletions(-) diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index 585fc08d..9f94f9a7 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -51,8 +51,7 @@ class MyProfileScreen extends StatelessWidget { ); } - Widget _buildMyProfileScreen( - BuildContext context, MyProfileLoadedState state) { + _buildMyProfileScreen(BuildContext context, MyProfileLoadedState state) { mediaQueryData = MediaQuery.of(context); return SafeArea( child: Scaffold( @@ -100,31 +99,35 @@ class MyProfileScreen extends StatelessWidget { ExitButton( text: "exit".tr, margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 17.v), - onTap: () async { - final box = await Hive.openBox('token'); - final token = box.get('token'); - final response = await http.post( - Uri.parse(dotenv.env['SERVER_ROOT']! + '/profile/logout'), - headers: { - 'Authorization': 'Bearer $token', - }, - ); - - if (response.statusCode == 204) { - print(response.statusCode); - box.delete('token'); // Удаляем токен из Hive - Navigator.pushNamed( - context, - AppRoutes.authScreen, - ); - } - }, + onTap: _onTapLogout(context), ) ]); } + Function _onTapLogout(BuildContext context) { + return () async { + final box = await Hive.openBox('token'); + final token = box.get('token'); + final response = await http.post( + Uri.parse(dotenv.env['SERVER_ROOT']! + '/profile/logout'), + headers: { + 'Authorization': 'Bearer $token', + }, + ); + + if (response.statusCode == 204) { + print(response.statusCode); + box.delete('token'); // Удаляем токен из Hive + Navigator.pushNamed( + context, + AppRoutes.authScreen, + ); + } + }; + } + /// Section Widget - Widget _buildMyBlog(BuildContext context) { + _buildMyBlog(BuildContext context) { return Padding( padding: EdgeInsets.symmetric(horizontal: 7.h), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -142,7 +145,7 @@ class MyProfileScreen extends StatelessWidget { } /// Section Widget - Widget _buildSettings(BuildContext context) { + _buildSettings(BuildContext context) { return Padding( padding: EdgeInsets.symmetric(horizontal: 7.h), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -154,19 +157,23 @@ class MyProfileScreen extends StatelessWidget { Expanded( child: NextStepButton( buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - Navigator.pushNamed(context, AppRoutes.mySettings); - }, + onPressed: onTapSettings(context), text: "my_settings".tr.toUpperCase(), margin: EdgeInsets.only(left: 10.h))), ])); } - Widget _buildBottomBar(BuildContext context) { + onTapSettings(BuildContext context) { + return () { + Navigator.pushNamed(context, AppRoutes.mySettings); + }; + } + + _buildBottomBar(BuildContext context) { return CustomBottomBar(onChanged: (BottomBarEnum type) {}); } - Widget _buildCarousel(BuildContext contex, MyProfileLoadedState state) { + _buildCarousel(BuildContext contex, MyProfileLoadedState state) { return CarouselSlider( options: CarouselOptions(height: 340.0), items: [1, 2, 3].map((chartType) { @@ -175,9 +182,7 @@ class MyProfileScreen extends StatelessWidget { switch (chartType) { case 1: // График веса return GestureDetector( - onTap: () { - _editWeight(context, state); - }, + onTap: _editWeight(context, state), child: Column(children: [ Text( "weight_chart".tr, @@ -220,9 +225,7 @@ class MyProfileScreen extends StatelessWidget { ]); case 3: //График обхватов return GestureDetector( - onTap: () { - _editCircumference(context, state); - }, + onTap: _editCircumference(context, state), child: Column(children: [ Text( "circumferences_chart".tr, @@ -244,7 +247,7 @@ class MyProfileScreen extends StatelessWidget { ); } - Widget _buildChartLegend() { + _buildChartLegend() { final colors = [Colors.pink, Colors.green, Colors.purple]; final titles = ["chest".tr, "waist".tr, "hips".tr]; final style = TextStyle( @@ -277,7 +280,7 @@ class MyProfileScreen extends StatelessWidget { } /// Section Widget - Widget _buildChart( + _buildChart( BuildContext context, List chartPoints, List? dates) { // Определение осей графика List spots = []; @@ -340,20 +343,7 @@ class MyProfileScreen extends StatelessWidget { touchTooltipData: LineTouchTooltipData( maxContentWidth: 100, tooltipBgColor: Colors.black, - getTooltipItems: (touchedSpots) { - return touchedSpots.map((LineBarSpot touchedSpot) { - final textStyle = TextStyle( - color: touchedSpot.bar.gradient?.colors[0] ?? - touchedSpot.bar.color, - fontWeight: FontWeight.bold, - fontSize: 14, - ); - return LineTooltipItem( - '${touchedSpot.x}, ${touchedSpot.y.toStringAsFixed(2)}', - textStyle, - ); - }).toList(); - }, + getTooltipItems: mapSpots(), ), handleBuiltInTouches: true, getTouchLineStart: (data, index) => 0, @@ -410,9 +400,7 @@ class MyProfileScreen extends StatelessWidget { drawVerticalLine: true, horizontalInterval: 1.5, verticalInterval: 5, - checkToShowHorizontalLine: (value) { - return value.toInt() == 0; - }, + checkToShowHorizontalLine: valuteToInt(), getDrawingHorizontalLine: (_) => FlLine( color: Colors.blue.withOpacity(1), dashArray: [8, 2], @@ -423,9 +411,7 @@ class MyProfileScreen extends StatelessWidget { dashArray: [8, 2], strokeWidth: 0.8, ), - checkToShowVerticalLine: (value) { - return value.toInt() == 0; - }, + checkToShowVerticalLine: valuteToInt(), ), borderData: FlBorderData(show: false), ), @@ -436,7 +422,29 @@ class MyProfileScreen extends StatelessWidget { ); } - Widget _buildCircumferenceChart( + valuteToInt() { + return (value) { + return value.toInt() == 0; + }; + } + + mapSpots() { + return (touchedSpots) { + return touchedSpots.map((LineBarSpot touchedSpot) { + final textStyle = TextStyle( + color: touchedSpot.bar.gradient?.colors[0] ?? touchedSpot.bar.color, + fontWeight: FontWeight.bold, + fontSize: 14, + ); + return LineTooltipItem( + '${touchedSpot.x}, ${touchedSpot.y.toStringAsFixed(2)}', + textStyle, + ); + }).toList(); + }; + } + + _buildCircumferenceChart( BuildContext context, chartPoints, List? dates) { // Определение осей графика final chestCircumferences = @@ -526,20 +534,7 @@ class MyProfileScreen extends StatelessWidget { touchTooltipData: LineTouchTooltipData( maxContentWidth: 100, tooltipBgColor: Colors.black, - getTooltipItems: (touchedSpots) { - return touchedSpots.map((LineBarSpot touchedSpot) { - final textStyle = TextStyle( - color: touchedSpot.bar.gradient?.colors[0] ?? - touchedSpot.bar.color, - fontWeight: FontWeight.bold, - fontSize: 14, - ); - return LineTooltipItem( - '${touchedSpot.x}, ${touchedSpot.y.toStringAsFixed(2)}', - textStyle, - ); - }).toList(); - }, + getTooltipItems: mapTouchedSpots(), ), handleBuiltInTouches: true, getTouchLineStart: (data, index) => 0, @@ -618,9 +613,7 @@ class MyProfileScreen extends StatelessWidget { drawVerticalLine: true, horizontalInterval: 1.5, verticalInterval: 5, - checkToShowHorizontalLine: (value) { - return value.toInt() == 0; - }, + checkToShowHorizontalLine: valuteToInt(), getDrawingHorizontalLine: (_) => FlLine( color: Colors.blue.withOpacity(1), dashArray: [8, 2], @@ -631,9 +624,7 @@ class MyProfileScreen extends StatelessWidget { dashArray: [8, 2], strokeWidth: 0.8, ), - checkToShowVerticalLine: (value) { - return value.toInt() == 0; - }, + checkToShowVerticalLine: valuteToInt(), ), borderData: FlBorderData(show: false), ), @@ -644,8 +635,24 @@ class MyProfileScreen extends StatelessWidget { ); } + mapTouchedSpots() { + return (touchedSpots) { + return touchedSpots.map((LineBarSpot touchedSpot) { + final textStyle = TextStyle( + color: touchedSpot.bar.gradient?.colors[0] ?? touchedSpot.bar.color, + fontWeight: FontWeight.bold, + fontSize: 14, + ); + return LineTooltipItem( + '${touchedSpot.x}, ${touchedSpot.y.toStringAsFixed(2)}', + textStyle, + ); + }).toList(); + }; + } + /// Section Widget - Widget _buildPlans(BuildContext context, List? plans, + _buildPlans(BuildContext context, List? plans, List? imagePaths, List? states) { return Padding( padding: EdgeInsets.only(left: 7.h), @@ -829,46 +836,7 @@ class MyProfileScreen extends StatelessWidget { child: Text("Отмена", style: theme.textTheme.bodyLarge), ), TextButton( - onPressed: () async { - Map data = { - "chest_circumference": - state.chestCircumferenceController?.text, - "waist_circumference": - state.waistCircumferenceController?.text, - "hip_circumference": state.hipCircumferenceController?.text, - }; - - // Преобразование Map в JSON - String jsonData = json.encode(data); - - // Отправка HTTP-запроса - try { - final token = state.token; - final response = await http.post( - Uri.parse(dotenv.env['SERVER_ROOT']! + - '/profile/addCircumference'), - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }, - body: jsonData, - ); - - if (response.statusCode == 201) { - Navigator.pushNamed( - context, - AppRoutes.myProfile, - ); - } else { - // Ошибка от сервера - print( - "Ошибка при отправке данных. Код ответа: ${response.statusCode}"); - } - } catch (e) { - // Обработка ошибок при отправке запроса - print("Ошибка при отправке запроса: $e"); - } - }, + onPressed: sendEditData(state, context), child: Text("Изменить", style: CustomTextStyles.titleMediumBlack.copyWith( color: Colors.blue, @@ -883,6 +851,46 @@ class MyProfileScreen extends StatelessWidget { ); } + sendEditData(MyProfileLoadedState state, BuildContext context) { + return () async { + Map data = { + "chest_circumference": state.chestCircumferenceController?.text, + "waist_circumference": state.waistCircumferenceController?.text, + "hip_circumference": state.hipCircumferenceController?.text, + }; + + // Преобразование Map в JSON + String jsonData = json.encode(data); + + // Отправка HTTP-запроса + try { + final token = state.token; + final response = await http.post( + Uri.parse(dotenv.env['SERVER_ROOT']! + '/profile/addCircumference'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: jsonData, + ); + + if (response.statusCode == 201) { + Navigator.pushNamed( + context, + AppRoutes.myProfile, + ); + } else { + // Ошибка от сервера + print( + "Ошибка при отправке данных. Код ответа: ${response.statusCode}"); + } + } catch (e) { + // Обработка ошибок при отправке запроса + print("Ошибка при отправке запроса: $e"); + } + }; + } + _editWeight(BuildContext context, MyProfileLoadedState state) { showDialog( context: context, @@ -913,41 +921,7 @@ class MyProfileScreen extends StatelessWidget { child: Text("Отмена", style: theme.textTheme.bodyLarge), ), TextButton( - onPressed: () async { - Map data = { - "weight": state.weightController!.text, - }; - // Преобразование Map в JSON - String jsonData = json.encode(data); - - // Отправка HTTP-запроса - try { - final token = state.token; - final response = await http.post( - Uri.parse( - dotenv.env['SERVER_ROOT']! + '/profile/addWeight'), - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }, - body: jsonData, - ); - - if (response.statusCode == 201) { - Navigator.pushNamed( - context, - AppRoutes.myProfile, - ); - } else { - // Ошибка от сервера - print( - "Ошибка при отправке данных. Код ответа: ${response.statusCode}"); - } - } catch (e) { - // Обработка ошибок при отправке запроса - print("Ошибка при отправке запроса: $e"); - } - }, + onPressed: addWeight(state, context), child: Text("Изменить", style: CustomTextStyles.titleMediumBlack.copyWith( color: Colors.blue, @@ -961,4 +935,41 @@ class MyProfileScreen extends StatelessWidget { }, ); } + + addWeight(MyProfileLoadedState state, BuildContext context) { + return () async { + Map data = { + "weight": state.weightController!.text, + }; + // Преобразование Map в JSON + String jsonData = json.encode(data); + + // Отправка HTTP-запроса + try { + final token = state.token; + final response = await http.post( + Uri.parse(dotenv.env['SERVER_ROOT']! + '/profile/addWeight'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: jsonData, + ); + + if (response.statusCode == 201) { + Navigator.pushNamed( + context, + AppRoutes.myProfile, + ); + } else { + // Ошибка от сервера + print( + "Ошибка при отправке данных. Код ответа: ${response.statusCode}"); + } + } catch (e) { + // Обработка ошибок при отправке запроса + print("Ошибка при отправке запроса: $e"); + } + }; + } } diff --git a/lib/widgets/custom_expandable_list.dart b/lib/widgets/custom_expandable_list.dart index db4cdab0..f20ac19e 100644 --- a/lib/widgets/custom_expandable_list.dart +++ b/lib/widgets/custom_expandable_list.dart @@ -80,7 +80,7 @@ class _ExpandableListState extends State { }; } - Widget _buildForm(BuildContext context, MyProfileLoadedState state) { + _buildForm(BuildContext context, MyProfileLoadedState state) { List cities = [ 'Москва', 'Санкт-Петербург', diff --git a/lib/widgets/custom_outlined_button.dart b/lib/widgets/custom_outlined_button.dart index f2ffd707..38a77041 100644 --- a/lib/widgets/custom_outlined_button.dart +++ b/lib/widgets/custom_outlined_button.dart @@ -89,7 +89,7 @@ class CustomOutlinedButton extends BaseButton { } } - /*Widget _buildOutlinedButtonWidget() { + /*_buildAppBarbuildOutlinedButtonWidget() { return Container( height: this.height ?? 30.v, width: this.width ?? double.maxFinite, From 43da826fa4a632353ecfd2b3475e73e0fa5b50a4 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 12:32:58 +0300 Subject: [PATCH 35/39] refactor(diary): Refactoring done for profille_screen --- .../my_profile_screen/my_profile_screen.dart | 124 ++++++++++-------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index 9f94f9a7..cb11557c 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -788,51 +788,58 @@ class MyProfileScreen extends StatelessWidget { showDialog( context: context, builder: (context) { - final digitsOnly = FilteringTextInputFormatter.digitsOnly; + //final digitsOnly = FilteringTextInputFormatter.digitsOnly; return AlertDialog( title: Center(child: Text("Добавить замер")), - content: SingleChildScrollView( - child: Column( - children: [ - Text("chest_circumference".tr, + content: ListView( + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 5.v), + child: Text("chest_circumference".tr, style: theme.textTheme.bodyLarge), - SizedBox(height: 5.v), - CustomTextFormField( - controller: state.chestCircumferenceController, - keyboardType: TextInputType.number, - inputFormatters: [ - digitsOnly // Ограничение ввода только цифрами - ], - ), - SizedBox(height: 15.v), - Text("waist_circumference".tr, + ), + SizedBox(height: 5.v), + CustomTextFormField( + controller: state.chestCircumferenceController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter + .digitsOnly, // Ограничение ввода только цифрами + ], + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 15.v), + child: Text("waist_circumference".tr, style: theme.textTheme.bodyLarge), - SizedBox(height: 5.v), - CustomTextFormField( - controller: state.waistCircumferenceController, - keyboardType: TextInputType.number, - inputFormatters: [ - digitsOnly // Ограничение ввода только цифрами - ], - ), - SizedBox(height: 15.v), - Text("hip_circumference".tr, style: theme.textTheme.bodyLarge), - SizedBox(height: 5.v), - CustomTextFormField( - controller: state.hipCircumferenceController, - keyboardType: TextInputType.number, - inputFormatters: [ - digitsOnly // Ограничение ввода только цифрами - ], - ), - ], - ), + ), + SizedBox(height: 5.v), + CustomTextFormField( + controller: state.waistCircumferenceController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter + .digitsOnly, // Ограничение ввода только цифрами + ], + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 15.v), + child: Text("hip_circumference".tr, + style: theme.textTheme.bodyLarge), + ), + SizedBox(height: 5.v), + CustomTextFormField( + controller: state.hipCircumferenceController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter + .digitsOnly, // Ограничение ввода только цифрами + ], + ), + ], ), actions: [ TextButton( - onPressed: () { - Navigator.pop(context); - }, + onPressed: onTapOk(context), child: Text("Отмена", style: theme.textTheme.bodyLarge), ), TextButton( @@ -895,29 +902,28 @@ class MyProfileScreen extends StatelessWidget { showDialog( context: context, builder: (context) { - final digitsOnly = FilteringTextInputFormatter.digitsOnly; return AlertDialog( title: Center(child: Text("add_measure".tr)), - content: SingleChildScrollView( - child: Column( - children: [ - Text("weight".tr, style: theme.textTheme.bodyLarge), - SizedBox(height: 5.v), - CustomTextFormField( - controller: state.weightController, - keyboardType: TextInputType.number, - inputFormatters: [ - digitsOnly // Ограничение ввода только цифрами - ], - ), - ], - ), + content: ListView( + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 5.v), + child: Text("weight".tr, style: theme.textTheme.bodyLarge), + ), + SizedBox(height: 5.v), + CustomTextFormField( + controller: state.weightController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter + .digitsOnly, // Ограничение ввода только цифрами + ], + ), + ], ), actions: [ TextButton( - onPressed: () { - Navigator.pop(context); - }, + onPressed: onTapOk(context), child: Text("Отмена", style: theme.textTheme.bodyLarge), ), TextButton( @@ -936,6 +942,12 @@ class MyProfileScreen extends StatelessWidget { ); } + onTapOk(BuildContext context) { + return () { + Navigator.pop(context); + }; + } + addWeight(MyProfileLoadedState state, BuildContext context) { return () async { Map data = { From a4586f91c23d3031b3f5aae8f78cf89438207b3b Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 13:12:55 +0300 Subject: [PATCH 36/39] Refactoring diary started --- .../diary_edit_screen/diary_edit_screen.dart | 897 +++++++++--------- 1 file changed, 441 insertions(+), 456 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index 0068e333..a8ad156c 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -92,7 +92,7 @@ class DiaryEditScreen extends StatelessWidget { } /// Section Widget - Widget _buildHeaderRow(BuildContext context, DiaryEditLoadedState state) { + _buildHeaderRow(BuildContext context, DiaryEditLoadedState state) { final day = state.diaryId; return Container( margin: EdgeInsets.symmetric(horizontal: 16.h, vertical: 16.h), @@ -102,7 +102,7 @@ class DiaryEditScreen extends StatelessWidget { ), decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(12), + borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), @@ -116,10 +116,7 @@ class DiaryEditScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CustomImageView( - imagePath: ImageConstant.imgArrowLeft, - onTap: () { - NavigatorService.goBack(); - }), + imagePath: ImageConstant.imgArrowLeft, onTap: onTapBack()), Padding( padding: EdgeInsets.only(top: 1.v), child: Column( @@ -144,30 +141,32 @@ class DiaryEditScreen extends StatelessWidget { ); } + onTapBack() { + return () { + NavigatorService.goBack(); + }; + } + /// Section Widget - Widget _buildAddProduct(BuildContext context, DiaryEditLoadedState state) { + _buildAddProduct(BuildContext context, DiaryEditLoadedState state) { return CustomOutlinedButton( text: "Добавить продукт", margin: EdgeInsets.symmetric(horizontal: 10.h), buttonStyle: CustomButtonStyles.outlinePrimaryTL15, - onPressed: () { - context.read().add(AddPortionEvent()); - }, + onPressed: addProduct(context), ); } + addProduct(BuildContext context) { + return () { + context.read().add(AddPortionEvent()); + }; + } + /// Section Widget - Widget _buildAddPhoto(BuildContext context) { + _buildAddPhoto(BuildContext context) { return GestureDetector( - onTap: () async { - final picker = ImagePicker(); - List? images = await picker.pickMultiImage(); - if (images.isNotEmpty) { - for (var image in images) { - context.read().add(UploadImages(image)); - } - } - }, + onTap: addImage(context), child: Container( margin: EdgeInsets.symmetric(horizontal: 10.h), padding: EdgeInsets.symmetric( @@ -202,243 +201,249 @@ class DiaryEditScreen extends StatelessWidget { ); } - Padding _buildMeal(BuildContext context, DiaryEditLoadedState state) { + addImage(BuildContext context) { + return () async { + final picker = ImagePicker(); + List? images = await picker.pickMultiImage(); + if (images.isNotEmpty) { + for (var image in images) { + context.read().add(UploadImages(image)); + } + } + }; + } + + _buildMeal(BuildContext context, DiaryEditLoadedState state) { final digitsOnly = FilteringTextInputFormatter.digitsOnly; List _options = state.autocompleteList!.map((dynamic item) => item as String).toList(); print(_options); - return Padding( - padding: EdgeInsets.symmetric(horizontal: 16.h), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 24.h, - vertical: 12.v, - ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: Offset(0, 3), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Время приема пищи", - style: CustomTextStyles.bodyMediumBlack900, - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width - 260, - ), - child: GestureDetector( - onTap: () => _selectMealTime(context, state), - child: AbsorbPointer( - child: CustomTextFormField( - hintText: state.mealTimeController - ?.format(context) - .toString(), - autofocus: false, - ), + return Container( + margin: EdgeInsets.symmetric(horizontal: 16.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(12)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Время приема пищи", + style: CustomTextStyles.bodyMediumBlack900, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width - 260, + ), + child: GestureDetector( + onTap: () => _selectMealTime(context, state), + child: AbsorbPointer( + child: CustomTextFormField( + hintText: state.mealTimeController + ?.format(context) + .toString(), + autofocus: false, ), ), ), ), - ], - ), + ), + ], ), - SizedBox(height: 20.v), - Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: BlocSelector( - selector: (state) => state.diaryEditModelObj, - builder: (context, diaryEditModelObj) { - return CustomDropDown( - hintText: "Прием пищи", - items: diaryEditModelObj?.mealList, - contentPadding: EdgeInsets.symmetric( - horizontal: 10.h, - vertical: 9.v, - ), - defaultValue: diaryEditModelObj?.mealList[0], - onChanged: (value) { - context.read().add( - ChangeMeal(meals: state.meals, value: value)); - }, - ); - })), - SizedBox(height: 20.v), - Padding( + ), + SizedBox(height: 20.v), + Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), - child: RawAutocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - return _options.where((String option) { - return true; - }); - }, fieldViewBuilder: ( - BuildContext context, - TextEditingController textEditingController, - FocusNode focusNode, - VoidCallback onFieldSubmitted, - ) { - return CustomTextFormField( - hintText: "Введите название продукта", - controller: textEditingController, - focusNode: focusNode, - onChanged: (value) { - /*print(state.autocompleteList + child: BlocSelector( + selector: (state) => state.diaryEditModelObj, + builder: (context, diaryEditModelObj) { + return CustomDropDown( + hintText: "Прием пищи", + items: diaryEditModelObj?.mealList, + contentPadding: EdgeInsets.symmetric( + horizontal: 10.h, + vertical: 9.v, + ), + defaultValue: diaryEditModelObj?.mealList[0], + onChanged: (value) { + context.read().add( + ChangeMeal(meals: state.meals, value: value)); + }, + ); + })), + SizedBox(height: 20.v), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: RawAutocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + return _options.where((String option) { + return true; + }); + }, fieldViewBuilder: ( + BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted, + ) { + return CustomTextFormField( + hintText: "Введите название продукта", + controller: textEditingController, + focusNode: focusNode, + onChanged: (value) { + /*print(state.autocompleteList ?.map((dynamic item) => item as String) .toList());*/ - if (value.length > 2) { - context.read().add(ProductInput(value)); - } - }, - /*onFieldSubmitted: (String value) { + if (value.length > 2) { + context.read().add(ProductInput(value)); + } + }, + /*onFieldSubmitted: (String value) { onFieldSubmitted(); },*/ - ); - }, optionsViewBuilder: ( - BuildContext context, - AutocompleteOnSelected onSelected, - Iterable options, - ) { - return Align( - alignment: Alignment.topLeft, - child: Material( - elevation: 4.0, - child: SizedBox( - height: 200.0, - child: ListView.builder( - padding: const EdgeInsets.all(8.0), - itemCount: options.length, - itemBuilder: (BuildContext context, int index) { - final String option = options.elementAt(index); - return GestureDetector( - onTap: () { - onSelected(option); - }, - child: ListTile( - title: Text(option), - ), - ); - }, - ), + ); + }, optionsViewBuilder: ( + BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options, + ) { + return Align( + alignment: Alignment.topLeft, + child: Material( + elevation: 4.0, + child: SizedBox( + height: 200.0, + child: ListView.builder( + padding: const EdgeInsets.all(8.0), + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + final String option = options.elementAt(index); + return GestureDetector( + onTap: () { + onSelected(option); + }, + child: ListTile( + title: Text(option), + ), + ); + }, ), ), + ), + ); + }), + ), + SizedBox(height: 20.v), + Padding( + padding: EdgeInsets.symmetric(horizontal: 10.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomTextFormField( + width: 146.h, + hintText: "Кол-во", + textInputAction: TextInputAction.done, + controller: state.productQuantityController, + keyboardType: TextInputType.number, + inputFormatters: [digitsOnly], + ), + Padding( + padding: EdgeInsets.only(right: 30.h), + child: Text( + "порций", + style: CustomTextStyles.bodyMediumBlack900, + )), + ], + ), + ), + SizedBox(height: 30.v), + _buildAddProduct(context, state), + SizedBox(height: 30.v), + ...state.portions! + .map((portion) => _buildProduct(context, portion)) + .toList(), + SizedBox(height: 30.v), + _buildAddPhoto(context), + SizedBox(height: 30.v), + Text( + "Ваша сытость после приёма пищи", + style: CustomTextStyles.bodyMediumBlack900, + ), + SizedBox(height: 15.v), + BlocBuilder( + builder: (context, state) { + if (state is DiaryEditLoadedState) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("😭"), + ScaleElement( + color: Colors.red, + isSelected: state.selectedSatiety == 0, + onTap: () { + context.read().add(ChangeSatiety(0)); + }, + ), + ScaleElement( + color: Colors.orange, + isSelected: state.selectedSatiety == 1, + onTap: () { + context.read().add(ChangeSatiety(1)); + }, + ), + ScaleElement( + color: Colors.yellow, + isSelected: state.selectedSatiety == 2, + onTap: () { + context.read().add(ChangeSatiety(2)); + }, + ), + ScaleElement( + color: Colors.lime, + isSelected: state.selectedSatiety == 3, + onTap: () { + context.read().add(ChangeSatiety(3)); + }, + ), + ScaleElement( + color: Colors.lightGreen, + isSelected: state.selectedSatiety == 4, + onTap: () { + context.read().add(ChangeSatiety(4)); + }, + ), + ScaleElement( + color: Colors.green, + isSelected: state.selectedSatiety == 5, + onTap: () { + context.read().add(ChangeSatiety(5)); + }, + ), + Text("😊"), + // Остальные элементы шкалы + ], ); - }), - ), - SizedBox(height: 20.v), - Padding( - padding: EdgeInsets.symmetric(horizontal: 10.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - CustomTextFormField( - width: 146.h, - hintText: "Кол-во", - textInputAction: TextInputAction.done, - controller: state.productQuantityController, - keyboardType: TextInputType.number, - inputFormatters: [digitsOnly], - ), - Padding( - padding: EdgeInsets.only(right: 30.h), - child: Text( - "порций", - style: CustomTextStyles.bodyMediumBlack900, - )), - ], - ), - ), - SizedBox(height: 30.v), - _buildAddProduct(context, state), - SizedBox(height: 30.v), - ...state.portions! - .map((portion) => _buildProduct(context, portion)) - .toList(), - SizedBox(height: 30.v), - _buildAddPhoto(context), - SizedBox(height: 30.v), - Text( - "Ваша сытость после приёма пищи", - style: CustomTextStyles.bodyMediumBlack900, - ), - SizedBox(height: 15.v), - BlocBuilder( - builder: (context, state) { - if (state is DiaryEditLoadedState) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("😭"), - ScaleElement( - color: Colors.red, - isSelected: state.selectedSatiety == 0, - onTap: () { - context.read().add(ChangeSatiety(0)); - }, - ), - ScaleElement( - color: Colors.orange, - isSelected: state.selectedSatiety == 1, - onTap: () { - context.read().add(ChangeSatiety(1)); - }, - ), - ScaleElement( - color: Colors.yellow, - isSelected: state.selectedSatiety == 2, - onTap: () { - context.read().add(ChangeSatiety(2)); - }, - ), - ScaleElement( - color: Colors.lime, - isSelected: state.selectedSatiety == 3, - onTap: () { - context.read().add(ChangeSatiety(3)); - }, - ), - ScaleElement( - color: Colors.lightGreen, - isSelected: state.selectedSatiety == 4, - onTap: () { - context.read().add(ChangeSatiety(4)); - }, - ), - ScaleElement( - color: Colors.green, - isSelected: state.selectedSatiety == 5, - onTap: () { - context.read().add(ChangeSatiety(5)); - }, - ), - Text("😊"), - // Остальные элементы шкалы - ], - ); - } else { - return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState - } - }, - ) - ], - ), + } else { + return Container(); // Возвращаем пустой контейнер, если состояние не является DiaryEditLoadedState + } + }, + ) + ], )); } @@ -497,7 +502,7 @@ class DiaryEditScreen extends StatelessWidget { ); } - Widget _buildNutritionChart(BuildContext context) { + _buildNutritionChart(BuildContext context) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), padding: EdgeInsets.symmetric( @@ -506,7 +511,7 @@ class DiaryEditScreen extends StatelessWidget { ), decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(12), + borderRadius: const BorderRadius.all(Radius.circular(12)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), @@ -737,148 +742,129 @@ class DiaryEditScreen extends StatelessWidget { } /// Section Widget - Widget _buildComment(BuildContext context, DiaryEditLoadedState state) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 16.h), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 24.h, - vertical: 12.v, + _buildComment(BuildContext context, DiaryEditLoadedState state) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16.h), + padding: EdgeInsets.symmetric( + horizontal: 24.h, + vertical: 12.v, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(12)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: Offset(0, 3), - ), - ], + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Дополнительная информация для консультанта", + style: theme.textTheme.titleMedium, + textAlign: TextAlign.center, ), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Дополнительная информация для консультанта", - style: theme.textTheme.titleMedium, - textAlign: TextAlign.center, - ), - Align( - alignment: Alignment.bottomCenter, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 20.v), - Container( - width: 320.h, - child: CustomTextFormField( - autofocus: false, - hintText: "Введите информацию для консультанта", - maxLines: 7, - borderDecoration: InputBorder.none, - controller: state.commentController, - ), - ), - ], - ), - ), - ], + SizedBox(height: 20.v), + Container( + width: 320.h, + child: CustomTextFormField( + autofocus: false, + hintText: "Введите информацию для консультанта", + maxLines: 7, + borderDecoration: InputBorder.none, + controller: state.commentController, + ), ), - )); + ], + ), + ); } - Padding _buildWakupRetire(BuildContext context, DiaryEditLoadedState state) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 16.h), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 24.h, - vertical: 12.v, + _buildWakupRetire(BuildContext context, DiaryEditLoadedState state) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16.h), + padding: EdgeInsets.symmetric( + horizontal: 24.h, + vertical: 12.v, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(12)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: Offset(0, 3), - ), - ], + ], + ), + child: Column( + children: [ + GestureDetector( + onTap: () { + BlocProvider.of(context) + .add(ToggleWakeupExpandedEvent()); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + r"Подъем \ отход ко сну", + style: CustomTextStyles.bodyMediumBlack900, + ), + Icon(state.wakeupExpanded + ? Icons.arrow_drop_up + : Icons.arrow_drop_down), + ], + ), ), - child: Column( - children: [ - GestureDetector( - onTap: () { - BlocProvider.of(context) - .add(ToggleWakeupExpandedEvent()); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - r"Подъем \ отход ко сну", - style: CustomTextStyles.bodyMediumBlack900, + if (state.wakeupExpanded) + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Column( + children: [ + SizedBox(height: 20.v), + GestureDetector( + onTap: () => _selectWakeupTime(context, state), + child: AbsorbPointer( + child: CustomTextFormField( + hintText: + state.wakeupController?.format(context).toString(), + prefix: Icon(Icons.sunny), + autofocus: false, + ), ), - Icon(state.wakeupExpanded - ? Icons.arrow_drop_up - : Icons.arrow_drop_down), - ], - ), - ), - if (state.wakeupExpanded) - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Column( - children: [ - SizedBox(height: 20.v), - GestureDetector( - onTap: () => _selectWakeupTime(context, state), - child: AbsorbPointer( - child: CustomTextFormField( - hintText: state.wakeupController - ?.format(context) - .toString(), - prefix: Icon(Icons.sunny), - autofocus: false, - /*initialValue: state.wakeupController - ?.format(context) - .toString()*/ - ), - ), - ), - SizedBox(height: 20.v), - GestureDetector( - onTap: () => _selectRetireTime(context, state), - child: AbsorbPointer( - child: CustomTextFormField( - hintText: state.retireController - ?.format(context) - .toString(), - prefix: Icon(Icons.bed), - autofocus: false, - /*initialValue: state.retireController - ?.format(context) - .toString(),*/ - ), - ), - ), - SizedBox(height: 20.v), - ], ), - ), - ], - )), + SizedBox(height: 20.v), + GestureDetector( + onTap: () => _selectRetireTime(context, state), + child: AbsorbPointer( + child: CustomTextFormField( + hintText: + state.retireController?.format(context).toString(), + prefix: Icon(Icons.bed), + autofocus: false, + ), + ), + ), + SizedBox(height: 20.v), + ], + ), + ), + ], + ), ); } /// Section Widget - Widget _buildEndDay(BuildContext context) { + _buildEndDay(BuildContext context) { return CustomOutlinedButton( text: "Закончить день", margin: EdgeInsets.only( @@ -893,97 +879,96 @@ class DiaryEditScreen extends StatelessWidget { ); } - Widget _buildMood(BuildContext context, DiaryEditLoadedState state) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 16.h), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 24.h, - vertical: 12.v, + _buildMood(BuildContext context, DiaryEditLoadedState state) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 16.h), + padding: EdgeInsets.symmetric( + horizontal: 24.h, + vertical: 12.v, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(12)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), ), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 2, - blurRadius: 5, - offset: Offset(0, 3), + ], + ), + child: Column(children: [ + GestureDetector( + onTap: () { + BlocProvider.of(context) + .add(ToggleMoodExpandedEvent()); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Ваше настроение после приема пищи", + style: CustomTextStyles.bodyMediumBlack900, ), + Icon(state.moodExpanded + ? Icons.arrow_drop_up + : Icons.arrow_drop_down), ], ), - child: Column(children: [ - GestureDetector( - onTap: () { - BlocProvider.of(context) - .add(ToggleMoodExpandedEvent()); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Ваше настроение после приема пищи", - style: CustomTextStyles.bodyMediumBlack900, - ), - Icon(state.moodExpanded - ? Icons.arrow_drop_up - : Icons.arrow_drop_down), - ], + ), + if (state.moodExpanded) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("😭"), + ScaleElement( + color: Colors.red, + isSelected: state.selectedMood == 0, + onTap: () { + context.read().add(ChangeMood(0)); + }, ), - ), - if (state.moodExpanded) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("😭"), - ScaleElement( - color: Colors.red, - isSelected: state.selectedMood == 0, - onTap: () { - context.read().add(ChangeMood(0)); - }, - ), - ScaleElement( - color: Colors.orange, - isSelected: state.selectedMood == 1, - onTap: () { - context.read().add(ChangeMood(1)); - }, - ), - ScaleElement( - color: Colors.yellow, - isSelected: state.selectedMood == 2, - onTap: () { - context.read().add(ChangeMood(2)); - }, - ), - ScaleElement( - color: Colors.lime, - isSelected: state.selectedMood == 3, - onTap: () { - context.read().add(ChangeMood(3)); - }, - ), - ScaleElement( - color: Colors.lightGreen, - isSelected: state.selectedMood == 4, - onTap: () { - context.read().add(ChangeMood(4)); - }, - ), - ScaleElement( - color: Colors.green, - isSelected: state.selectedMood == 5, - onTap: () { - context.read().add(ChangeMood(5)); - }, - ), - Text("😊"), - // Остальные элементы шкалы - ], + ScaleElement( + color: Colors.orange, + isSelected: state.selectedMood == 1, + onTap: () { + context.read().add(ChangeMood(1)); + }, ), - ]))); + ScaleElement( + color: Colors.yellow, + isSelected: state.selectedMood == 2, + onTap: () { + context.read().add(ChangeMood(2)); + }, + ), + ScaleElement( + color: Colors.lime, + isSelected: state.selectedMood == 3, + onTap: () { + context.read().add(ChangeMood(3)); + }, + ), + ScaleElement( + color: Colors.lightGreen, + isSelected: state.selectedMood == 4, + onTap: () { + context.read().add(ChangeMood(4)); + }, + ), + ScaleElement( + color: Colors.green, + isSelected: state.selectedMood == 5, + onTap: () { + context.read().add(ChangeMood(5)); + }, + ), + Text("😊"), + // Остальные элементы шкалы + ], + ), + ])); } Future _selectWakeupTime( From b62c3b49238939419a5f2a54a3a5fb4ca0ae6579 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 14:22:30 +0300 Subject: [PATCH 37/39] Refactoring diary finished --- .../diary_edit_screen/diary_edit_screen.dart | 225 ++++++++++-------- .../my_profile_screen/my_profile_screen.dart | 1 - 2 files changed, 120 insertions(+), 106 deletions(-) diff --git a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart index a8ad156c..1629dd1c 100644 --- a/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart +++ b/lib/presentation/diary/diary_edit_screen/diary_edit_screen.dart @@ -281,72 +281,58 @@ class DiaryEditScreen extends StatelessWidget { vertical: 9.v, ), defaultValue: diaryEditModelObj?.mealList[0], - onChanged: (value) { - context.read().add( - ChangeMeal(meals: state.meals, value: value)); - }, + onChanged: changeMeal(context, state), ); })), SizedBox(height: 20.v), Padding( padding: EdgeInsets.symmetric(horizontal: 10.h), child: RawAutocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - return _options.where((String option) { - return true; - }); - }, fieldViewBuilder: ( - BuildContext context, - TextEditingController textEditingController, - FocusNode focusNode, - VoidCallback onFieldSubmitted, - ) { - return CustomTextFormField( - hintText: "Введите название продукта", - controller: textEditingController, - focusNode: focusNode, - onChanged: (value) { - /*print(state.autocompleteList - ?.map((dynamic item) => item as String) - .toList());*/ - if (value.length > 2) { - context.read().add(ProductInput(value)); - } - }, - /*onFieldSubmitted: (String value) { + optionsBuilder: buildOptions(_options), + fieldViewBuilder: ( + BuildContext context, + TextEditingController textEditingController, + FocusNode focusNode, + VoidCallback onFieldSubmitted, + ) { + return CustomTextFormField( + hintText: "Введите название продукта", + controller: textEditingController, + focusNode: focusNode, + onChanged: getAutocomplete(context), + /*onFieldSubmitted: (String value) { onFieldSubmitted(); },*/ - ); - }, optionsViewBuilder: ( - BuildContext context, - AutocompleteOnSelected onSelected, - Iterable options, - ) { - return Align( - alignment: Alignment.topLeft, - child: Material( - elevation: 4.0, - child: SizedBox( - height: 200.0, - child: ListView.builder( - padding: const EdgeInsets.all(8.0), - itemCount: options.length, - itemBuilder: (BuildContext context, int index) { - final String option = options.elementAt(index); - return GestureDetector( - onTap: () { - onSelected(option); + ); + }, + optionsViewBuilder: ( + BuildContext context, + AutocompleteOnSelected onSelected, + Iterable options, + ) { + return Align( + alignment: Alignment.topLeft, + child: Material( + elevation: 4.0, + child: SizedBox( + height: 200.0, + child: ListView.builder( + padding: const EdgeInsets.all(8.0), + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + final String option = options.elementAt(index); + return GestureDetector( + onTap: selectProduct(onSelected, option), + child: ListTile( + title: Text(option), + ), + ); }, - child: ListTile( - title: Text(option), - ), - ); - }, + ), + ), ), - ), - ), - ); - }), + ); + }), ), SizedBox(height: 20.v), Padding( @@ -395,44 +381,32 @@ class DiaryEditScreen extends StatelessWidget { ScaleElement( color: Colors.red, isSelected: state.selectedSatiety == 0, - onTap: () { - context.read().add(ChangeSatiety(0)); - }, + onTap: changeSatiety(context, 0), ), ScaleElement( color: Colors.orange, isSelected: state.selectedSatiety == 1, - onTap: () { - context.read().add(ChangeSatiety(1)); - }, + onTap: changeSatiety(context, 1), ), ScaleElement( color: Colors.yellow, isSelected: state.selectedSatiety == 2, - onTap: () { - context.read().add(ChangeSatiety(2)); - }, + onTap: changeSatiety(context, 2), ), ScaleElement( color: Colors.lime, isSelected: state.selectedSatiety == 3, - onTap: () { - context.read().add(ChangeSatiety(3)); - }, + onTap: changeSatiety(context, 3), ), ScaleElement( color: Colors.lightGreen, isSelected: state.selectedSatiety == 4, - onTap: () { - context.read().add(ChangeSatiety(4)); - }, + onTap: changeSatiety(context, 4), ), ScaleElement( color: Colors.green, isSelected: state.selectedSatiety == 5, - onTap: () { - context.read().add(ChangeSatiety(5)); - }, + onTap: changeSatiety(context, 5), ), Text("😊"), // Остальные элементы шкалы @@ -447,6 +421,45 @@ class DiaryEditScreen extends StatelessWidget { )); } + changeSatiety(BuildContext context, int satiety) { + return () { + context.read().add(ChangeSatiety(satiety)); + }; + } + + selectProduct(AutocompleteOnSelected onSelected, String option) { + return () { + onSelected(option); + }; + } + + getAutocomplete(BuildContext context) { + return (value) { + /*print(state.autocompleteList + ?.map((dynamic item) => item as String) + .toList());*/ + if (value.length > 2) { + context.read().add(ProductInput(value)); + } + }; + } + + buildOptions(List _options) { + return (TextEditingValue textEditingValue) { + return _options.where((String option) { + return true; + }); + }; + } + + changeMeal(BuildContext context, DiaryEditLoadedState state) { + return (value) { + context + .read() + .add(ChangeMeal(meals: state.meals, value: value)); + }; + } + _buildProduct(BuildContext context, Map portion) { return Container( margin: EdgeInsets.symmetric(horizontal: 10.h), @@ -485,11 +498,7 @@ class DiaryEditScreen extends StatelessWidget { ), Spacer(), GestureDetector( - onTap: () { - context - .read() - .add(RemovePortionEvent(portion['id'])); - }, + onTap: removePortion(context, portion), child: Padding( padding: const EdgeInsets.only(right: 10), child: Icon( @@ -502,6 +511,12 @@ class DiaryEditScreen extends StatelessWidget { ); } + removePortion(BuildContext context, Map portion) { + return () { + context.read().add(RemovePortionEvent(portion['id'])); + }; + } + _buildNutritionChart(BuildContext context) { return Container( margin: EdgeInsets.symmetric(horizontal: 16.h), @@ -808,10 +823,7 @@ class DiaryEditScreen extends StatelessWidget { child: Column( children: [ GestureDetector( - onTap: () { - BlocProvider.of(context) - .add(ToggleWakeupExpandedEvent()); - }, + onTap: toggleWakeup(context), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -863,6 +875,12 @@ class DiaryEditScreen extends StatelessWidget { ); } + toggleWakeup(BuildContext context) { + return () { + BlocProvider.of(context).add(ToggleWakeupExpandedEvent()); + }; + } + /// Section Widget _buildEndDay(BuildContext context) { return CustomOutlinedButton( @@ -900,10 +918,7 @@ class DiaryEditScreen extends StatelessWidget { ), child: Column(children: [ GestureDetector( - onTap: () { - BlocProvider.of(context) - .add(ToggleMoodExpandedEvent()); - }, + onTap: toggleMood(context), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -925,44 +940,32 @@ class DiaryEditScreen extends StatelessWidget { ScaleElement( color: Colors.red, isSelected: state.selectedMood == 0, - onTap: () { - context.read().add(ChangeMood(0)); - }, + onTap: changeMood(context, 0), ), ScaleElement( color: Colors.orange, isSelected: state.selectedMood == 1, - onTap: () { - context.read().add(ChangeMood(1)); - }, + onTap: changeMood(context, 1), ), ScaleElement( color: Colors.yellow, isSelected: state.selectedMood == 2, - onTap: () { - context.read().add(ChangeMood(2)); - }, + onTap: changeMood(context, 2), ), ScaleElement( color: Colors.lime, isSelected: state.selectedMood == 3, - onTap: () { - context.read().add(ChangeMood(3)); - }, + onTap: changeMood(context, 3), ), ScaleElement( color: Colors.lightGreen, isSelected: state.selectedMood == 4, - onTap: () { - context.read().add(ChangeMood(4)); - }, + onTap: changeMood(context, 4), ), ScaleElement( color: Colors.green, isSelected: state.selectedMood == 5, - onTap: () { - context.read().add(ChangeMood(5)); - }, + onTap: changeMood(context, 5), ), Text("😊"), // Остальные элементы шкалы @@ -971,6 +974,18 @@ class DiaryEditScreen extends StatelessWidget { ])); } + changeMood(BuildContext context, int satiety) { + return () { + context.read().add(ChangeMood(satiety)); + }; + } + + toggleMood(BuildContext context) { + return () { + BlocProvider.of(context).add(ToggleMoodExpandedEvent()); + }; + } + Future _selectWakeupTime( BuildContext context, DiaryEditLoadedState state) async { final TimeOfDay? pickedTime = await showTimePicker( diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index cb11557c..77929fd5 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -677,7 +677,6 @@ class MyProfileScreen extends StatelessWidget { Align( alignment: Alignment.topCenter, child: ListView.builder( - shrinkWrap: true, itemCount: plans?.length ?? 0, itemBuilder: (context, i) { String state = states?[i]; From 2c5e9a1749ae08d44ea63c117b3a0d8df9f71342 Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 14:49:21 +0300 Subject: [PATCH 38/39] fix(diary): Remove sample test --- test/widget_test.dart | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 test/widget_test.dart diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index e93dc93b..00000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:eatvio_app/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} From 7b20842853453b7f02f03eb89e0f32f8e6944f0f Mon Sep 17 00:00:00 2001 From: maxxkim Date: Thu, 7 Mar 2024 11:57:27 +0300 Subject: [PATCH 39/39] test(diary) App launch test --- test/launch_test.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/launch_test.dart diff --git a/test/launch_test.dart b/test/launch_test.dart new file mode 100644 index 00000000..4f1eafee --- /dev/null +++ b/test/launch_test.dart @@ -0,0 +1,15 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:eatvio_app/main.dart' as app; + +void main() { + testWidgets('Smoke test', (WidgetTester tester) async { + // Запустить приложение + app.main(); + + // Подождать, пока приложение загрузится + await tester.pumpAndSettle(); + + // Проверить, что нет ошибок + expect(tester.takeException(), isNull); + }); +}