forked from eatvio/eatvio_app
feat(diet): add diet editing
This commit is contained in:
@@ -6,7 +6,9 @@ import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
|
||||
@@ -28,6 +30,7 @@ class CustomPopup extends StatelessWidget {
|
||||
final int? id;
|
||||
final FeedBlogPostModel? feedBlogPostModel;
|
||||
final Recipe? recipe;
|
||||
final Diet? diet;
|
||||
|
||||
const CustomPopup({
|
||||
super.key,
|
||||
@@ -38,6 +41,7 @@ class CustomPopup extends StatelessWidget {
|
||||
this.slug,
|
||||
this.feedBlogPostModel,
|
||||
this.recipe,
|
||||
this.diet,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -94,11 +98,15 @@ class CustomPopup extends StatelessWidget {
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
});
|
||||
addItem('assets/icons/edit_paint.svg', 'Редактировать', () {
|
||||
addItem('assets/icons/edit_paint.svg', 'Редактировать', () async {
|
||||
if (complainedContentType == ComplainedContent.posts) {
|
||||
GoRouter.of(context).pushNamed('blogPostCreateScreen', extra: feedBlogPostModel);
|
||||
} else if (complainedContentType == ComplainedContent.recipe) {
|
||||
GoRouter.of(context).pushNamed(RecipeCreateScreen.name, extra: recipe);
|
||||
} else if (complainedContentType == ComplainedContent.diet) {
|
||||
await showErrorDialog(context, title: 'Предупреждение', description: 'Диета будет перенесена в архив. Вы создаете новую диету на основе существующей.');
|
||||
await sl<MyDietsCubit>().unpublishDiet(id!);
|
||||
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: diet);
|
||||
} else {
|
||||
showInfoToast('В разработке');
|
||||
return;
|
||||
|
||||
@@ -5,8 +5,8 @@ import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
void showErrorDialog(BuildContext context, {String? title, String? description}) {
|
||||
showDialog<void>(
|
||||
Future<void> showErrorDialog(BuildContext context, {String? title, String? description}) async {
|
||||
return await showDialog<void>(
|
||||
context: context,
|
||||
barrierColor: Colors.transparent,
|
||||
builder: (BuildContext context) {
|
||||
|
||||
@@ -27,8 +27,11 @@ 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(
|
||||
@@ -40,6 +43,7 @@ class CreateDietScreen extends StatelessWidget {
|
||||
|
||||
class CreateDietScreenContent extends StatefulWidget {
|
||||
const CreateDietScreenContent({super.key, this.diet});
|
||||
|
||||
final Diet? diet;
|
||||
|
||||
@override
|
||||
@@ -95,7 +99,7 @@ class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.diet != null ? 'Редактирование диеты' : s.create_diet,
|
||||
s.create_diet,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
@@ -151,7 +155,7 @@ class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
|
||||
const SizedBox(height: 12),
|
||||
const DietDurationDropDownWidget(),
|
||||
const SizedBox(height: 12),
|
||||
const StatusDropDownWidget(),
|
||||
StatusDropDownWidget(dietState: widget.diet?.state),
|
||||
const SizedBox(height: 16),
|
||||
const DietTypeChoiceWidget(),
|
||||
const SizedBox(height: 16),
|
||||
@@ -247,23 +251,13 @@ class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
|
||||
else
|
||||
CustomOutlinedButton(
|
||||
onPressed: () async {
|
||||
if (widget.diet != null) {
|
||||
final result = await context.read<CreateDietCubit>().updateDiet(
|
||||
widget.diet!.id,
|
||||
);
|
||||
if (result == 'error') {
|
||||
if (!context.mounted) return;
|
||||
showErrorDialog(context, title: '${s.could_not_update_diet} ${state.dietData.name}');
|
||||
}
|
||||
} else {
|
||||
final result = await context.read<CreateDietCubit>().createDiet();
|
||||
if (result == 'error') {
|
||||
if (!context.mounted) return;
|
||||
showErrorDialog(context, title: '${s.could_not_publish_diet} ${state.dietData.name}');
|
||||
}
|
||||
final result = await context.read<CreateDietCubit>().createDiet();
|
||||
if (result == 'error') {
|
||||
if (!context.mounted) return;
|
||||
showErrorDialog(context, title: '${s.could_not_publish_diet} ${state.dietData.name}');
|
||||
}
|
||||
},
|
||||
text: widget.diet != null ? s.save : s.publish,
|
||||
text: s.publish,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
|
||||
@@ -12,6 +12,8 @@ import 'package:eatvio_app/features/glossary/repositories/glossary_repository.da
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
final CreateDietRepository createDietRepository;
|
||||
@@ -319,18 +321,38 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
return diet;
|
||||
}
|
||||
|
||||
Future<File> downloadImageAsFile(String imageUrl) async {
|
||||
final response = await http.get(Uri.parse(imageUrl));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final filePath = '${tempDir.path}/${imageUrl.split('/').last}';
|
||||
final file = File(filePath);
|
||||
return await file.writeAsBytes(response.bodyBytes);
|
||||
} else {
|
||||
throw Exception('Не удалось загрузить изображение');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> createDiet() async {
|
||||
emit(state.copyWith(isDietPublishing: true));
|
||||
if (!_isFromValid()) return 'validation';
|
||||
try {
|
||||
final image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
File? file;
|
||||
if (state.dietData.imageUrl != null) {
|
||||
file = await downloadImageAsFile(state.dietData.imageUrl!);
|
||||
}
|
||||
File? image;
|
||||
if (state.dietData.image?.path != null) {
|
||||
image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
}
|
||||
final dietState = state.dietData.state!;
|
||||
final dailySchedule = state.dietData.dailySchedule;
|
||||
await createDietRepository.createDiet(
|
||||
name: state.dietData.name ?? '',
|
||||
duration: state.dietData.duration ?? 7,
|
||||
state: dietState,
|
||||
image: image,
|
||||
image: image ?? file!,
|
||||
meatType: state.dietData.type['meat'] == true ? '1' : '0',
|
||||
carbType: state.dietData.type['carb'] == true ? '1' : '0',
|
||||
vegType: state.dietData.type['veg'] == true ? '1' : '0',
|
||||
|
||||
@@ -11,7 +11,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class StatusDropDownWidget extends StatefulWidget {
|
||||
const StatusDropDownWidget({super.key});
|
||||
final DietState? dietState;
|
||||
|
||||
const StatusDropDownWidget({super.key, this.dietState});
|
||||
|
||||
@override
|
||||
State<StatusDropDownWidget> createState() => _StatusDropDownWidgetState();
|
||||
@@ -19,6 +21,7 @@ class StatusDropDownWidget extends StatefulWidget {
|
||||
|
||||
class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
|
||||
final List<String> dietStateTitles = [];
|
||||
String? currentState;
|
||||
// late final List<DietState> dietStates = DietState.values;
|
||||
|
||||
@override
|
||||
@@ -39,6 +42,13 @@ class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
|
||||
// }
|
||||
// }
|
||||
}
|
||||
if (widget.dietState != null) {
|
||||
if (widget.dietState == DietState.active) {
|
||||
currentState = dietStateTitles[0];
|
||||
} else if (widget.dietState == DietState.personal) {
|
||||
currentState = dietStateTitles[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -77,7 +87,7 @@ class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: state.dietState == DietState.active ? dietStateTitles[0] : state.dietState == DietState.personal ? dietStateTitles[1] : null,
|
||||
value: currentState,
|
||||
),
|
||||
if (state.dietStateError != null) ...[
|
||||
const SizedBox(
|
||||
|
||||
@@ -321,6 +321,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
diet: widget.diet,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
@@ -501,6 +502,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
diet: widget.diet,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
@@ -527,6 +529,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
diet: widget.diet,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
|
||||
@@ -42,7 +42,7 @@ class Diet with _$Diet {
|
||||
enum DietState {
|
||||
@JsonKey(name: 'active')
|
||||
active,
|
||||
@JsonKey(name: 'draft')
|
||||
@JsonKey(name: 'drafted')
|
||||
draft,
|
||||
@JsonKey(name: 'personal')
|
||||
personal;
|
||||
@@ -53,7 +53,7 @@ enum DietState {
|
||||
case DietState.active:
|
||||
return 'active';
|
||||
case DietState.draft:
|
||||
return 'draft';
|
||||
return 'drafted';
|
||||
case DietState.personal:
|
||||
return 'personal';
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ class _DietsWidgetState extends State<DietsWidget> {
|
||||
path: 'diet/${widget.diet.id}',
|
||||
id: widget.diet.id,
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
diet: widget.diet,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:eatvio_app/core/utils/toasts.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/info_row.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/create_diet_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
@@ -194,6 +195,7 @@ class _MyDietWidgetState extends State<MyDietWidget> {
|
||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||
}
|
||||
} else {
|
||||
await showErrorDialog(context, title: 'Предупреждение', description: 'Вы можете создать новую диету на основе существующей.');
|
||||
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user