refactor(diary): Refactoring for settings done

This commit is contained in:
2024-03-06 11:44:20 +03:00
parent 3019a5a264
commit 00b1452cef
8 changed files with 664 additions and 593 deletions

View File

@@ -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<LanguageDropdown> {
String selectedLanguage = 'Русский';
@override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: selectedLanguage,
onChanged: (newValue) {
setState(() {
selectedLanguage = newValue!;
});
},
isDense: false, // Установите isDense в false
selectedItemBuilder: (BuildContext context) {
return ['Русский'].map<Widget>((String language) {
return Align(
alignment: Alignment.center, // Выравнивание текста по центру
child: Text(
language,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
);
}).toList();
},
items: ['Русский'].map((String language) {
return DropdownMenuItem<String>(
value: language,
child: Text(language),
);
}).toList(),
);
}
}
class NotificationSwitch extends StatefulWidget {
final String title;
NotificationSwitch(this.title);
@override
_NotificationSwitchState createState() => _NotificationSwitchState();
}
class _NotificationSwitchState extends State<NotificationSwitch> {
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<HyperSwitch> {
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<HypoSwitch> {
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<ExpandableList> {
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<MyProfileBloc, MyProfileState>(
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<String> cities = [
'Москва',
'Санкт-Петербург',
'Новосибирск',
'Екатеринбург',
'Нижний Новгород',
'Казань',
'Челябинск',
'Омск',
'Самара',
'Ростов-на-Дону',
'Уфа',
'Красноярск',
'Воронеж',
'Пермь',
'Волгоград',
'Краснодар',
'Саратов',
'Тюмень',
'Тольятти',
'Ижевск',
'Барнаул',
'Ульяновск',
'Иркутск',
'Хабаровск',
'Ярославль',
'Владивосток',
'Махачкала',
'Томск',
'Оренбург',
'Кемерово',
];
List<String> 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<String>(
value: state.selectedCountry,
hint: Text(state.selectedCountry ?? "Не выбрано"),
onChanged: (newValue) {
// Обработчик изменения выбранной страны
setSelectedCountry(state, newValue);
},
items: countries.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
decoration: InputDecoration(labelText: 'country'.tr),
),
DropdownButtonFormField<String>(
hint: Text(state.selectedCity ?? "Не выбрано"),
value: state.selectedCity,
onChanged: (newValue) {
// Обработчик изменения выбранного города
setSelectedCity(state, newValue);
},
items: cities.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
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: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.heightFormController,
decoration: InputDecoration(labelText: 'height_measurements'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.chestCircumferenceFormController,
decoration: InputDecoration(labelText: 'chest_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.waistCircumferenceFormController,
decoration: InputDecoration(labelText: 'waist_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.hipCircumferenceFormController,
decoration: InputDecoration(labelText: 'hip_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.upPressureFormController,
decoration: InputDecoration(labelText: 'up_pressure'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.downPressureFormController,
decoration: InputDecoration(labelText: 'down_pressure'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[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<void> sendProfileData(MyProfileLoadedState? state) async {
try {
// Создаем JSON объект с данными профиля
Map<String, dynamic> 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<String> items;
AboutList(this.title, this.items);
@override
_AboutListState createState() => _AboutListState();
}
class _AboutListState extends State<AboutList> {
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(),
],
);
}
}

View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
class AboutList extends StatefulWidget {
final String title;
final List<String> items;
AboutList(this.title, this.items);
@override
_AboutListState createState() => _AboutListState();
}
class _AboutListState extends State<AboutList> {
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;
});
};
}
}

View File

@@ -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<ExpandableList> {
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<MyProfileBloc, MyProfileState>(
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<String> cities = [
'Москва',
'Санкт-Петербург',
'Новосибирск',
'Екатеринбург',
'Нижний Новгород',
'Казань',
'Челябинск',
'Омск',
'Самара',
'Ростов-на-Дону',
'Уфа',
'Красноярск',
'Воронеж',
'Пермь',
'Волгоград',
'Краснодар',
'Саратов',
'Тюмень',
'Тольятти',
'Ижевск',
'Барнаул',
'Ульяновск',
'Иркутск',
'Хабаровск',
'Ярославль',
'Владивосток',
'Махачкала',
'Томск',
'Оренбург',
'Кемерово',
];
List<String> 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<String>(
value: state.selectedCountry,
hint: Text(state.selectedCountry ?? "Не выбрано"),
onChanged: setCountry(state),
items: countries.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
decoration: InputDecoration(labelText: 'country'.tr),
),
DropdownButtonFormField<String>(
hint: Text(state.selectedCity ?? "Не выбрано"),
value: state.selectedCity,
onChanged: setCity(state),
items: cities.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
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: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.heightFormController,
decoration: InputDecoration(labelText: 'height_measurements'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.chestCircumferenceFormController,
decoration: InputDecoration(labelText: 'chest_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.waistCircumferenceFormController,
decoration: InputDecoration(labelText: 'waist_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.hipCircumferenceFormController,
decoration: InputDecoration(labelText: 'hip_circumference'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.upPressureFormController,
decoration: InputDecoration(labelText: 'up_pressure'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[digitsOnly]),
TextField(
controller: state.downPressureFormController,
decoration: InputDecoration(labelText: 'down_pressure'.tr),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[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<void> sendProfileData(MyProfileLoadedState? state) async {
try {
// Создаем JSON объект с данными профиля
Map<String, dynamic> 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);
};
}
}

View File

@@ -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<HyperSwitch> {
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";
});
};
}
}

View File

@@ -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<HypoSwitch> {
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";
});
};
}
}

View File

@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
class LanguageDropdown extends StatefulWidget {
@override
_LanguageDropdownState createState() => _LanguageDropdownState();
}
class _LanguageDropdownState extends State<LanguageDropdown> {
String selectedLanguage = 'Русский';
@override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: selectedLanguage,
onChanged: selectLanguage(),
isDense: false, // Установите isDense в false
selectedItemBuilder: getList(),
items: ['Русский'].map((String language) {
return DropdownMenuItem<String>(
value: language,
child: Text(language),
);
}).toList(),
);
}
getList() {
return (BuildContext context) {
return ['Русский'].map<Widget>((String language) {
return Align(
alignment: Alignment.center, // Выравнивание текста по центру
child: Text(
language,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
);
}).toList();
};
}
selectLanguage() {
return (newValue) {
setState(() {
selectedLanguage = newValue!;
});
};
}
}

View File

@@ -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<NotificationSwitch> {
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;
});
};
}
}

View File

@@ -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),
),
);
}
}