import 'package:eatvio_app/core/enums/complained_content.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/core/utils/date_time_utils.dart'; import 'package:eatvio_app/core/utils/string_extentions.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart'; import 'package:eatvio_app/features/profile/models/circumference_model.dart'; import 'package:eatvio_app/features/profile/models/weight_model.dart'; import 'package:eatvio_app/features/profile/presentation/widgets/circumference_chart_widget.dart'; import 'package:eatvio_app/features/profile/presentation/widgets/imt_chart_widget.dart'; import 'package:eatvio_app/features/profile/presentation/widgets/weight_chart_widget.dart'; import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart'; import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_state.dart'; import 'package:eatvio_app/features/user_details/presentation/widgets/expandable_bouble.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_svg/svg.dart'; class UserDetailsScreen extends StatelessWidget { final String slug; const UserDetailsScreen({super.key, required this.slug}); static const name = 'userDetailsScreen'; static const path = '/user-details-screen'; @override Widget build(BuildContext context) { return BlocProvider( create: (context) => sl()..getUserDetails(slug), child: UserDetailsContent( slug: slug, ), ); } } class UserDetailsContent extends StatefulWidget { const UserDetailsContent({super.key, required this.slug}); final String slug; @override State createState() => _UserDetailsContentState(); } class _UserDetailsContentState extends State { final List chipsLabelList = ['Вес', 'Замеры', 'ИМТ']; final List chipsIntervalLabelList = ['1М', '3М', '6М', '1Г', 'ВСЁ ВРЕМЯ']; final List chipsIntervalList = ['1', '3', '6', '12', 'all']; List weightPoints = []; List circumferencePoints = []; int _selectedChipIndex = 0; int _selectedIntervalChipIndex = 0; bool isMoreOptionsVisible = false; @override Widget build(BuildContext context) { final s = S.of(context); return BlocBuilder( builder: (context, state) { final profileDetails = state.profileDetails; if (profileDetails != null && state.isLoading == false) { weightPoints = state.weightPoints ?? []; circumferencePoints = state.circumferencePoints ?? []; return Scaffold( backgroundColor: appTheme.gray100, appBar: AppBar( centerTitle: true, title: Text( '${s.user_data} ${profileDetails.firstName} ${profileDetails.lastName}', maxLines: 2, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black), ), actions: [ PortalTarget( visible: isMoreOptionsVisible, portalFollower: MoreOptions( path: 'profile/${widget.slug}', complainedContentType: ComplainedContent.profile, slug: widget.slug, ), anchor: Aligned( shiftToWithinBound: AxisFlag(x: true, y: true), follower: Alignment.topRight, target: Alignment.bottomRight, ), child: IconButton( onPressed: () { setState(() { isMoreOptionsVisible = !isMoreOptionsVisible; }); }, icon: SvgPicture.asset( 'assets/icons/more_button.svg', width: 20, height: 20, ), ), ), ], ), body: SingleChildScrollView( controller: ScrollController() ..addListener(() { setState(() { isMoreOptionsVisible = false; }); }), child: Column( mainAxisAlignment: MainAxisAlignment.start, spacing: 12, children: [ SizedBox.shrink(), _charts(), ExpandableBouble( initiallyExpanded: true, title: s.general_info, children: [ Text( s.date_of_birth, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: DateTime.parse(profileDetails.birthdate).format('dd.MM.yyyy')), ), SizedBox(height: 16), Text( s.sex, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.gender.parseGender()), ), SizedBox(height: 16), ], ), ExpandableBouble( title: s.physical_fitness, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.height, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.height.toString()), ), ], ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.weight, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.weight.toStringAsFixed(0)), ), ], ), ), ], ), SizedBox(height: 16), Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.chest_circumference, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.chestCircumference.toString()), ), ], ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.waist_circumference, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.waistCircumference.toString()), ), ], ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.hip_circumference, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.hipCircumference.toString()), ), ], ), ), ], ), SizedBox(height: 16), ], ), ExpandableBouble( title: s.pressure, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.upper, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.bloodPressureUp.toString()), ), ], ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.lower, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.bloodPressureDown.toStringAsFixed(0)), ), ], ), ), ], ), SizedBox(height: 16), Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.has_hypo, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.hasHypo.toString()), ), ], ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.has_hyper, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.hasHyper.toString()), ), ], ), ), ], ), SizedBox(height: 16), ], ), ExpandableBouble( title: s.other_info, children: [ Text( s.has_alergy, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.aboutAlergy), ), SizedBox(height: 16), Text( s.takes_pills, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.aboutTakingPils), ), SizedBox(height: 16), Text( s.sport_hobbies, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.aboutSportHobbies), ), SizedBox(height: 16), Text( s.liked_groceries, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.favoriteFoods), ), SizedBox(height: 16), Text( s.not_liked_groceries, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), CustomTextFormField( readOnly: true, controller: TextEditingController(text: profileDetails.unfavoriteFoods), ), SizedBox(height: 16), Text( s.additional_information, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), SizedBox(height: 4), SizedBox( height: 112, child: CustomTextFormField( readOnly: true, maxLength: 1000, maxLines: null, minLines: null, expands: true, textAlignVertical: TextAlignVertical.top, controller: TextEditingController(text: profileDetails.additionalInfo), ), ), SizedBox(height: 16), ], ), ], ), ), ); } else if (state.error != null) { return Scaffold( appBar: AppBar(), body: DataErrorWidget( onReload: () async { context.read().getUserDetails(widget.slug); }, ), ); } return Scaffold( appBar: AppBar(), body: Loader(), ); }, ); } _charts() { return Material( color: Colors.white, borderRadius: BorderRadius.circular(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 8), SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 16), scrollDirection: Axis.horizontal, child: Row( children: [ _choiceChipWidget(0), SizedBox(width: 8), _choiceChipWidget(1), SizedBox(width: 8), _choiceChipWidget(2), ], ), ), Builder( builder: (context) { switch (_selectedChipIndex) { case 0: return WeightChartWidget( weightPoints: weightPoints, ); case 1: return CircumferenceChartWidget( circumferencePoints: circumferencePoints, ); case 2: return ImtChartWidget( weightPoints: weightPoints, ); default: return SizedBox.shrink(); } }, ), SizedBox(height: 8), Row( children: [ SizedBox(width: 16), _choiceIntervalChipWidget(0), SizedBox(width: 8), _choiceIntervalChipWidget(1), SizedBox(width: 8), _choiceIntervalChipWidget(2), SizedBox(width: 8), _choiceIntervalChipWidget(3), SizedBox(width: 8), _choiceIntervalChipWidget(4), ], ), SizedBox(height: 8), ], ), ); } _choiceIntervalChipWidget(int index) { return ChoiceChip( selectedColor: Colors.grey.withValues(alpha: 0.1), pressElevation: 0, showCheckmark: false, side: BorderSide.none, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), label: Text(chipsIntervalLabelList[index]), labelStyle: TextStyle( color: appTheme.gray600, fontWeight: FontWeight.w500, fontSize: 12, ), selected: _selectedIntervalChipIndex == index, onSelected: (bool selected) { context.read().getChartData(period: chipsIntervalList[index], slug: widget.slug); setState(() { _selectedIntervalChipIndex = index; }); }, ); } _choiceChipWidget(int index) { return ChoiceChip( selectedColor: appTheme.blueA400, pressElevation: 0, showCheckmark: false, side: BorderSide.none, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), label: Text(chipsLabelList[index]), labelStyle: TextStyle( color: index == _selectedChipIndex ? Colors.white : appTheme.gray600, fontWeight: FontWeight.w500, fontSize: 12, ), selected: _selectedChipIndex == index, backgroundColor: appTheme.gray100, onSelected: (bool selected) { setState(() { _selectedChipIndex = index; }); }, ); } }