import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:eatvio_app/core/widgets/custom_divider.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/core/widgets/main_background_bouble.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart'; import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart'; import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart'; import 'package:eatvio_app/features/create_plan/presentation/widgets/add_item_widget.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/flutter_svg.dart'; class OptionWidget extends StatefulWidget { const OptionWidget({super.key}); @override State createState() => _OptionWidgetState(); } class _OptionWidgetState extends State { final firstOptionCustomerPriceController = TextEditingController()..text = '1200₽'; final secondOptionCustomerPriceController = TextEditingController()..text = '1200₽'; final thirdOptionCustomerPriceController = TextEditingController()..text = '1200₽'; final creatorPriceController = TextEditingController()..text = '1000₽'; final firstOptionTitleController = TextEditingController(); final secondOptionTitleController = TextEditingController(); final thirdOptionTitleController = TextEditingController(); final firstOptionDescriptionController = TextEditingController(); final secondOptionDescriptionController = TextEditingController(); final thirdOptionDescriptionController = TextEditingController(); bool firstExplanationVisible = false; bool isChecked = false; bool secondExplanationVisible = false; @override void initState() { super.initState(); firstOptionCustomerPriceController.addListener(() { if (!firstOptionCustomerPriceController.text.endsWith('₽')) { final text = firstOptionCustomerPriceController.text.replaceAll('₽', ''); firstOptionCustomerPriceController.text = '$text₽'; firstOptionCustomerPriceController.selection = TextSelection.collapsed(offset: text.length); } }); secondOptionCustomerPriceController.addListener(() { if (!secondOptionCustomerPriceController.text.endsWith('₽')) { final text = secondOptionCustomerPriceController.text.replaceAll('₽', ''); secondOptionCustomerPriceController.text = '$text₽'; secondOptionCustomerPriceController.selection = TextSelection.collapsed(offset: text.length); } }); thirdOptionCustomerPriceController.addListener(() { if (!thirdOptionCustomerPriceController.text.endsWith('₽')) { final text = thirdOptionCustomerPriceController.text.replaceAll('₽', ''); thirdOptionCustomerPriceController.text = '$text₽'; thirdOptionCustomerPriceController.selection = TextSelection.collapsed(offset: text.length); } }); } @override Widget build(BuildContext context) { final s = S.of(context); return BlocBuilder( builder: (context, state) { final selectedOptionIndex = state.selectedOptionIndex ?? 0; final optionNameHintText = switch (selectedOptionIndex) { 0 => s.economy, 2 => s.comfort, _ => s.standard, }; final optionTitleController = switch (selectedOptionIndex) { 0 => firstOptionTitleController, 2 => thirdOptionTitleController, _ => secondOptionTitleController, }; final optionDescriptionController = switch (selectedOptionIndex) { 0 => firstOptionDescriptionController, 2 => thirdOptionDescriptionController, _ => secondOptionDescriptionController, }; final customerPriceController = switch (selectedOptionIndex) { 0 => firstOptionCustomerPriceController, 2 => thirdOptionCustomerPriceController, _ => secondOptionCustomerPriceController, }; final price = double.tryParse(customerPriceController.text.replaceAll('₽', '')); creatorPriceController.text = '${((price ?? 0) * 0.8).toStringAsFixed(2)}₽'; firstOptionTitleController.text = state.planData.options[selectedOptionIndex].short; firstOptionDescriptionController.text = state.planData.options[selectedOptionIndex].description ?? ''; return MainBackgroundBouble( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( s.option_title, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(height: 4), CustomTextFormField( hintText: optionNameHintText, hasError: state.validationState.optionsValidationState[state.selectedOptionIndex ?? 0].titleHasError, controller: optionTitleController, onChanged: (value) { context.read().setOptionTitle(value); }, maxLength: 150, ), if (state.validationState.optionsValidationState[state.selectedOptionIndex ?? 0].titleHasError) ...[ const SizedBox(height: 4), ValidationErrorWidget(error: s.atLeast3Symbols), ], const SizedBox(height: 12), Text( s.option_desc, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(height: 4), SizedBox( height: 120, child: CustomTextFormField( controller: optionDescriptionController, textAlignVertical: TextAlignVertical.top, hasError: state.validationState.optionsValidationState[state.selectedOptionIndex ?? 0].descriptionHasError, maxLength: 1000, minLines: null, maxLines: null, expands: true, hintText: s.option_desc_hint_text, onChanged: (value) { context.read().setOptionDescription(value); }, ), ), if (state.validationState.optionsValidationState[state.selectedOptionIndex ?? 0].descriptionHasError) ...[ const SizedBox(height: 4), ValidationErrorWidget(error: s.atLeast3Symbols), ], const SizedBox(height: 12), Row( children: [ Text( s.you_will_get, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(width: 4), const _PriceExplanationWidget(), ], ), const SizedBox(height: 4), CustomTextFormField( controller: creatorPriceController, readOnly: true, textStyle: TextStyle(color: appTheme.gray), maxLength: 20, ), const SizedBox(height: 12), Row( children: [ Text( s.customer_price, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(width: 4), const _PriceExplanationWidget(), ], ), const SizedBox(height: 4), CustomTextFormField( controller: customerPriceController, textInputType: const TextInputType.numberWithOptions(decimal: true), hasError: state.validationState.optionsValidationState[state.selectedOptionIndex ?? 0].priceHasError, onChanged: (value) { final price = double.tryParse(value.replaceAll('₽', '')); if (price != null) { context.read().setPrice(price); } }, maxLength: 20, ), const SizedBox(height: 10), Text( s.minimal_customer_price, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(height: 16), const CustomDivider(), const SizedBox(height: 16), Text( s.option_content, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.textSMedium.copyWith(color: appTheme.black), ), const SizedBox(height: 4), ListView.separated( padding: EdgeInsets.zero, separatorBuilder: (context, index) => const SizedBox(height: 8), reverse: false, itemBuilder: (context, index) { final items = state.planData.options[selectedOptionIndex].items; if (items.isEmpty) { return AddItemWidget( index: index, canBeDeleted: false, enableHint: true, items: items, ); } else { if (index < items.length) { return AddItemWidget( canBeDeleted: true, enableHint: false, index: index, items: items, ); } else { return AddItemWidget( canBeDeleted: false, enableHint: false, index: index, items: items, ); } } }, itemCount: state.planData.options[selectedOptionIndex].items.length + 1, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), ), const SizedBox(height: 16), const CustomDivider(), const SizedBox(height: 16), Row( children: [ Checkbox( value: state.planData.options[selectedOptionIndex].hasPersonalDiet, activeColor: appTheme.gray, checkColor: appTheme.gray, fillColor: const WidgetStatePropertyAll(Colors.transparent), side: WidgetStateBorderSide.resolveWith( (Set states) { return BorderSide(width: 1, color: appTheme.gray); }, ), onChanged: (bool? value) { context.read().togglePersonalizedDietOptionState(); }, ), Expanded( child: Text( s.option_personal_diet_desc, style: TextStyles.textMMedium.copyWith(color: appTheme.black), ), ), ], ), ], ), ); }, ); } } class _PriceExplanationWidget extends StatefulWidget { const _PriceExplanationWidget(); @override State<_PriceExplanationWidget> createState() => _PriceExplanationWidgetState(); } class _PriceExplanationWidgetState extends State<_PriceExplanationWidget> { bool visible = false; @override Widget build(BuildContext context) { final s = S.of(context); return PortalTarget( closeDuration: const Duration(milliseconds: 300), portalFollower: AnimatedContainer( padding: const EdgeInsets.all(10), duration: const Duration(milliseconds: 300), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: visible ? appTheme.black : Colors.transparent, ), child: AnimatedDefaultTextStyle( style: TextStyles.textMMediumAuto.copyWith( color: visible ? appTheme.whiteA700 : Colors.transparent, ), duration: const Duration(milliseconds: 300), child: Text( s.price_explanation, ), ), ), visible: visible, anchor: const Aligned( shiftToWithinBound: AxisFlag(x: true, y: true), follower: Alignment.bottomLeft, target: Alignment.topRight, ), child: GestureDetector( onTap: () { setState(() { visible = !visible; }); }, child: SvgPicture.asset('assets/icons/question_mark.svg', height: 12, width: 12), ), ); } }