import 'package:eatvio_app/common/widgets/markdown_editor.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/localization_utils.dart'; import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/core/widgets/main_background_bouble.dart'; import 'package:eatvio_app/core/widgets/show_error_dialog.dart'; import 'package:eatvio_app/core/widgets/success_published_diet_bottom_sheet.dart'; import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart'; import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/day_widget.dart'; import 'package:eatvio_app/features/create_diet/presentation/diet_preview_screen.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/diet_duration_drop_down_widget.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/diet_image_picker_widget.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/status_drop_down_widget.dart'; import 'package:eatvio_app/features/create_diet/presentation/widgets/diet_type_choice_widget.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; class CreateDietScreen extends StatelessWidget { static const name = 'createDietScreen'; static const path = '/create-diet-screen'; const CreateDietScreen({super.key, this.diet}); final Diet? diet; @override Widget build(BuildContext context) { return BlocProvider( create: (context) => sl()..setInitialData(diet), child: CreateDietScreenContent(diet: diet), ); } } class CreateDietScreenContent extends StatefulWidget { const CreateDietScreenContent({super.key, this.diet}); final Diet? diet; @override State createState() => _CreateDietScreenContentState(); } class _CreateDietScreenContentState extends State { final nameController = TextEditingController(); final descriptionController = TextEditingController(); final scaffoldKey = GlobalKey(); final GlobalKey _mdKey = GlobalKey(); bool _mdToolbarVisible = false; final GlobalKey _nameKey = GlobalKey(); final GlobalKey _durationKey = GlobalKey(); final GlobalKey _statusKey = GlobalKey(); final GlobalKey _typeKey = GlobalKey(); final GlobalKey _imageKey = GlobalKey(); final GlobalKey _planKey = GlobalKey(); void _scrollToFirstError(CreateDietState state) { GlobalKey? key; if (state.dietNameError != null) { key = _nameKey; } else if (state.dietDescriptionError != null) { key = _mdKey; } else if (state.dietDurationError != null) { key = _durationKey; } else if (state.dietStateError != null) { key = _statusKey; } else if (state.dietImageError != null) { key = _imageKey; } else if (state.dailyScheduleErrors.any((e) => e.isNotEmpty)) { key = _planKey; } if (key != null && key.currentContext != null) { Scrollable.ensureVisible( key.currentContext!, duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, alignment: 0.1, ); } } @override void initState() { super.initState(); if (widget.diet != null) { nameController.text = widget.diet?.name ?? ''; descriptionController.text = widget.diet?.details ?? ''; } } @override Widget build(BuildContext context) { final s = S.of(context); return BlocBuilder( builder: (context, state) { if (state.published) { Future.delayed(const Duration(milliseconds: 500), () { if (!context.mounted) return; context.pop(); showBottomSheetWithBlur( userRootNavigator: true, context: context, child: SuccessPublishedDietOrPlanBottomSheet(title: state.dietData.name ?? 'Диета'), ); }); } else if (state.drafted) { Future.delayed(const Duration(milliseconds: 500), () { if (!context.mounted) return; context.pop(); showBottomSheetWithBlur( context: context, child: SuccessPublishedDietOrPlanBottomSheet(title: '${state.dietData.name ?? 'Диета'} сохраненна в черновиках'), ); }); } return Scaffold( backgroundColor: appTheme.gray100, floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: _mdToolbarVisible && _mdKey.currentState != null ? _mdKey.currentState!.buildToolbar(context) : null, appBar: AppBar( centerTitle: true, title: Text( s.create_diet, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, softWrap: true, style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black), ), ), body: SingleChildScrollView( child: Column( children: [ const SizedBox(height: 8), MainBackgroundBouble( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 16), CustomTextFormField( key: _nameKey, hintText: s.enter_diet_name, controller: nameController, hasError: state.dietNameError != null, onChanged: (value) { context.read().setName(value); }, ), if (state.dietNameError != null) ...[const SizedBox(height: 4), ValidationErrorWidget(error: state.dietNameError ?? '')], const SizedBox(height: 12), MarkdownEditor( key: _mdKey, initialText: descriptionController.text, hintText: s.enter_diet_description, hasError: state.dietDescriptionError != null, minLines: 6, maxLines: 8, showInlineToolbar: false, onToolbarVisibilityChanged: (v) => setState(() => _mdToolbarVisible = v), onChanged: (value) { descriptionController.text = value; context.read().setDetails(value); }, ), if (state.dietDescriptionError != null) ...[const SizedBox(height: 4), ValidationErrorWidget(error: state.dietDescriptionError ?? '')], const SizedBox(height: 12), DietDurationDropDownWidget(key: _durationKey), const SizedBox(height: 12), StatusDropDownWidget(key: _statusKey, dietState: widget.diet?.state), const SizedBox(height: 16), DietTypeChoiceWidget(key: _typeKey), const SizedBox(height: 16), DietImagePickerWidget(key: _imageKey), const SizedBox(height: 16), ], ), ), const SizedBox(height: 16), MainBackgroundBouble( key: _planKey, child: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Center( child: Text( '${s.diet_plan} (${state.dietData.duration ?? 0} ${getDayForm(state.dietData.duration ?? 0, s)})', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black), ), ), ), ), const SizedBox(height: 8), ListView.separated( padding: const EdgeInsets.all(0), itemBuilder: (context, index) => DayWidget(index: index), itemCount: state.dietData.dailySchedule?.length ?? 0, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), separatorBuilder: (context, index) => const SizedBox(height: 8), ), const SizedBox(height: 12), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: [ CustomOutlinedButton( onPressed: state.isDietPublishing ? () {} : () async { final diet = await context.read().getDietForPreview(); if (diet == null) { // ignore: use_build_context_synchronously _scrollToFirstError(context.read().state); return; } if (!context.mounted) return; GoRouter.of(context).pushNamed(DietPreviewScreen.name, extra: diet); }, text: s.preview, height: 52, buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray), buttonStyle: ButtonStyle( side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.dottedBorder), ), ), const SizedBox(height: 12), if (state.isDietPublishing) const Loader() else CustomOutlinedButton( onPressed: () async { final result = await context.read().createDiet(); if (result == 'validation') { // ignore: use_build_context_synchronously _scrollToFirstError(context.read().state); } else if (result == 'error') { if (!context.mounted) return; showErrorDialog(context, title: '${s.could_not_publish_diet} ${state.dietData.name}'); } }, text: s.publish, height: 52, buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), buttonStyle: ButtonStyle( side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400), ), ), ], ), ), const SizedBox(height: 20), ], ), ), ); }, ); } }