From 00b1452cefdc378363b8fe7ceb5010cf3d38222e Mon Sep 17 00:00:00 2001 From: maxxkim Date: Wed, 6 Mar 2024 11:44:20 +0300 Subject: [PATCH] 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), + ), + ); + } +}