forked from eatvio/eatvio_app
refactor(all): refactor
This commit is contained in:
@@ -74,20 +74,16 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
waistCircumferenceController: TextEditingController(),
|
||||
hipCircumferenceController: TextEditingController(),
|
||||
weightController: TextEditingController(),
|
||||
chestCircumferenceFormController:
|
||||
currentState.chestCircumferenceFormController,
|
||||
waistCircumferenceFormController:
|
||||
currentState.waistCircumferenceFormController,
|
||||
hipCircumferenceFormController:
|
||||
currentState.hipCircumferenceFormController,
|
||||
chestCircumferenceFormController: currentState.chestCircumferenceFormController,
|
||||
waistCircumferenceFormController: currentState.waistCircumferenceFormController,
|
||||
hipCircumferenceFormController: currentState.hipCircumferenceFormController,
|
||||
firstNameFormController: currentState.firstNameFormController,
|
||||
lastNameFormController: currentState.lastNameFormController,
|
||||
countryFormController: currentState.countryFormController,
|
||||
cityFormController: currentState.cityFormController,
|
||||
heightFormController: currentState.heightFormController,
|
||||
upPressureFormController: currentState.upPressureFormController,
|
||||
downPressureFormController:
|
||||
currentState.downPressureFormController,
|
||||
downPressureFormController: currentState.downPressureFormController,
|
||||
allergiesFormController: currentState.allergiesFormController,
|
||||
pillsFormController: currentState.pillsFormController,
|
||||
favoriteFormController: currentState.favoriteFormController,
|
||||
@@ -181,8 +177,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
waistCircumferenceController: TextEditingController(),
|
||||
hipCircumferenceController: TextEditingController(),
|
||||
hypoFormController: data['userDetails']['has_hypo'].toString(),
|
||||
hyperFormController:
|
||||
data['userDetails']['has_hyper'].toString(),
|
||||
hyperFormController: data['userDetails']['has_hyper'].toString(),
|
||||
chestCircumferenceFormController: TextEditingController(
|
||||
text: data['userDetails']['chest_circumference']?.toString(),
|
||||
),
|
||||
@@ -201,12 +196,9 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
firstNameFormController: TextEditingController(
|
||||
text: data['userDetails']['first_name'],
|
||||
),
|
||||
lastNameFormController: TextEditingController(
|
||||
text: data['userDetails']['last_name']),
|
||||
countryFormController:
|
||||
TextEditingController(text: data['userDetails']['country']),
|
||||
cityFormController:
|
||||
TextEditingController(text: data['userDetails']['city']),
|
||||
lastNameFormController: TextEditingController(text: data['userDetails']['last_name']),
|
||||
countryFormController: TextEditingController(text: data['userDetails']['country']),
|
||||
cityFormController: TextEditingController(text: data['userDetails']['city']),
|
||||
heightFormController: TextEditingController(
|
||||
text: data['userDetails']['height']?.toString(),
|
||||
),
|
||||
@@ -234,8 +226,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
additionalFormController: TextEditingController(
|
||||
text: data['userDetails']['additional_info'],
|
||||
),
|
||||
dateFormController: TextEditingController(
|
||||
text: data['userDetails']['birthdate']),
|
||||
dateFormController: TextEditingController(text: data['userDetails']['birthdate']),
|
||||
selectedCity: data['userDetails']['city'],
|
||||
selectedCountry: data['userDetails']['country'],
|
||||
selectedActivity: determineActivityLevel(
|
||||
@@ -282,6 +273,7 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
|
||||
var currentState = state as MyProfileLoadedState;
|
||||
|
||||
await uploadImageToServer(event.image.path, currentState.token);
|
||||
this.add(MyProfileInitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,27 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
SizedBox(height: 15.v),
|
||||
Container(
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildCarousel(context, state),
|
||||
),
|
||||
SizedBox(height: 15.v),
|
||||
if (!state.plans!.isEmpty)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 24.h,
|
||||
vertical: 12.v,
|
||||
@@ -112,32 +133,13 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildCarousel(context, state),),
|
||||
SizedBox(height: 15.v),
|
||||
if (!state.plans!.isEmpty)
|
||||
Container(
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _buildPlans(
|
||||
context,
|
||||
state.plans?.map((plan) => plan['name']).toList(),
|
||||
state.plans?.map((plan) => plan['image']).toList(),
|
||||
state.plans?.map((plan) => plan['state']).toList(),
|
||||
),),
|
||||
child: _buildPlans(
|
||||
context,
|
||||
state.plans?.map((plan) => plan['name']).toList(),
|
||||
state.plans?.map((plan) => plan['image']).toList(),
|
||||
state.plans?.map((plan) => plan['state']).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
],
|
||||
),
|
||||
@@ -176,11 +178,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
|
||||
addImage(BuildContext context) async {
|
||||
final picker = ImagePicker();
|
||||
List<XFile>? images = await picker.pickMultiImage();
|
||||
if (images.isNotEmpty) {
|
||||
for (var image in images) {
|
||||
context.read<MyProfileBloc>().add(UploadAvatar(image));
|
||||
}
|
||||
XFile? image = await picker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
context.read<MyProfileBloc>().add(UploadAvatar(image));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,8 +199,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
switch (chartType) {
|
||||
case 1: // График веса
|
||||
return GestureDetector(
|
||||
onTap: () => _editWeight(context, state),
|
||||
child: Column(children: [
|
||||
onTap: () => _editWeight(context, state),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"weight_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
@@ -213,26 +214,34 @@ class MyProfileScreen extends StatelessWidget {
|
||||
state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.chartDates,
|
||||
),
|
||||
],),);
|
||||
case 2: // График ИМТ
|
||||
return Column(children: [
|
||||
Text(
|
||||
"bodymass_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: appTheme.black900,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 50.v),
|
||||
_buildChart(
|
||||
);
|
||||
case 2: // График ИМТ
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
"bodymass_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: appTheme.black900,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 50.v),
|
||||
_buildChart(
|
||||
context,
|
||||
_bodyMassIndex(state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.userDetails?['height'].toInt() ?? 160,),
|
||||
state.chartDates,),
|
||||
],);
|
||||
_bodyMassIndex(
|
||||
state.chartPoints?.values.map<int>((e) => e['weight']).toList().map((i) => i.toDouble()).toList() ?? [0.0, 0.0, 0.0, 0.0],
|
||||
state.userDetails?['height'].toInt() ?? 160,
|
||||
),
|
||||
state.chartDates,
|
||||
),
|
||||
],
|
||||
);
|
||||
case 3: //График обхватов
|
||||
return GestureDetector(
|
||||
onTap: () => _editCircumference(context, state),
|
||||
child: Column(children: [
|
||||
onTap: () => _editCircumference(context, state),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"circumferences_chart".tr,
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
@@ -242,7 +251,9 @@ class MyProfileScreen extends StatelessWidget {
|
||||
SizedBox(height: 30.v),
|
||||
_buildCircumferenceChart(context, state.circumferences, state.chartDates),
|
||||
_buildChartLegend(),
|
||||
],),);
|
||||
],
|
||||
),
|
||||
);
|
||||
default:
|
||||
return Text('text', style: TextStyle(fontSize: 16.0));
|
||||
}
|
||||
@@ -636,79 +647,108 @@ class MyProfileScreen extends StatelessWidget {
|
||||
/// Section Widget
|
||||
_buildPlans(BuildContext context, List<dynamic>? plans, List<dynamic>? imagePaths, List<dynamic>? states) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(left: 7.h),
|
||||
child: Column(children: [
|
||||
padding: EdgeInsets.only(left: 7.h),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 15.h),
|
||||
child: Text("plans_complete".tr, style: CustomTextStyles.titleMediumBlack.copyWith(color: appTheme.black900)),),
|
||||
padding: EdgeInsets.only(left: 15.h),
|
||||
child: Text("plans_complete".tr, style: CustomTextStyles.titleMediumBlack.copyWith(color: appTheme.black900)),
|
||||
),
|
||||
SizedBox(height: 5.v),
|
||||
Container(
|
||||
decoration: AppDecoration.outlineBlueGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
decoration: AppDecoration.outlineBlueGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 105.v,
|
||||
width: 343.h,
|
||||
child: Stack(alignment: Alignment.bottomCenter, children: [
|
||||
height: 105.v,
|
||||
width: 343.h,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ListView.builder(
|
||||
itemCount: plans?.length ?? 0,
|
||||
itemBuilder: (context, i) {
|
||||
String state = states?[i];
|
||||
var boxColor = appTheme.greenA700;
|
||||
switch (states?[i]) {
|
||||
case 'active':
|
||||
boxColor = appTheme.greenA700;
|
||||
break;
|
||||
case 'archived': // График ИМТ
|
||||
boxColor = appTheme.gray400;
|
||||
break;
|
||||
case 'draft':
|
||||
boxColor = appTheme.deepOrange900;
|
||||
break;
|
||||
case 'in_progress': //График обхватов
|
||||
boxColor = appTheme.lightGreen300;
|
||||
break;
|
||||
}
|
||||
return SizedBox(
|
||||
height: 40.v,
|
||||
width: 343.h,
|
||||
child: Stack(alignment: Alignment.bottomRight, children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 11.v),
|
||||
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.v),
|
||||
decoration: AppDecoration.fillGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 1.v),
|
||||
child: Text(plans![i], style: CustomTextStyles.titleSmallBluegray800Bold),),
|
||||
Container(
|
||||
height: 19.v,
|
||||
width: 100.h,
|
||||
decoration: BoxDecoration(color: boxColor, borderRadius: BorderRadius.circular(5.h)),),
|
||||
],),),),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 12.h),
|
||||
child: Image.network(
|
||||
dotenv.env['STORAGE_URL']! + imagePaths?[i],
|
||||
height: 25.adaptSize,
|
||||
width: 25.adaptSize,
|
||||
),),),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 70.h,
|
||||
margin: EdgeInsets.only(bottom: 14.h, right: 22.h),
|
||||
child: Text("$state".tr, maxLines: 3, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleSmall),),),
|
||||
],),);
|
||||
},),),
|
||||
],),),
|
||||
],),),
|
||||
],),);
|
||||
alignment: Alignment.topCenter,
|
||||
child: ListView.builder(
|
||||
itemCount: plans?.length ?? 0,
|
||||
itemBuilder: (context, i) {
|
||||
String state = states?[i];
|
||||
var boxColor = appTheme.greenA700;
|
||||
switch (states?[i]) {
|
||||
case 'active':
|
||||
boxColor = appTheme.greenA700;
|
||||
break;
|
||||
case 'archived': // График ИМТ
|
||||
boxColor = appTheme.gray400;
|
||||
break;
|
||||
case 'draft':
|
||||
boxColor = appTheme.deepOrange900;
|
||||
break;
|
||||
case 'in_progress': //График обхватов
|
||||
boxColor = appTheme.lightGreen300;
|
||||
break;
|
||||
}
|
||||
return SizedBox(
|
||||
height: 40.v,
|
||||
width: 343.h,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 11.v),
|
||||
padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 4.v),
|
||||
decoration: AppDecoration.fillGray.copyWith(borderRadius: BorderRadiusStyle.roundedBorder5),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 1.v),
|
||||
child: Text(plans![i], style: CustomTextStyles.titleSmallBluegray800Bold),
|
||||
),
|
||||
Container(
|
||||
height: 19.v,
|
||||
width: 100.h,
|
||||
decoration: BoxDecoration(color: boxColor, borderRadius: BorderRadius.circular(5.h)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 12.h),
|
||||
child: Image.network(
|
||||
dotenv.env['STORAGE_URL']! + imagePaths?[i],
|
||||
height: 25.adaptSize,
|
||||
width: 25.adaptSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 70.h,
|
||||
margin: EdgeInsets.only(bottom: 14.h, right: 22.h),
|
||||
child: Text("$state".tr, maxLines: 3, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleSmall),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<double> _bodyMassIndex(List<double> weightPoints, int height) {
|
||||
@@ -729,48 +769,49 @@ class MyProfileScreen extends StatelessWidget {
|
||||
title: Center(child: Text("Добавить замер")),
|
||||
|
||||
content: SizedBox(
|
||||
width: 200, // Ширина диалогового окна
|
||||
height: 300, // Высота диалогового окна
|
||||
child: 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: <TextInputFormatter>[
|
||||
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: <TextInputFormatter>[
|
||||
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: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
],
|
||||
),),
|
||||
width: 200, // Ширина диалогового окна
|
||||
height: 300, // Высота диалогового окна
|
||||
child: 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: <TextInputFormatter>[
|
||||
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: <TextInputFormatter>[
|
||||
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: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly, // Ограничение ввода только цифрами
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: onTapOk(context),
|
||||
@@ -778,10 +819,12 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: sendEditData(state, context),
|
||||
child: Text("Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),),
|
||||
child: Text(
|
||||
"Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.white,
|
||||
@@ -824,6 +867,7 @@ class MyProfileScreen extends StatelessWidget {
|
||||
// Обработка ошибок при отправке запроса
|
||||
print("Ошибка при отправке запроса: $e");
|
||||
}
|
||||
Navigator.pop(context);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -859,10 +903,12 @@ class MyProfileScreen extends StatelessWidget {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => saveWeight(state, context),
|
||||
child: Text("Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),),
|
||||
child: Text(
|
||||
"Изменить",
|
||||
style: CustomTextStyles.titleMediumBlack.copyWith(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
backgroundColor: Colors.white,
|
||||
|
||||
Reference in New Issue
Block a user