fixed profile, recipeis and diets

This commit is contained in:
Username1548
2025-02-10 21:50:13 +07:00
parent 5ea3264474
commit 070d7e1047
51 changed files with 1382 additions and 1360 deletions

View File

@@ -6,6 +6,7 @@ import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.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/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
@@ -16,6 +17,7 @@ import 'package:eatvio_app/features/create_diet/presentation/widgets/diet_image_
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';
@@ -24,19 +26,37 @@ 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});
const CreateDietScreen({super.key, this.diet});
final Diet? diet;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => sl<CreateDietCubit>(),
child: const CreateDietScreenContent(),
create: (context) => sl<CreateDietCubit>()..setInitialData(diet),
child: CreateDietScreenContent(diet: diet),
);
}
}
class CreateDietScreenContent extends StatelessWidget {
const CreateDietScreenContent({super.key});
class CreateDietScreenContent extends StatefulWidget {
CreateDietScreenContent({super.key, this.diet});
final Diet? diet;
@override
State<CreateDietScreenContent> createState() => _CreateDietScreenContentState();
}
class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
final nameController = TextEditingController();
final descriptionController = TextEditingController();
@override
void initState() {
super.initState();
if (widget.diet != null) {
nameController.text = widget.diet?.name ?? '';
descriptionController.text = widget.diet?.details ?? '';
}
}
@override
Widget build(BuildContext context) {
@@ -44,55 +64,12 @@ class CreateDietScreenContent extends StatelessWidget {
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
if (state.published) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.pop();
showBottomSheetWithBlur(
context: context,
child: Column(
children: [
SizedBox(
height: 20,
),
BottomSheetHandlerBar(),
SizedBox(
height: 20,
),
Text(
'${state.dietData.name ?? 'Диета'}',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
Text(
'опубликованна',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: CustomOutlinedButton(
onPressed: () {
context.pop();
},
text: 'Хорошо',
height: 52,
buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
),
),
),
SizedBox(
height: 20,
),
],
),
);
Future.delayed(Duration(milliseconds: 500), () {
context.pop('${state.dietData.name ?? 'Диета'}');
});
} else if (state.drafted) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.pop();
Future.delayed(Duration(milliseconds: 500), () {
context.pop('${state.dietData.name ?? 'Диета'}');
showBottomSheetWithBlur(
context: context,
child: Column(
@@ -116,7 +93,7 @@ class CreateDietScreenContent extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: CustomOutlinedButton(
onPressed: () {
context.pop();
Navigator.of(context, rootNavigator: true).pop();
},
text: 'Хорошо',
height: 52,
@@ -141,7 +118,7 @@ class CreateDietScreenContent extends StatelessWidget {
appBar: AppBar(
centerTitle: true,
title: Text(
s.create_diet,
widget.diet != null ? 'Редактирование диеты' : s.create_diet,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
@@ -160,6 +137,7 @@ class CreateDietScreenContent extends StatelessWidget {
SizedBox(height: 16),
CustomTextFormField(
hintText: s.enter_diet_name,
controller: nameController,
hasError: state.dietNameError != null,
onChanged: (value) {
context.read<CreateDietCubit>().setName(value);
@@ -176,6 +154,7 @@ class CreateDietScreenContent extends StatelessWidget {
height: 132,
child: CustomTextFormField(
hasError: state.dietDescriptionError != null,
controller: descriptionController,
textAlignVertical: TextAlignVertical.top,
maxLines: null,
minLines: null,
@@ -227,30 +206,19 @@ class CreateDietScreenContent extends StatelessWidget {
physics: NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) => SizedBox(height: 8),
),
SizedBox(height: 20),
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: [
CustomOutlinedButton(
onPressed: () async {
await context.read<CreateDietCubit>().publishDiet(toDraft: true);
},
text: s.to_draft,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.dottedBorder),
),
),
SizedBox(height: 12),
CustomOutlinedButton(
onPressed: () async {
final diet = await context.read<CreateDietCubit>().getDietForPreview();
if (diet == null) return;
GoRouter.of(context).pushNamed(DietPreviewScreen.name, extra: diet);
},
onPressed: state.isDietPublishing
? () {}
: () async {
final diet = await context.read<CreateDietCubit>().getDietForPreview();
if (diet == null) return;
GoRouter.of(context).pushNamed(DietPreviewScreen.name, extra: diet);
},
text: s.preview,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray),
@@ -260,18 +228,21 @@ class CreateDietScreenContent extends StatelessWidget {
),
),
SizedBox(height: 12),
CustomOutlinedButton(
onPressed: () {
context.read<CreateDietCubit>().publishDiet();
},
text: s.publish,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
if (state.isDietPublishing)
Loader()
else
CustomOutlinedButton(
onPressed: () {
context.read<CreateDietCubit>().publishDiet();
},
text: widget.diet != null ? s.save : s.publish,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
),
),
),
],
),
),
@@ -282,5 +253,5 @@ class CreateDietScreenContent extends StatelessWidget {
);
},
);
}
}
}

View File

@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
@@ -16,10 +17,46 @@ class CreateDietCubit extends Cubit<CreateDietState> {
final CreateDietRepository createDietRepository;
final ProfileRepository profileRepository;
final GlossaryRepository glossaryRepository;
static const _dietStateValues = ['active', 'personal', 'draft'];
String? tempImagePath;
static const _dietStateValues = DietState.values;
CreateDietCubit({required this.profileRepository, required this.createDietRepository, required this.glossaryRepository}) : super(CreateDietState.initial());
Future<void> setInitialData(Diet? diet) async {
if (diet == null) return;
emit(state.copyWith(isLoading: true, isDietBeingEdited: true));
final countOfDays = diet.dailySchedule.length;
final List<List<List<DailySchedule>>> dailySchedule = List.generate(countOfDays, (index) => [[], [], [], [], []]);
for (final dayEntry in diet.dailySchedule.entries) {
for (final mealEntry in dayEntry.value.entries) {
for (final product in mealEntry.value.values) {
dailySchedule[dayEntry.key - 1][mealEntry.key - 1].add(product);
}
}
}
final dietStateIndex = _dietStateValues.indexOf(diet.state);
final type = Map<String, bool>.fromIterable(dietTypeValues, value: (element) => false);
type['meat'] = diet.type.meat ?? false;
type['veg'] = diet.type.veg ?? false;
type['carb'] = diet.type.carb ?? false;
type['light'] = diet.type.light ?? false;
emit(
state.copyWith.dietData(
dailySchedule: dailySchedule,
details: diet.details,
state: diet.state,
name: diet.name,
duration: diet.duration,
type: type,
imageUrl: baseUrl + '/storage/' + diet.image,
),
);
emit(state.copyWith(dietStateIndex: dietStateIndex, durationIndex: durationValues.indexOf(diet.duration)));
emit(state.copyWith(isLoading: true));
}
void setDetails(String text) {
emit(state.copyWith(dietData: state.dietData.copyWith(details: text), dietDescriptionError: null));
}
@@ -82,16 +119,16 @@ class CreateDietCubit extends Cubit<CreateDietState> {
return await glossaryRepository.getGlossaryListByQuery(query);
}
void setImage(XFile? image) {
emit(state.copyWith(dietData: state.dietData.copyWith(image: image), dietImageError: null));
void setImage(XFile? image, {String? imageUrl}) {
emit(state.copyWith(dietData: state.dietData.copyWith(image: image, imageUrl: imageUrl), dietImageError: null));
}
void setDailySchedule(List<List<List<DailySchedule>>> dailySchedule) {
emit(state.copyWith(dietData: state.dietData.copyWith(dailySchedule: dailySchedule), dietDurationError: null));
}
void setDietState(int index) {
emit(state.copyWith(dietStateIndex: index, dietData: state.dietData.copyWith(state: _dietStateValues[index]), dietStateError: null));
void setDietState(DietState dietState, int index) {
emit(state.copyWith(dietData: state.dietData.copyWith(state: dietState), dietStateIndex: index, dietStateError: null));
}
void setDietType({required String key, required bool value}) {
@@ -236,12 +273,26 @@ class CreateDietCubit extends Cubit<CreateDietState> {
);
}
}
final dailySchedule = <int, Map<int, Map<int, DailySchedule>>>{};
for (final (dayIndex, day) in state.dietData.dailySchedule!.indexed) {
final mappedDay = <int, Map<int, DailySchedule>>{};
for (final (mealIndex, meal) in day.indexed) {
final mappedMeal = <int, DailySchedule>{};
for (final (productIndex, product) in meal.indexed) {
mappedMeal[productIndex + 1] = product;
}
mappedDay[mealIndex + 1] = mappedMeal;
}
dailySchedule[dayIndex + 1] = mappedDay;
}
final diet = Diet(
id: 0,
name: state.dietData.name ?? '',
image: imageInBase64,
duration: state.dietData.duration ?? 0,
state: state.dietData.state ?? '',
state: state.dietData.state ?? DietState.active,
type: DietType(
meat: state.dietData.type['meat'],
veg: state.dietData.type['veg'],
@@ -249,7 +300,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
light: state.dietData.type['light'],
),
details: state.dietData.details ?? '',
dailySchedule: state.dietData.dailySchedule ?? [],
dailySchedule: dailySchedule,
author: Author(
authorSlug: authorProfile.slug,
authorName: authorProfile.name,
@@ -267,32 +318,32 @@ class CreateDietCubit extends Cubit<CreateDietState> {
return diet;
}
Future<String?> publishDiet({bool toDraft = false}) async {
Future<String?> publishDiet() async {
emit(state.copyWith(isDietPublishing: true));
if (!_isFromValid()) return null;
try {
final image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
final dietState = toDraft ? _dietStateValues.last : state.dietData.state;
final diet = await createDietRepository.createDiet(
name: state.dietData.name,
duration: state.dietData.duration,
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,
meatType: state.dietData.type['meat'] == true ? '1' : '0',
carbType: state.dietData.type['carb'] == true ? '1' : '0',
vegType: state.dietData.type['veg'] == true ? '1' : '0',
lightType: state.dietData.type['light'] == true ? '1' : '0',
details: state.dietData.details,
details: state.dietData.details ?? '',
dailySchedule: dailySchedule ?? [],
);
final dailySchedule = state.dietData.dailySchedule;
createDietRepository.createDietDailySchedule(
id: diet.id,
model: {'daily_schedule': dailySchedule},
);
emit(state.copyWith(published: !toDraft, drafted: toDraft));
emit(state.copyWith(published: dietState != DietState.draft, drafted: dietState == DietState.draft));
return state.dietData.name;
} catch (e, stackTrace) {
} on DioException catch (e, stackTrace) {
log(e.toString(), stackTrace: stackTrace);
}
emit(state.copyWith(isDietPublishing: false));
return null;
}
@@ -336,15 +387,11 @@ class CreateDietCubit extends Cubit<CreateDietState> {
if (dailySchedule == null) {
result = false;
} else {
final dailyScheduleErrors = state.dailyScheduleErrors.map((element) {
return element.map((element) => element).toList();
}).toList();
final dailyScheduleErrors = [...state.dailyScheduleErrors];
for (final (dayIndex, day) in dailySchedule.indexed) {
for (final (mealIndex, meal) in day.indexed) {
if (meal.isEmpty) {
result = false;
dailyScheduleErrors[dayIndex][mealIndex] = 'Добавьте продукты';
}
if (day.every((meal) => meal.isEmpty)) {
result = false;
dailyScheduleErrors[dayIndex] = 'Добавьте продукты';
}
}
emit(state.copyWith(dailyScheduleErrors: dailyScheduleErrors));
@@ -358,16 +405,13 @@ class CreateDietCubit extends Cubit<CreateDietState> {
if (dailySchedule == null) {
result = false;
} else {
final dailyScheduleErrors = state.dailyScheduleErrors.map((element) {
return element.map((element) => element).toList();
}).toList();
for (final (mealIndex, meal) in dailySchedule[dayIndex].indexed) {
if (meal.isEmpty) {
result = false;
dailyScheduleErrors[dayIndex][mealIndex] = 'Добавьте продукты';
} else {
dailyScheduleErrors[dayIndex][mealIndex] = '';
}
final dailyScheduleErrors = [...state.dailyScheduleErrors];
final day = dailySchedule[dayIndex];
if (day.every((meal) => meal.isEmpty)) {
result = false;
dailyScheduleErrors[dayIndex] = 'Добавьте продукты';
} else {
dailyScheduleErrors[dayIndex] = '';
}
emit(state.copyWith(dailyScheduleErrors: dailyScheduleErrors));
}

View File

@@ -9,6 +9,7 @@ part 'create_diet_state.freezed.dart';
class CreateDietState with _$CreateDietState {
const factory CreateDietState({
required bool isLoading,
required bool isDietPublishing,
required String? errorMessage,
required CreateDietModel dietData,
List<List<DailySchedule>>? copiedDay,
@@ -17,15 +18,17 @@ class CreateDietState with _$CreateDietState {
String? dietDurationError,
String? dietStateError,
String? dietImageError,
required List<List<String>> dailyScheduleErrors,
required List<String> dailyScheduleErrors,
int? durationIndex,
int? dietStateIndex,
@Default(false) bool published,
@Default(false) bool drafted,
@Default(false) bool isDietBeingEdited,
}) = _CreateDietState;
factory CreateDietState.initial() => CreateDietState(
dailyScheduleErrors: List.filled(21, ['', '', '', '', '']),
dailyScheduleErrors: List.filled(21, ''),
isDietPublishing: false,
isLoading: false,
errorMessage: null,
dietData: CreateDietModel(

View File

@@ -17,6 +17,7 @@ final _privateConstructorUsedError = UnsupportedError(
/// @nodoc
mixin _$CreateDietState {
bool get isLoading => throw _privateConstructorUsedError;
bool get isDietPublishing => throw _privateConstructorUsedError;
String? get errorMessage => throw _privateConstructorUsedError;
CreateDietModel get dietData => throw _privateConstructorUsedError;
List<List<DailySchedule>>? get copiedDay =>
@@ -26,12 +27,12 @@ mixin _$CreateDietState {
String? get dietDurationError => throw _privateConstructorUsedError;
String? get dietStateError => throw _privateConstructorUsedError;
String? get dietImageError => throw _privateConstructorUsedError;
List<List<String>> get dailyScheduleErrors =>
throw _privateConstructorUsedError;
List<String> get dailyScheduleErrors => throw _privateConstructorUsedError;
int? get durationIndex => throw _privateConstructorUsedError;
int? get dietStateIndex => throw _privateConstructorUsedError;
bool get published => throw _privateConstructorUsedError;
bool get drafted => throw _privateConstructorUsedError;
bool get isDietBeingEdited => throw _privateConstructorUsedError;
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.
@@ -48,6 +49,7 @@ abstract class $CreateDietStateCopyWith<$Res> {
@useResult
$Res call(
{bool isLoading,
bool isDietPublishing,
String? errorMessage,
CreateDietModel dietData,
List<List<DailySchedule>>? copiedDay,
@@ -56,11 +58,12 @@ abstract class $CreateDietStateCopyWith<$Res> {
String? dietDurationError,
String? dietStateError,
String? dietImageError,
List<List<String>> dailyScheduleErrors,
List<String> dailyScheduleErrors,
int? durationIndex,
int? dietStateIndex,
bool published,
bool drafted});
bool drafted,
bool isDietBeingEdited});
$CreateDietModelCopyWith<$Res> get dietData;
}
@@ -81,6 +84,7 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
@override
$Res call({
Object? isLoading = null,
Object? isDietPublishing = null,
Object? errorMessage = freezed,
Object? dietData = null,
Object? copiedDay = freezed,
@@ -94,12 +98,17 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
Object? dietStateIndex = freezed,
Object? published = null,
Object? drafted = null,
Object? isDietBeingEdited = null,
}) {
return _then(_value.copyWith(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
isDietPublishing: null == isDietPublishing
? _value.isDietPublishing
: isDietPublishing // ignore: cast_nullable_to_non_nullable
as bool,
errorMessage: freezed == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
@@ -135,7 +144,7 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
dailyScheduleErrors: null == dailyScheduleErrors
? _value.dailyScheduleErrors
: dailyScheduleErrors // ignore: cast_nullable_to_non_nullable
as List<List<String>>,
as List<String>,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
@@ -152,6 +161,10 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
? _value.drafted
: drafted // ignore: cast_nullable_to_non_nullable
as bool,
isDietBeingEdited: null == isDietBeingEdited
? _value.isDietBeingEdited
: isDietBeingEdited // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
@@ -176,6 +189,7 @@ abstract class _$$CreateDietStateImplCopyWith<$Res>
@useResult
$Res call(
{bool isLoading,
bool isDietPublishing,
String? errorMessage,
CreateDietModel dietData,
List<List<DailySchedule>>? copiedDay,
@@ -184,11 +198,12 @@ abstract class _$$CreateDietStateImplCopyWith<$Res>
String? dietDurationError,
String? dietStateError,
String? dietImageError,
List<List<String>> dailyScheduleErrors,
List<String> dailyScheduleErrors,
int? durationIndex,
int? dietStateIndex,
bool published,
bool drafted});
bool drafted,
bool isDietBeingEdited});
@override
$CreateDietModelCopyWith<$Res> get dietData;
@@ -208,6 +223,7 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
@override
$Res call({
Object? isLoading = null,
Object? isDietPublishing = null,
Object? errorMessage = freezed,
Object? dietData = null,
Object? copiedDay = freezed,
@@ -221,12 +237,17 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
Object? dietStateIndex = freezed,
Object? published = null,
Object? drafted = null,
Object? isDietBeingEdited = null,
}) {
return _then(_$CreateDietStateImpl(
isLoading: null == isLoading
? _value.isLoading
: isLoading // ignore: cast_nullable_to_non_nullable
as bool,
isDietPublishing: null == isDietPublishing
? _value.isDietPublishing
: isDietPublishing // ignore: cast_nullable_to_non_nullable
as bool,
errorMessage: freezed == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
@@ -262,7 +283,7 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
dailyScheduleErrors: null == dailyScheduleErrors
? _value._dailyScheduleErrors
: dailyScheduleErrors // ignore: cast_nullable_to_non_nullable
as List<List<String>>,
as List<String>,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
@@ -279,6 +300,10 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
? _value.drafted
: drafted // ignore: cast_nullable_to_non_nullable
as bool,
isDietBeingEdited: null == isDietBeingEdited
? _value.isDietBeingEdited
: isDietBeingEdited // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
@@ -288,6 +313,7 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
class _$CreateDietStateImpl implements _CreateDietState {
const _$CreateDietStateImpl(
{required this.isLoading,
required this.isDietPublishing,
required this.errorMessage,
required this.dietData,
final List<List<DailySchedule>>? copiedDay,
@@ -296,17 +322,20 @@ class _$CreateDietStateImpl implements _CreateDietState {
this.dietDurationError,
this.dietStateError,
this.dietImageError,
required final List<List<String>> dailyScheduleErrors,
required final List<String> dailyScheduleErrors,
this.durationIndex,
this.dietStateIndex,
this.published = false,
this.drafted = false})
this.drafted = false,
this.isDietBeingEdited = false})
: _copiedDay = copiedDay,
_dailyScheduleErrors = dailyScheduleErrors;
@override
final bool isLoading;
@override
final bool isDietPublishing;
@override
final String? errorMessage;
@override
final CreateDietModel dietData;
@@ -330,9 +359,9 @@ class _$CreateDietStateImpl implements _CreateDietState {
final String? dietStateError;
@override
final String? dietImageError;
final List<List<String>> _dailyScheduleErrors;
final List<String> _dailyScheduleErrors;
@override
List<List<String>> get dailyScheduleErrors {
List<String> get dailyScheduleErrors {
if (_dailyScheduleErrors is EqualUnmodifiableListView)
return _dailyScheduleErrors;
// ignore: implicit_dynamic_type
@@ -349,10 +378,13 @@ class _$CreateDietStateImpl implements _CreateDietState {
@override
@JsonKey()
final bool drafted;
@override
@JsonKey()
final bool isDietBeingEdited;
@override
String toString() {
return 'CreateDietState(isLoading: $isLoading, errorMessage: $errorMessage, dietData: $dietData, copiedDay: $copiedDay, dietNameError: $dietNameError, dietDescriptionError: $dietDescriptionError, dietDurationError: $dietDurationError, dietStateError: $dietStateError, dietImageError: $dietImageError, dailyScheduleErrors: $dailyScheduleErrors, durationIndex: $durationIndex, dietStateIndex: $dietStateIndex, published: $published, drafted: $drafted)';
return 'CreateDietState(isLoading: $isLoading, isDietPublishing: $isDietPublishing, errorMessage: $errorMessage, dietData: $dietData, copiedDay: $copiedDay, dietNameError: $dietNameError, dietDescriptionError: $dietDescriptionError, dietDurationError: $dietDurationError, dietStateError: $dietStateError, dietImageError: $dietImageError, dailyScheduleErrors: $dailyScheduleErrors, durationIndex: $durationIndex, dietStateIndex: $dietStateIndex, published: $published, drafted: $drafted, isDietBeingEdited: $isDietBeingEdited)';
}
@override
@@ -362,6 +394,8 @@ class _$CreateDietStateImpl implements _CreateDietState {
other is _$CreateDietStateImpl &&
(identical(other.isLoading, isLoading) ||
other.isLoading == isLoading) &&
(identical(other.isDietPublishing, isDietPublishing) ||
other.isDietPublishing == isDietPublishing) &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage) &&
(identical(other.dietData, dietData) ||
@@ -386,13 +420,16 @@ class _$CreateDietStateImpl implements _CreateDietState {
other.dietStateIndex == dietStateIndex) &&
(identical(other.published, published) ||
other.published == published) &&
(identical(other.drafted, drafted) || other.drafted == drafted));
(identical(other.drafted, drafted) || other.drafted == drafted) &&
(identical(other.isDietBeingEdited, isDietBeingEdited) ||
other.isDietBeingEdited == isDietBeingEdited));
}
@override
int get hashCode => Object.hash(
runtimeType,
isLoading,
isDietPublishing,
errorMessage,
dietData,
const DeepCollectionEquality().hash(_copiedDay),
@@ -405,7 +442,8 @@ class _$CreateDietStateImpl implements _CreateDietState {
durationIndex,
dietStateIndex,
published,
drafted);
drafted,
isDietBeingEdited);
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.
@@ -420,6 +458,7 @@ class _$CreateDietStateImpl implements _CreateDietState {
abstract class _CreateDietState implements CreateDietState {
const factory _CreateDietState(
{required final bool isLoading,
required final bool isDietPublishing,
required final String? errorMessage,
required final CreateDietModel dietData,
final List<List<DailySchedule>>? copiedDay,
@@ -428,15 +467,18 @@ abstract class _CreateDietState implements CreateDietState {
final String? dietDurationError,
final String? dietStateError,
final String? dietImageError,
required final List<List<String>> dailyScheduleErrors,
required final List<String> dailyScheduleErrors,
final int? durationIndex,
final int? dietStateIndex,
final bool published,
final bool drafted}) = _$CreateDietStateImpl;
final bool drafted,
final bool isDietBeingEdited}) = _$CreateDietStateImpl;
@override
bool get isLoading;
@override
bool get isDietPublishing;
@override
String? get errorMessage;
@override
CreateDietModel get dietData;
@@ -453,7 +495,7 @@ abstract class _CreateDietState implements CreateDietState {
@override
String? get dietImageError;
@override
List<List<String>> get dailyScheduleErrors;
List<String> get dailyScheduleErrors;
@override
int? get durationIndex;
@override
@@ -462,6 +504,8 @@ abstract class _CreateDietState implements CreateDietState {
bool get published;
@override
bool get drafted;
@override
bool get isDietBeingEdited;
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.

View File

@@ -335,7 +335,7 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return _dayOfPlan(widget.diet.dailySchedule[index], index, s);
return _dayOfPlan(widget.diet.dailySchedule[index] ?? {}, index, s);
},
itemCount: widget.diet.dailySchedule.length,
),
@@ -363,7 +363,7 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
);
}
_dayOfPlan(List<List<DailySchedule>> day, int dayNumber, S s) {
_dayOfPlan(Map<int, Map<int, DailySchedule>> day, int dayNumber, S s) {
_choiceChipWidget(int index) {
return ChoiceChip(
selectedColor: appTheme.blueA400,
@@ -431,8 +431,8 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => _daily(day[widget.selectedIndexes[dayNumber]][index], s),
itemCount: day[widget.selectedIndexes[dayNumber]].length,
itemBuilder: (context, index) => _daily(day[widget.selectedIndexes[dayNumber] + 1]?[index + 1], s),
itemCount: day[widget.selectedIndexes[dayNumber] + 1]?.length ?? 0,
),
SizedBox(height: 8),
],
@@ -450,7 +450,8 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
);
}
_daily(DailySchedule daily, S s) {
_daily(DailySchedule? daily, S s) {
if (daily == null) return SizedBox.shrink();
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(

View File

@@ -199,8 +199,7 @@ class _AddMealWidgetState extends State<AddMealWidget> {
final portion = DailySchedule(
dailyNutrition: DailyNutrition(energy: calories, proteins: proteins, fats: fats, carbohydrates: carbohydrates),
quantity: int.parse(quantityController.text),
name: glossary.name,
uniq: '',
name: glossary.name,
productNutritionalValueId: glossary.id.toString(),
portion: measurementUnits,
);
@@ -240,7 +239,6 @@ class _AddMealWidgetState extends State<AddMealWidget> {
dailyNutrition: DailyNutrition(energy: calories, proteins: proteins, fats: fats, carbohydrates: carbohydrates),
quantity: int.parse(quantityController.text),
name: newGlossary.name,
uniq: '',
productNutritionalValueId: newGlossary.id.toString(),
portion: measurementUnits,
);

View File

@@ -35,7 +35,7 @@ class _DayWidgetState extends State<DayWidget> {
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return MainBackgroundBouble(
hasError: state.dailyScheduleErrors[widget.index].where((element) => element.isNotEmpty).isNotEmpty,
hasError: state.dailyScheduleErrors[widget.index].isNotEmpty,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -216,16 +216,15 @@ class _DayWidgetState extends State<DayWidget> {
),
],
),
if (state.dailyScheduleErrors[widget.index][_selectedMealIndex].isNotEmpty) ...[
if (state.dailyScheduleErrors[widget.index].isNotEmpty) ...[
SizedBox(height: 12),
CustomErrorWidget(error: state.dailyScheduleErrors[widget.index][_selectedMealIndex]),
CustomErrorWidget(error: state.dailyScheduleErrors[widget.index]),
],
SizedBox(height: 20),
],
),
),
BlocBuilder<CreateDietCubit, CreateDietState>(
buildWhen: (previous, current) => previous.dietData.dailySchedule != current.dietData.dailySchedule,
builder: (context, state) {
if (state.dietData.dailySchedule != null) {
final day = state.dietData.dailySchedule?[widget.index];

View File

@@ -71,6 +71,8 @@ class _DietImagePickerWidgetState extends State<DietImagePickerWidget> {
final s = S.of(context);
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
final hasImage = state.dietData.image != null || state.dietData.imageUrl != null;
final hasFile = state.dietData.image != null;
return Column(
children: [
GestureDetector(
@@ -81,17 +83,26 @@ class _DietImagePickerWidgetState extends State<DietImagePickerWidget> {
height: 240,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: state.dietData.image != null ? DecorationImage(fit: BoxFit.cover, image: FileImage(File(state.dietData.image?.path ?? ''))) : null,
image: hasImage
? DecorationImage(
fit: BoxFit.cover,
image: (hasFile
? FileImage(
File(state.dietData.image?.path ?? ''),
)
: NetworkImage(state.dietData.imageUrl ?? '')) as ImageProvider,
)
: null,
color: appTheme.gray50,
),
width: MediaQuery.sizeOf(context).width,
padding: state.dietData.image != null ? null : EdgeInsets.all(8),
child: state.dietData.image != null
padding: hasImage ? null : EdgeInsets.all(8),
child: hasImage
? Padding(
padding: const EdgeInsets.only(top: 6, right: 6),
child: GestureDetector(
onTap: () {
context.read<CreateDietCubit>().setImage(null);
context.read<CreateDietCubit>().setImage(null, imageUrl: null);
},
child: Align(
alignment: Alignment.topRight,

View File

@@ -18,8 +18,7 @@ class DietTypeChoiceWidget extends StatefulWidget {
class _DietTypeChoiceWidgetState extends State<DietTypeChoiceWidget> {
final List<(String, String)> choiceContent = [];
@override
void didChangeDependencies() {
// const List<String> typeValues = ['veg', 'light', 'carb', 'meat'];
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (choiceContent.isEmpty) {

View File

@@ -4,6 +4,7 @@ import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_c
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_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';
@@ -18,14 +19,23 @@ class StatusDropDownWidget extends StatefulWidget {
class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
final List<String> dietStateTitles = [];
late final List<DietState> dietStates = DietState.values;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (dietStateTitles.isEmpty) {
dietStateTitles.add(s.active_diet_state);
dietStateTitles.add(s.personal_diet_state);
dietStates.forEach((elem) {
switch (elem) {
case DietState.active:
dietStateTitles.add(s.active_diet_state);
case DietState.draft:
dietStateTitles.add(s.draft);
case DietState.personal:
dietStateTitles.add(s.personal_diet_state);
}
});
}
}
@@ -45,7 +55,8 @@ class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
),
onChanged: (value) {
if (value != null) {
context.read<CreateDietCubit>().setDietState(dietStateTitles.indexOf(value));
final index = dietStates.indexOf(value);
context.read<CreateDietCubit>().setDietState(value, index);
}
},
items: dietStateTitles
@@ -55,11 +66,11 @@ class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
dietStateTitles[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: dietStateTitles[index],
value: dietStates[index],
),
)
.toList(),
value: state.dietStateIndex == null ? null : dietStateTitles[state.dietStateIndex ?? 0],
value: state.dietStateIndex == null ? null : dietStates[state.dietStateIndex ?? 0],
),
if (state.dietStateError != null) ...[
SizedBox(