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

@@ -54,11 +54,10 @@ class AppRouter {
initialLocation: '/auth-screen',
navigatorKey: navigatorKey,
routes: [
GoRoute(
GoRoute(
path: '/auth-screen',
name: 'authScreen',
redirect: (context, state) async {
// TokenStorage.removeTokenInStorage();
if (await TokenStorage.haveTokenInStorage()) {
return '/my-profile-screen';
}
@@ -276,7 +275,10 @@ class AppRouter {
GoRoute(
path: CreateDietScreen.path,
name: CreateDietScreen.name,
builder: (context, state) => CreateDietScreen(),
builder: (context, state) {
final diet = state.extra as Diet?;
return CreateDietScreen(diet: diet);
},
),
GoRoute(
path: DietPreviewScreen.path,

View File

@@ -4,42 +4,44 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
Future<void> showBottomSheetWithBlur({
required BuildContext context,
required Widget child,
double height = 200,
bool hasBlur = true,
bool enableDrag = true,
}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
barrierColor: appTheme.transparentBlack,
backgroundColor: Colors.transparent,
elevation: 0,
useSafeArea: true,
enableDrag: enableDrag,
builder: (context) => GestureDetector(
behavior: HitTestBehavior.opaque,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: hasBlur ? 24 : 0,
sigmaY: hasBlur ? 24 : 0,
tileMode: TileMode.mirror,
),
child: SizedBox(
child: Container(
height: height,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
color: appTheme.whiteA700,
required BuildContext context,
required Widget child,
double height = 200,
bool hasBlur = true,
bool enableDrag = true,
bool userRootNavigator = false,
}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
barrierColor: appTheme.transparentBlack,
backgroundColor: Colors.transparent,
useRootNavigator: userRootNavigator,
elevation: 0,
useSafeArea: true,
enableDrag: enableDrag,
builder: (context) => GestureDetector(
behavior: HitTestBehavior.opaque,
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: hasBlur ? 24 : 0,
sigmaY: hasBlur ? 24 : 0,
tileMode: TileMode.mirror,
),
child: SizedBox(
child: Container(
height: height,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
child: child,
color: appTheme.whiteA700,
),
child: child,
),
),
),
);
}
),
);
}

View File

@@ -9,11 +9,7 @@ part of 'blog_post_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _BlogPostService implements BlogPostService {
_BlogPostService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_BlogPostService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -27,23 +23,21 @@ class _BlogPostService implements BlogPostService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = formData;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/blogPosts/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/blogPosts/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -56,23 +50,21 @@ class _BlogPostService implements BlogPostService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = formData;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/blogPosts/update/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/blogPosts/update/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -82,22 +74,16 @@ class _BlogPostService implements BlogPostService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/blogPosts/delete/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/blogPosts/delete/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -114,10 +100,7 @@ class _BlogPostService implements BlogPostService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,11 +9,7 @@ part of 'calendar_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _CalendarService implements CalendarService {
_CalendarService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_CalendarService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -27,27 +23,23 @@ class _CalendarService implements CalendarService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<List<CalendarModel>>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/calendar/index',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<List<CalendarModel>>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/calendar/index',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<List<dynamic>>(_options);
late List<CalendarModel> _value;
try {
_value = _result.data!
.map((dynamic i) => CalendarModel.fromJson(i as Map<String, dynamic>))
.map(
(dynamic i) => CalendarModel.fromJson(i as Map<String, dynamic>),
)
.toList();
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
@@ -69,10 +61,7 @@ class _CalendarService implements CalendarService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,11 +9,7 @@ part of 'consultant_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _ConsultantService implements ConsultantService {
_ConsultantService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_ConsultantService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -22,28 +18,23 @@ class _ConsultantService implements ConsultantService {
final ParseErrorLogger? errorLogger;
@override
Future<void> consultantRegistration(
{required ConsultantProfileModel consultantModel}) async {
Future<void> consultantRegistration({
required ConsultantProfileModel consultantModel,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = consultantModel;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/consultant_request/registration',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/consultant_request/registration',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -57,23 +48,21 @@ class _ConsultantService implements ConsultantService {
if (photos != null) {
_data.files.addAll(photos.map((i) => MapEntry('photos[]', i)));
}
final _options = _setStreamType<List<String>>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/consultant_request/photos/upload',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<List<String>>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/consultant_request/photos/upload',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<List<dynamic>>(_options);
late List<String> _value;
try {
@@ -98,10 +87,7 @@ class _ConsultantService implements ConsultantService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,12 +9,15 @@ class CreateDietModel with _$CreateDietModel {
const CreateDietModel._();
const factory CreateDietModel({
String? imageUrl,
String? name,
String? details,
String? state,
DietState? state,
int? duration,
required Map<String, bool> type,
XFile? image,
List<List<List<DailySchedule>>>? dailySchedule,
}) = _CreateDietModel;
}

View File

@@ -16,9 +16,10 @@ final _privateConstructorUsedError = UnsupportedError(
/// @nodoc
mixin _$CreateDietModel {
String? get imageUrl => throw _privateConstructorUsedError;
String? get name => throw _privateConstructorUsedError;
String? get details => throw _privateConstructorUsedError;
String? get state => throw _privateConstructorUsedError;
DietState? get state => throw _privateConstructorUsedError;
int? get duration => throw _privateConstructorUsedError;
Map<String, bool> get type => throw _privateConstructorUsedError;
XFile? get image => throw _privateConstructorUsedError;
@@ -39,9 +40,10 @@ abstract class $CreateDietModelCopyWith<$Res> {
_$CreateDietModelCopyWithImpl<$Res, CreateDietModel>;
@useResult
$Res call(
{String? name,
{String? imageUrl,
String? name,
String? details,
String? state,
DietState? state,
int? duration,
Map<String, bool> type,
XFile? image,
@@ -63,6 +65,7 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? imageUrl = freezed,
Object? name = freezed,
Object? details = freezed,
Object? state = freezed,
@@ -72,6 +75,10 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
Object? dailySchedule = freezed,
}) {
return _then(_value.copyWith(
imageUrl: freezed == imageUrl
? _value.imageUrl
: imageUrl // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
@@ -83,7 +90,7 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
state: freezed == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String?,
as DietState?,
duration: freezed == duration
? _value.duration
: duration // ignore: cast_nullable_to_non_nullable
@@ -113,9 +120,10 @@ abstract class _$$CreateDietModelImplCopyWith<$Res>
@override
@useResult
$Res call(
{String? name,
{String? imageUrl,
String? name,
String? details,
String? state,
DietState? state,
int? duration,
Map<String, bool> type,
XFile? image,
@@ -135,6 +143,7 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? imageUrl = freezed,
Object? name = freezed,
Object? details = freezed,
Object? state = freezed,
@@ -144,6 +153,10 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
Object? dailySchedule = freezed,
}) {
return _then(_$CreateDietModelImpl(
imageUrl: freezed == imageUrl
? _value.imageUrl
: imageUrl // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
@@ -155,7 +168,7 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
state: freezed == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String?,
as DietState?,
duration: freezed == duration
? _value.duration
: duration // ignore: cast_nullable_to_non_nullable
@@ -180,7 +193,8 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
class _$CreateDietModelImpl extends _CreateDietModel {
const _$CreateDietModelImpl(
{this.name,
{this.imageUrl,
this.name,
this.details,
this.state,
this.duration,
@@ -191,12 +205,14 @@ class _$CreateDietModelImpl extends _CreateDietModel {
_dailySchedule = dailySchedule,
super._();
@override
final String? imageUrl;
@override
final String? name;
@override
final String? details;
@override
final String? state;
final DietState? state;
@override
final int? duration;
final Map<String, bool> _type;
@@ -221,7 +237,7 @@ class _$CreateDietModelImpl extends _CreateDietModel {
@override
String toString() {
return 'CreateDietModel(name: $name, details: $details, state: $state, duration: $duration, type: $type, image: $image, dailySchedule: $dailySchedule)';
return 'CreateDietModel(imageUrl: $imageUrl, name: $name, details: $details, state: $state, duration: $duration, type: $type, image: $image, dailySchedule: $dailySchedule)';
}
@override
@@ -229,6 +245,8 @@ class _$CreateDietModelImpl extends _CreateDietModel {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CreateDietModelImpl &&
(identical(other.imageUrl, imageUrl) ||
other.imageUrl == imageUrl) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.details, details) || other.details == details) &&
(identical(other.state, state) || other.state == state) &&
@@ -243,6 +261,7 @@ class _$CreateDietModelImpl extends _CreateDietModel {
@override
int get hashCode => Object.hash(
runtimeType,
imageUrl,
name,
details,
state,
@@ -263,9 +282,10 @@ class _$CreateDietModelImpl extends _CreateDietModel {
abstract class _CreateDietModel extends CreateDietModel {
const factory _CreateDietModel(
{final String? name,
{final String? imageUrl,
final String? name,
final String? details,
final String? state,
final DietState? state,
final int? duration,
required final Map<String, bool> type,
final XFile? image,
@@ -273,12 +293,14 @@ abstract class _CreateDietModel extends CreateDietModel {
_$CreateDietModelImpl;
const _CreateDietModel._() : super._();
@override
String? get imageUrl;
@override
String? get name;
@override
String? get details;
@override
String? get state;
DietState? get state;
@override
int? get duration;
@override

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(

View File

@@ -1,5 +1,5 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
@@ -8,40 +8,54 @@ class CreateDietRepository {
CreateDietRepository({required this.createDietService});
Future<CreatedDiet> createDiet({
String? name,
int? duration,
String? state,
String? meatType,
String? carbType,
String? vegType,
String? lightType,
String? details,
File? image,
required String name,
required int duration,
required DietState state,
required String meatType,
required String carbType,
required String vegType,
required String lightType,
required String details,
required File image,
required List<List<List<DailySchedule>>> dailySchedule,
}) {
return createDietService.createDiet(
name: name,
duration: duration,
state: state,
meatType: meatType,
carbType: carbType,
vegType: vegType,
lightType: lightType,
details: details,
image: image,
);
}
final dietMap = <String, dynamic>{};
for (final (dayIndex, day) in dailySchedule.indexed) {
for (final (mealIndex, meal) in day.indexed) {
for (final (productIndex, product) in meal.indexed) {
final jsonProduct = product.toJson();
dietMap.addAll({
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][name]': jsonProduct['name'],
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][portion]': jsonProduct['portion'],
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][quantity]': jsonProduct['quantity'],
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][product_nutritional_value_id]': jsonProduct['product_nutritional_value_id'],
});
}
}
}
Future<void> createDietDailySchedule({
required int id,
required Map<String, dynamic> model,
}) {
try {
return createDietService.createDietDailySchedule(
id: id,
model: model,
);
} catch (e) {
rethrow;
dietMap.addAll({
'name': name,
'details': details,
'duration': duration,
'type[meat]': meatType,
'type[carb]': carbType,
'type[veg]': vegType,
'type[light]': lightType,
'image': MultipartFile.fromFileSync(
image.path,
filename: image.path.split(Platform.pathSeparator).last,
),
});
final formData = FormData.fromMap(dietMap);
switch (state) {
case DietState.active:
return createDietService.createPublishedDiet(formData: formData);
case DietState.draft:
return createDietService.createDraftedDiet(formData: formData);
case DietState.personal:
return createDietService.createPersonalDiet(formData: formData);
}
}
}

View File

@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:retrofit/retrofit.dart';
@@ -10,23 +8,21 @@ part 'create_diet_service.g.dart';
abstract class CreateDietService {
factory CreateDietService(Dio dio, {String baseUrl}) = _CreateDietService;
@POST('/api/diets/create')
@POST('/api/diets/create/published')
@MultiPart()
Future<CreatedDiet> createDiet({
@Part(name: 'name') String? name,
@Part(name: 'duration') int? duration,
@Part(name: 'state') String? state,
@Part(name: 'type[meat]') String? meatType,
@Part(name: 'type[carb]') String? carbType,
@Part(name: 'type[veg]') String? vegType,
@Part(name: 'type[light]') String? lightType,
@Part(name: 'details') String? details,
@Part(name: 'image') File? image,
Future<CreatedDiet> createPublishedDiet({
@Body() required FormData formData,
});
@POST('/api/diets/create/{id}/daily_schedule')
Future<void> createDietDailySchedule({
@Path() required int id,
@Body() required Map<String, dynamic> model,
@POST('/api/diets/create/drafted')
@MultiPart()
Future<CreatedDiet> createDraftedDiet({
@Body() required FormData formData,
});
@POST('/api/diets/create/personalized')
@MultiPart()
Future<CreatedDiet> createPersonalDiet({
@Body() required FormData formData,
});
}

View File

@@ -9,11 +9,7 @@ part of 'create_diet_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _CreateDietService implements CreateDietService {
_CreateDietService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_CreateDietService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -22,98 +18,26 @@ class _CreateDietService implements CreateDietService {
final ParseErrorLogger? errorLogger;
@override
Future<CreatedDiet> createDiet({
String? name,
int? duration,
String? state,
String? meatType,
String? carbType,
String? vegType,
String? lightType,
String? details,
File? image,
}) async {
Future<CreatedDiet> createPublishedDiet({required FormData formData}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
queryParameters.removeWhere((k, v) => v == null);
final _headers = <String, dynamic>{};
final _data = FormData();
if (name != null) {
_data.fields.add(MapEntry(
'name',
name,
));
}
if (duration != null) {
_data.fields.add(MapEntry(
'duration',
duration.toString(),
));
}
if (state != null) {
_data.fields.add(MapEntry(
'state',
state,
));
}
if (meatType != null) {
_data.fields.add(MapEntry(
'type[meat]',
meatType,
));
}
if (carbType != null) {
_data.fields.add(MapEntry(
'type[carb]',
carbType,
));
}
if (vegType != null) {
_data.fields.add(MapEntry(
'type[veg]',
vegType,
));
}
if (lightType != null) {
_data.fields.add(MapEntry(
'type[light]',
lightType,
));
}
if (details != null) {
_data.fields.add(MapEntry(
'details',
details,
));
}
if (image != null) {
if (image != null) {
_data.files.add(MapEntry(
'image',
MultipartFile.fromFileSync(
image.path,
filename: image.path.split(Platform.pathSeparator).last,
),
));
}
}
final _options = _setStreamType<CreatedDiet>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diets/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _data = formData;
final _options = _setStreamType<CreatedDiet>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diets/create/published',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late CreatedDiet _value;
try {
@@ -126,32 +50,67 @@ class _CreateDietService implements CreateDietService {
}
@override
Future<void> createDietDailySchedule({
required int id,
required Map<String, dynamic> model,
}) async {
Future<CreatedDiet> createDraftedDiet({required FormData formData}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(model);
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diets/create/${id}/daily_schedule',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
await _dio.fetch<void>(_options);
final _data = formData;
final _options = _setStreamType<CreatedDiet>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diets/create/drafted',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late CreatedDiet _value;
try {
_value = CreatedDiet.fromJson(_result.data!);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
@override
Future<CreatedDiet> createPersonalDiet({required FormData formData}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = formData;
final _options = _setStreamType<CreatedDiet>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diets/create/personalized',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late CreatedDiet _value;
try {
_value = CreatedDiet.fromJson(_result.data!);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
@@ -167,10 +126,7 @@ class _CreateDietService implements CreateDietService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,11 +9,7 @@ part of 'create_plan_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _CreatePlanService implements CreatePlanService {
_CreatePlanService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_CreatePlanService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -28,23 +24,21 @@ class _CreatePlanService implements CreatePlanService {
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(model);
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/plans/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/plans/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -58,22 +52,16 @@ class _CreatePlanService implements CreatePlanService {
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(model);
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/plans/create/${slug}/packet_option',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/plans/create/${slug}/packet_option',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -87,22 +75,16 @@ class _CreatePlanService implements CreatePlanService {
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(model);
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/plans/create/${slug}/packet_options',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/plans/create/${slug}/packet_options',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -119,10 +101,7 @@ class _CreatePlanService implements CreatePlanService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,11 +9,7 @@ part of 'diary_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _DiaryService implements DiaryService {
_DiaryService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_DiaryService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -22,33 +18,30 @@ class _DiaryService implements DiaryService {
final ParseErrorLogger? errorLogger;
@override
Future<List<DiaryDayModel>> getDiaryIndexByDate(
{required String date}) async {
Future<List<DiaryDayModel>> getDiaryIndexByDate({
required String date,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<List<DiaryDayModel>>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/index/${date}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<List<DiaryDayModel>>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/index/${date}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<List<dynamic>>(_options);
late List<DiaryDayModel> _value;
try {
_value = _result.data!
.map((dynamic i) => DiaryDayModel.fromJson(i as Map<String, dynamic>))
.map(
(dynamic i) => DiaryDayModel.fromJson(i as Map<String, dynamic>),
)
.toList();
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
@@ -63,22 +56,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<DiaryDayWrapperModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/show',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<DiaryDayWrapperModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/show',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late DiaryDayWrapperModel _value;
try {
@@ -96,22 +83,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<NutritionDataModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/dailyNutritionData',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<NutritionDataModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/dailyNutritionData',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late NutritionDataModel _value;
try {
@@ -133,30 +114,30 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = FormData();
_data.files.add(MapEntry(
'photo',
MultipartFile.fromFileSync(
photo.path,
filename: photo.path.split(Platform.pathSeparator).last,
_data.files.add(
MapEntry(
'photo',
MultipartFile.fromFileSync(
photo.path,
filename: photo.path.split(Platform.pathSeparator).last,
),
),
));
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/photo/upload',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
);
final _options = _setStreamType<void>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/photo/upload',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -170,22 +151,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'DELETE',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diaryId}/meals/${typeNo}/photo/${userAttachment}/delete',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'DELETE', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diaryId}/meals/${typeNo}/photo/${userAttachment}/delete',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -203,40 +178,27 @@ class _DiaryService implements DiaryService {
queryParameters.removeWhere((k, v) => v == null);
final _headers = <String, dynamic>{};
final _data = FormData();
_data.fields.add(MapEntry(
'product_name',
productName,
));
_data.fields.add(MapEntry(
'portion',
portion,
));
_data.fields.add(MapEntry(
'quantity',
quantity.toString(),
));
_data.fields.add(MapEntry('product_name', productName));
_data.fields.add(MapEntry('portion', portion));
_data.fields.add(MapEntry('quantity', quantity.toString()));
if (productNutritionalValueId != null) {
_data.fields.add(MapEntry(
'product_nutritional_value_id',
productNutritionalValueId.toString(),
));
_data.fields.add(
MapEntry(
'product_nutritional_value_id',
productNutritionalValueId.toString(),
),
);
}
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portion/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portion/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -252,22 +214,16 @@ class _DiaryService implements DiaryService {
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(productInMeal);
final _options = _setStreamType<void>(Options(
method: 'PUT',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'PUT', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -281,22 +237,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/${portionModel}/mark_eaten',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/${portionModel}/mark_eaten',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -310,22 +260,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/${portionModel}/unmark_eaten',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/${portionModel}/unmark_eaten',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -339,22 +283,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/restore',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/restore',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -368,22 +306,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(Options(
method: 'DELETE',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/delete',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'DELETE', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/delete',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -396,22 +328,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = finishDiaryDayModel;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/finishDay',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/finishDay',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -425,22 +351,16 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = {'satiety': satiety};
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/satiety/fill',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/satiety/fill',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@@ -454,49 +374,38 @@ class _DiaryService implements DiaryService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = {'time': time};
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/time/fill',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/${diary}/meals/${typeNo}/time/fill',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@override
Future<GlossaryModerationModel> sendProductToModeration(
{required Map<String, dynamic> data}) async {
Future<GlossaryModerationModel> sendProductToModeration({
required Map<String, dynamic> data,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(data);
final _options = _setStreamType<GlossaryModerationModel>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/product_nutritional_values/sendToModeration',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<GlossaryModerationModel>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/product_nutritional_values/sendToModeration',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late GlossaryModerationModel _value;
try {
@@ -521,10 +430,7 @@ class _DiaryService implements DiaryService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -454,7 +454,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return _dayOfPlan(widget.diet.dailySchedule[index], index, s);
return _dayOfPlan(widget.diet.dailySchedule[index + 1] ?? {}, index, s);
},
itemCount: widget.diet.dailySchedule.length,
),
@@ -500,7 +500,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
);
}
_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,
@@ -568,8 +568,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
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),
],
@@ -587,7 +587,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
);
}
_daily(DailySchedule daily, S s) {
_daily(DailySchedule? daily, S s) {
if (daily == null) return const SizedBox();
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(

View File

@@ -23,10 +23,10 @@ class Diet with _$Diet {
@JsonKey(name: "name") required String name,
@JsonKey(name: "image") required String image,
@JsonKey(name: "duration") required int duration,
@JsonKey(name: "state") required String state,
@JsonKey(name: "state") required DietState state,
@JsonKey(name: "type") required DietType type,
@JsonKey(name: "details") required String details,
@JsonKey(name: "daily_schedule") required List<List<List<DailySchedule>>> dailySchedule,
@JsonKey(name: "daily_schedule") required Map<int, Map<int, Map<int, DailySchedule>>> dailySchedule,
@JsonKey(name: "author") required Author author,
@JsonKey(name: "total_likes") required int totalLikes,
@JsonKey(name: "total_views") required int totalViews,
@@ -39,10 +39,30 @@ class Diet with _$Diet {
factory Diet.fromJson(Map<String, dynamic> json) => _$DietFromJson(json);
}
enum DietState {
@JsonKey(name: 'active')
active,
@JsonKey(name: 'draft')
draft,
@JsonKey(name: 'personal')
personal;
String toString() {
switch (this) {
case DietState.active:
return 'active';
case DietState.draft:
return 'draft';
case DietState.personal:
return 'personal';
}
}
}
@freezed
class CreatedDiet with _$CreatedDiet {
const factory CreatedDiet({
@JsonKey(name: "id") required int id,
@JsonKey(name: "id") required int id,
}) = _CreatedDiet;
factory CreatedDiet.fromJson(Map<String, dynamic> json) => _$CreatedDietFromJson(json);
@@ -51,9 +71,9 @@ class CreatedDiet with _$CreatedDiet {
int parseDuration(dynamic duration) {
if (duration is String) {
return int.parse(duration);
}else {
} else {
return duration;
}
}
}
@freezed
@@ -74,9 +94,8 @@ class Author with _$Author {
class DailySchedule with _$DailySchedule {
const factory DailySchedule({
@JsonKey(name: "name") required String name,
@JsonKey(name: "uniq", includeToJson: false) required String uniq,
@JsonKey(name: "portion") required Portion portion,
@JsonKey(name: "quantity") required int quantity,
@JsonKey(name: "quantity", fromJson: _parseQuantity) required int quantity,
@JsonKey(includeToJson: false, includeFromJson: false) DailyNutrition? dailyNutrition,
@JsonKey(name: 'product_nutritional_value_id', includeToJson: true, includeFromJson: false, includeIfNull: false) String? productNutritionalValueId,
}) = _DailySchedule;
@@ -84,8 +103,16 @@ class DailySchedule with _$DailySchedule {
factory DailySchedule.fromJson(Map<String, dynamic> json) => _$DailyScheduleFromJson(json);
}
int _parseQuantity(dynamic quantity) {
if (quantity is String) {
return int.parse(quantity);
} else {
return quantity;
}
}
enum Portion {
@JsonValue("grams")
@JsonValue("gr")
GRAMS,
@JsonValue("milliliters")
MILLILITERS,

View File

@@ -268,13 +268,13 @@ mixin _$Diet {
@JsonKey(name: "duration")
int get duration => throw _privateConstructorUsedError;
@JsonKey(name: "state")
String get state => throw _privateConstructorUsedError;
DietState get state => throw _privateConstructorUsedError;
@JsonKey(name: "type")
DietType get type => throw _privateConstructorUsedError;
@JsonKey(name: "details")
String get details => throw _privateConstructorUsedError;
@JsonKey(name: "daily_schedule")
List<List<List<DailySchedule>>> get dailySchedule =>
Map<int, Map<int, Map<int, DailySchedule>>> get dailySchedule =>
throw _privateConstructorUsedError;
@JsonKey(name: "author")
Author get author => throw _privateConstructorUsedError;
@@ -310,11 +310,11 @@ abstract class $DietCopyWith<$Res> {
@JsonKey(name: "name") String name,
@JsonKey(name: "image") String image,
@JsonKey(name: "duration") int duration,
@JsonKey(name: "state") String state,
@JsonKey(name: "state") DietState state,
@JsonKey(name: "type") DietType type,
@JsonKey(name: "details") String details,
@JsonKey(name: "daily_schedule")
List<List<List<DailySchedule>>> dailySchedule,
Map<int, Map<int, Map<int, DailySchedule>>> dailySchedule,
@JsonKey(name: "author") Author author,
@JsonKey(name: "total_likes") int totalLikes,
@JsonKey(name: "total_views") int totalViews,
@@ -378,7 +378,7 @@ class _$DietCopyWithImpl<$Res, $Val extends Diet>
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
as DietState,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
@@ -390,7 +390,7 @@ class _$DietCopyWithImpl<$Res, $Val extends Diet>
dailySchedule: null == dailySchedule
? _value.dailySchedule
: dailySchedule // ignore: cast_nullable_to_non_nullable
as List<List<List<DailySchedule>>>,
as Map<int, Map<int, Map<int, DailySchedule>>>,
author: null == author
? _value.author
: author // ignore: cast_nullable_to_non_nullable
@@ -455,11 +455,11 @@ abstract class _$$DietImplCopyWith<$Res> implements $DietCopyWith<$Res> {
@JsonKey(name: "name") String name,
@JsonKey(name: "image") String image,
@JsonKey(name: "duration") int duration,
@JsonKey(name: "state") String state,
@JsonKey(name: "state") DietState state,
@JsonKey(name: "type") DietType type,
@JsonKey(name: "details") String details,
@JsonKey(name: "daily_schedule")
List<List<List<DailySchedule>>> dailySchedule,
Map<int, Map<int, Map<int, DailySchedule>>> dailySchedule,
@JsonKey(name: "author") Author author,
@JsonKey(name: "total_likes") int totalLikes,
@JsonKey(name: "total_views") int totalViews,
@@ -522,7 +522,7 @@ class __$$DietImplCopyWithImpl<$Res>
state: null == state
? _value.state
: state // ignore: cast_nullable_to_non_nullable
as String,
as DietState,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
@@ -534,7 +534,7 @@ class __$$DietImplCopyWithImpl<$Res>
dailySchedule: null == dailySchedule
? _value._dailySchedule
: dailySchedule // ignore: cast_nullable_to_non_nullable
as List<List<List<DailySchedule>>>,
as Map<int, Map<int, Map<int, DailySchedule>>>,
author: null == author
? _value.author
: author // ignore: cast_nullable_to_non_nullable
@@ -579,7 +579,7 @@ class _$DietImpl implements _Diet {
@JsonKey(name: "type") required this.type,
@JsonKey(name: "details") required this.details,
@JsonKey(name: "daily_schedule")
required final List<List<List<DailySchedule>>> dailySchedule,
required final Map<int, Map<int, Map<int, DailySchedule>>> dailySchedule,
@JsonKey(name: "author") required this.author,
@JsonKey(name: "total_likes") required this.totalLikes,
@JsonKey(name: "total_views") required this.totalViews,
@@ -608,20 +608,20 @@ class _$DietImpl implements _Diet {
final int duration;
@override
@JsonKey(name: "state")
final String state;
final DietState state;
@override
@JsonKey(name: "type")
final DietType type;
@override
@JsonKey(name: "details")
final String details;
final List<List<List<DailySchedule>>> _dailySchedule;
final Map<int, Map<int, Map<int, DailySchedule>>> _dailySchedule;
@override
@JsonKey(name: "daily_schedule")
List<List<List<DailySchedule>>> get dailySchedule {
if (_dailySchedule is EqualUnmodifiableListView) return _dailySchedule;
Map<int, Map<int, Map<int, DailySchedule>>> get dailySchedule {
if (_dailySchedule is EqualUnmodifiableMapView) return _dailySchedule;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_dailySchedule);
return EqualUnmodifiableMapView(_dailySchedule);
}
@override
@@ -728,11 +728,11 @@ abstract class _Diet implements Diet {
@JsonKey(name: "name") required final String name,
@JsonKey(name: "image") required final String image,
@JsonKey(name: "duration") required final int duration,
@JsonKey(name: "state") required final String state,
@JsonKey(name: "state") required final DietState state,
@JsonKey(name: "type") required final DietType type,
@JsonKey(name: "details") required final String details,
@JsonKey(name: "daily_schedule")
required final List<List<List<DailySchedule>>> dailySchedule,
required final Map<int, Map<int, Map<int, DailySchedule>>> dailySchedule,
@JsonKey(name: "author") required final Author author,
@JsonKey(name: "total_likes") required final int totalLikes,
@JsonKey(name: "total_views") required final int totalViews,
@@ -758,7 +758,7 @@ abstract class _Diet implements Diet {
int get duration;
@override
@JsonKey(name: "state")
String get state;
DietState get state;
@override
@JsonKey(name: "type")
DietType get type;
@@ -767,7 +767,7 @@ abstract class _Diet implements Diet {
String get details;
@override
@JsonKey(name: "daily_schedule")
List<List<List<DailySchedule>>> get dailySchedule;
Map<int, Map<int, Map<int, DailySchedule>>> get dailySchedule;
@override
@JsonKey(name: "author")
Author get author;
@@ -1242,11 +1242,9 @@ DailySchedule _$DailyScheduleFromJson(Map<String, dynamic> json) {
mixin _$DailySchedule {
@JsonKey(name: "name")
String get name => throw _privateConstructorUsedError;
@JsonKey(name: "uniq", includeToJson: false)
String get uniq => throw _privateConstructorUsedError;
@JsonKey(name: "portion")
Portion get portion => throw _privateConstructorUsedError;
@JsonKey(name: "quantity")
@JsonKey(name: "quantity", fromJson: _parseQuantity)
int get quantity => throw _privateConstructorUsedError;
@JsonKey(includeToJson: false, includeFromJson: false)
DailyNutrition? get dailyNutrition => throw _privateConstructorUsedError;
@@ -1275,9 +1273,8 @@ abstract class $DailyScheduleCopyWith<$Res> {
@useResult
$Res call(
{@JsonKey(name: "name") String name,
@JsonKey(name: "uniq", includeToJson: false) String uniq,
@JsonKey(name: "portion") Portion portion,
@JsonKey(name: "quantity") int quantity,
@JsonKey(name: "quantity", fromJson: _parseQuantity) int quantity,
@JsonKey(includeToJson: false, includeFromJson: false)
DailyNutrition? dailyNutrition,
@JsonKey(
@@ -1306,7 +1303,6 @@ class _$DailyScheduleCopyWithImpl<$Res, $Val extends DailySchedule>
@override
$Res call({
Object? name = null,
Object? uniq = null,
Object? portion = null,
Object? quantity = null,
Object? dailyNutrition = freezed,
@@ -1317,10 +1313,6 @@ class _$DailyScheduleCopyWithImpl<$Res, $Val extends DailySchedule>
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
uniq: null == uniq
? _value.uniq
: uniq // ignore: cast_nullable_to_non_nullable
as String,
portion: null == portion
? _value.portion
: portion // ignore: cast_nullable_to_non_nullable
@@ -1365,9 +1357,8 @@ abstract class _$$DailyScheduleImplCopyWith<$Res>
@useResult
$Res call(
{@JsonKey(name: "name") String name,
@JsonKey(name: "uniq", includeToJson: false) String uniq,
@JsonKey(name: "portion") Portion portion,
@JsonKey(name: "quantity") int quantity,
@JsonKey(name: "quantity", fromJson: _parseQuantity) int quantity,
@JsonKey(includeToJson: false, includeFromJson: false)
DailyNutrition? dailyNutrition,
@JsonKey(
@@ -1395,7 +1386,6 @@ class __$$DailyScheduleImplCopyWithImpl<$Res>
@override
$Res call({
Object? name = null,
Object? uniq = null,
Object? portion = null,
Object? quantity = null,
Object? dailyNutrition = freezed,
@@ -1406,10 +1396,6 @@ class __$$DailyScheduleImplCopyWithImpl<$Res>
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
uniq: null == uniq
? _value.uniq
: uniq // ignore: cast_nullable_to_non_nullable
as String,
portion: null == portion
? _value.portion
: portion // ignore: cast_nullable_to_non_nullable
@@ -1435,9 +1421,9 @@ class __$$DailyScheduleImplCopyWithImpl<$Res>
class _$DailyScheduleImpl implements _DailySchedule {
const _$DailyScheduleImpl(
{@JsonKey(name: "name") required this.name,
@JsonKey(name: "uniq", includeToJson: false) required this.uniq,
@JsonKey(name: "portion") required this.portion,
@JsonKey(name: "quantity") required this.quantity,
@JsonKey(name: "quantity", fromJson: _parseQuantity)
required this.quantity,
@JsonKey(includeToJson: false, includeFromJson: false)
this.dailyNutrition,
@JsonKey(
@@ -1454,13 +1440,10 @@ class _$DailyScheduleImpl implements _DailySchedule {
@JsonKey(name: "name")
final String name;
@override
@JsonKey(name: "uniq", includeToJson: false)
final String uniq;
@override
@JsonKey(name: "portion")
final Portion portion;
@override
@JsonKey(name: "quantity")
@JsonKey(name: "quantity", fromJson: _parseQuantity)
final int quantity;
@override
@JsonKey(includeToJson: false, includeFromJson: false)
@@ -1475,7 +1458,7 @@ class _$DailyScheduleImpl implements _DailySchedule {
@override
String toString() {
return 'DailySchedule(name: $name, uniq: $uniq, portion: $portion, quantity: $quantity, dailyNutrition: $dailyNutrition, productNutritionalValueId: $productNutritionalValueId)';
return 'DailySchedule(name: $name, portion: $portion, quantity: $quantity, dailyNutrition: $dailyNutrition, productNutritionalValueId: $productNutritionalValueId)';
}
@override
@@ -1484,7 +1467,6 @@ class _$DailyScheduleImpl implements _DailySchedule {
(other.runtimeType == runtimeType &&
other is _$DailyScheduleImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.uniq, uniq) || other.uniq == uniq) &&
(identical(other.portion, portion) || other.portion == portion) &&
(identical(other.quantity, quantity) ||
other.quantity == quantity) &&
@@ -1497,7 +1479,7 @@ class _$DailyScheduleImpl implements _DailySchedule {
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, name, uniq, portion, quantity,
int get hashCode => Object.hash(runtimeType, name, portion, quantity,
dailyNutrition, productNutritionalValueId);
/// Create a copy of DailySchedule
@@ -1519,9 +1501,9 @@ class _$DailyScheduleImpl implements _DailySchedule {
abstract class _DailySchedule implements DailySchedule {
const factory _DailySchedule(
{@JsonKey(name: "name") required final String name,
@JsonKey(name: "uniq", includeToJson: false) required final String uniq,
@JsonKey(name: "portion") required final Portion portion,
@JsonKey(name: "quantity") required final int quantity,
@JsonKey(name: "quantity", fromJson: _parseQuantity)
required final int quantity,
@JsonKey(includeToJson: false, includeFromJson: false)
final DailyNutrition? dailyNutrition,
@JsonKey(
@@ -1538,13 +1520,10 @@ abstract class _DailySchedule implements DailySchedule {
@JsonKey(name: "name")
String get name;
@override
@JsonKey(name: "uniq", includeToJson: false)
String get uniq;
@override
@JsonKey(name: "portion")
Portion get portion;
@override
@JsonKey(name: "quantity")
@JsonKey(name: "quantity", fromJson: _parseQuantity)
int get quantity;
@override
@JsonKey(includeToJson: false, includeFromJson: false)

View File

@@ -29,16 +29,21 @@ _$DietImpl _$$DietImplFromJson(Map<String, dynamic> json) => _$DietImpl(
name: json['name'] as String,
image: json['image'] as String,
duration: (json['duration'] as num).toInt(),
state: json['state'] as String,
state: $enumDecode(_$DietStateEnumMap, json['state']),
type: DietType.fromJson(json['type'] as Map<String, dynamic>),
details: json['details'] as String,
dailySchedule: (json['daily_schedule'] as List<dynamic>)
.map((e) => (e as List<dynamic>)
.map((e) => (e as List<dynamic>)
.map((e) => DailySchedule.fromJson(e as Map<String, dynamic>))
.toList())
.toList())
.toList(),
dailySchedule: (json['daily_schedule'] as Map<String, dynamic>).map(
(k, e) => MapEntry(
int.parse(k),
(e as Map<String, dynamic>).map(
(k, e) => MapEntry(
int.parse(k),
(e as Map<String, dynamic>).map(
(k, e) => MapEntry(int.parse(k),
DailySchedule.fromJson(e as Map<String, dynamic>)),
)),
)),
),
author: Author.fromJson(json['author'] as Map<String, dynamic>),
totalLikes: (json['total_likes'] as num).toInt(),
totalViews: (json['total_views'] as num).toInt(),
@@ -56,10 +61,13 @@ Map<String, dynamic> _$$DietImplToJson(_$DietImpl instance) =>
'name': instance.name,
'image': instance.image,
'duration': instance.duration,
'state': instance.state,
'state': _$DietStateEnumMap[instance.state]!,
'type': instance.type,
'details': instance.details,
'daily_schedule': instance.dailySchedule,
'daily_schedule': instance.dailySchedule.map((k, e) => MapEntry(
k.toString(),
e.map((k, e) => MapEntry(
k.toString(), e.map((k, e) => MapEntry(k.toString(), e)))))),
'author': instance.author,
'total_likes': instance.totalLikes,
'total_views': instance.totalViews,
@@ -69,6 +77,12 @@ Map<String, dynamic> _$$DietImplToJson(_$DietImpl instance) =>
'daily_nutrition': instance.dailyNutrition,
};
const _$DietStateEnumMap = {
DietState.active: 'active',
DietState.draft: 'draft',
DietState.personal: 'personal',
};
_$CreatedDietImpl _$$CreatedDietImplFromJson(Map<String, dynamic> json) =>
_$CreatedDietImpl(
id: (json['id'] as num).toInt(),
@@ -101,9 +115,8 @@ Map<String, dynamic> _$$AuthorImplToJson(_$AuthorImpl instance) =>
_$DailyScheduleImpl _$$DailyScheduleImplFromJson(Map<String, dynamic> json) =>
_$DailyScheduleImpl(
name: json['name'] as String,
uniq: json['uniq'] as String,
portion: $enumDecode(_$PortionEnumMap, json['portion']),
quantity: (json['quantity'] as num).toInt(),
quantity: _parseQuantity(json['quantity']),
);
Map<String, dynamic> _$$DailyScheduleImplToJson(_$DailyScheduleImpl instance) =>
@@ -116,7 +129,7 @@ Map<String, dynamic> _$$DailyScheduleImplToJson(_$DailyScheduleImpl instance) =>
};
const _$PortionEnumMap = {
Portion.GRAMS: 'grams',
Portion.GRAMS: 'gr',
Portion.MILLILITERS: 'milliliters',
Portion.PCS: 'pcs',
};

View File

@@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:eatvio_app/features/feed/presentation/bloc/consultants_cubit/consultants_state.dart';
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -18,7 +20,8 @@ class ConsultantsCubit extends Cubit<ConsultantsState> {
isLoading: false,
),
);
} catch (e) {
} catch (e, st) {
log(e.toString(), stackTrace: st);
emit(ConsultantsState.error(errorMessage: e.toString()));
}
}

View File

@@ -107,9 +107,10 @@ class DietsCubit extends Cubit<DietsState> {
errorMessage: null,
),
);
} catch (e) {
} catch (e, st) {
log(e.toString(), stackTrace: st);
emit(
state.copyWith(errorMessage: e.toString()),
state.copyWith(isLoading: false),
);
}
}
@@ -143,14 +144,13 @@ class DietsCubit extends Cubit<DietsState> {
);
}
} catch (e) {
emit(state.copyWith(errorMessage: e.toString()));
emit(state.copyWith(isLoading: false));
}
}
}
Future<void> likeDiet(int id, int index) async {
final currentDiets = state.dietsList;
// if (currentDiets.isEmpty) return;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[index];
if (currentDiet.wasLikedByMe) {

View File

@@ -1,5 +1,6 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/widgets/add_item_button.dart';
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
import 'package:eatvio_app/core/widgets/custom_search_bar.dart';
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
import 'package:eatvio_app/features/create_plan/presentation/create_plan_screen.dart';
@@ -14,6 +15,7 @@ import 'package:eatvio_app/features/feed/presentation/widgets/chip_group.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/consultants.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/diets.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/plans.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/success_published_diet_bottom_sheet.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/tags_modal_widget.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart';
import 'package:eatvio_app/core/locator_service.dart';
@@ -25,7 +27,6 @@ import 'package:go_router/go_router.dart';
import '../widgets/recipes.dart';
class FeedScreen extends StatelessWidget {
const FeedScreen({super.key});
@@ -260,10 +261,23 @@ class _FeedScreenContentState extends State<FeedScreenContent> {
onTap: () => GoRouter.of(context).pushNamed(RecipeCreateScreen.name),
),
2 => AddItemButton(
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null,
onTap: state.profile?.roles.contains('consultant') ?? false
? () async {
final result = await GoRouter.of(context).pushNamed<String?>(CreateDietScreen.name);
if (result != null) {
showBottomSheetWithBlur(
userRootNavigator: true,
context: context,
child: SuccessPublishedDietBottomSheet(
title: result,
),
);
}
}
: null,
),
3 => AddItemButton(
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null,
onTap: state.profile?.roles.contains('consultant') ?? false ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null,
),
_ => AddItemButton()
},

View File

@@ -63,4 +63,4 @@ class Diets extends StatelessWidget {
),
);
}
}
}

View File

@@ -0,0 +1,54 @@
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/bottom_sheet_handler_bar.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class SuccessPublishedDietBottomSheet extends StatelessWidget {
const SuccessPublishedDietBottomSheet({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 20,
),
BottomSheetHandlerBar(),
SizedBox(
height: 20,
),
Text(
title,
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: () {
GoRouter.of(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,
),
],
);
}
}

View File

@@ -9,11 +9,7 @@ part of 'glossary_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _GlossaryService implements GlossaryService {
_GlossaryService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_GlossaryService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -22,28 +18,23 @@ class _GlossaryService implements GlossaryService {
final ParseErrorLogger? errorLogger;
@override
Future<GlossaryPaginationModel> getGlossaryByQuery(
{required String query}) async {
Future<GlossaryPaginationModel> getGlossaryByQuery({
required String query,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{r'search': query};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<GlossaryPaginationModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/glossaries/search',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<GlossaryPaginationModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/glossaries/search',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late GlossaryPaginationModel _value;
try {
@@ -68,10 +59,7 @@ class _GlossaryService implements GlossaryService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -1,5 +1,8 @@
import 'dart:developer';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
import 'package:eatvio_app/features/my_diets/repositories/my_diets_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -28,6 +31,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
'name',
'name:desc',
];
static const List<int?> _durationValues = [null, ...durationValues];
static const List<String?> _types = [null, ...dietTypeValues];
@@ -39,7 +43,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _activeQuery,
),
);
@@ -48,7 +52,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _draftQuery,
),
);
@@ -57,7 +61,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _personalQuery,
),
);
@@ -70,7 +74,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _activeQuery,
),
);
@@ -79,7 +83,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _draftQuery,
),
);
@@ -88,7 +92,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _personalQuery,
),
);
@@ -101,7 +105,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _activeQuery,
),
);
@@ -110,7 +114,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _draftQuery,
),
);
@@ -119,7 +123,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
EasyDebounce.debounce(
'loadDiets',
Duration(seconds: 1),
() => loadDiets(
() => loadCurrentDiets(
query: _personalQuery,
),
);
@@ -128,9 +132,34 @@ class MyDietsCubit extends Cubit<MyDietsState> {
void changeSelectedStateIndex(int index) {
emit(state.copyWith(selectedStateIndex: index));
if (state.activeDiets.isEmpty) {
EasyDebounce.debounce(
'loadActiveDiets',
Duration(seconds: 1),
() => loadCurrentDiets(
query: _activeQuery,
),
);
} else if (state.draftDiets.isEmpty) {
EasyDebounce.debounce(
'loadDraftDiets',
Duration(seconds: 1),
() => loadCurrentDiets(
query: _draftQuery,
),
);
} else if (state.personalDiets.isEmpty) {
EasyDebounce.debounce(
'loadPersonalDiets',
Duration(seconds: 1),
() => loadCurrentDiets(
query: _personalQuery,
),
);
}
}
Future<void> loadDiets({
Future<void> loadCurrentDiets({
String? query,
}) async {
switch (state.selectedStateIndex) {
@@ -160,11 +189,13 @@ class MyDietsCubit extends Cubit<MyDietsState> {
final type = _types[state.activeFilterState.typeIndex];
final duration = _durationValues[state.activeFilterState.durationIndex];
final sorting = _sortingValues[state.activeFilterState.sortingIndex];
final dietState = DietState.active;
final dietsPagination = await myDietsRepository.getDiets(
query: query,
types: type,
duration: duration,
sorting: sorting,
state: dietState.toString(),
);
lastActivePage = dietsPagination.meta.lastPage;
emit(
@@ -174,7 +205,8 @@ class MyDietsCubit extends Cubit<MyDietsState> {
error: null,
),
);
} catch (e) {
} catch (e, st) {
log(e.toString(), stackTrace: st);
emit(
state.copyWith(error: e.toString()),
);
@@ -187,11 +219,13 @@ class MyDietsCubit extends Cubit<MyDietsState> {
final type = _types[state.draftFilterState.typeIndex];
final duration = _durationValues[state.draftFilterState.durationIndex];
final sorting = _sortingValues[state.draftFilterState.sortingIndex];
final dietState = DietState.draft;
final dietsPagination = await myDietsRepository.getDiets(
query: query,
types: type,
duration: duration,
sorting: sorting,
state: dietState.toString(),
);
lastActivePage = dietsPagination.meta.lastPage;
emit(
@@ -214,11 +248,13 @@ class MyDietsCubit extends Cubit<MyDietsState> {
final type = _types[state.personalFilterState.typeIndex];
final duration = _durationValues[state.personalFilterState.durationIndex];
final sorting = _sortingValues[state.personalFilterState.sortingIndex];
final dietState = DietState.personal;
final dietsPagination = await myDietsRepository.getDiets(
query: query,
types: type,
duration: duration,
sorting: sorting,
state: dietState.toString(),
);
lastActivePage = dietsPagination.meta.lastPage;
emit(

View File

@@ -33,7 +33,7 @@ class MyDietsScreenContent extends StatelessWidget {
final activeDietsScrollController = ScrollController();
final draftDietsScrollController = ScrollController();
final personalDietsScrollController = ScrollController();
final activeDietsSearchController = SearchController();
final draftDietsSearchController = SearchController();
final personalDietsSearchController = SearchController();
@@ -111,7 +111,7 @@ class MyDietsScreenContent extends StatelessWidget {
'searchDiets',
Duration(milliseconds: 500),
() {
context.read<MyDietsCubit>().loadDiets(query: query == '' ? null : query);
context.read<MyDietsCubit>().loadCurrentDiets(query: query == '' ? null : query);
},
);
},
@@ -133,7 +133,7 @@ class MyDietsScreenContent extends StatelessWidget {
];
},
body: RefreshIndicator(
onRefresh: () => context.read<MyDietsCubit>().loadDiets(),
onRefresh: () => context.read<MyDietsCubit>().loadCurrentDiets(),
child: BlocBuilder<MyDietsCubit, MyDietsState>(
builder: (BuildContext context, MyDietsState state) {
if (state.isLoading) {

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/info_row.dart';
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
@@ -110,6 +111,13 @@ class _MyDietWidgetState extends State<MyDietWidget> {
children: [
Expanded(
child: CustomOutlinedButton(
onPressed: () {
if (state.selectedStateIndex == 1) {
} else if (state.selectedStateIndex == 2) {
} else {
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
}
},
text: switch (state.selectedStateIndex) {
1 => s.publish,
2 => s.toOffer,
@@ -160,6 +168,12 @@ class _MyDietWidgetState extends State<MyDietWidget> {
children: [
Expanded(
child: CustomOutlinedButton(
onPressed: () {
if (state.selectedStateIndex == 0) {
} else {
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
}
},
text: switch (state.selectedStateIndex) {
0 => s.removeFromActive,
_ => s.edit,
@@ -178,51 +192,49 @@ class _MyDietWidgetState extends State<MyDietWidget> {
onPressed: () async {
final result = await context.read<MyDietsCubit>().deleteDiet(widget.diet.id);
if (result)
Future.delayed(Duration(seconds: 3), () {
showBottomSheetWithBlur(
context: context,
child: Column(
children: [
SizedBox(
height: 20,
),
BottomSheetHandlerBar(),
SizedBox(
height: 20,
),
Text(
'${widget.diet.name}',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
Text(
s.deleted,
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),
),
showBottomSheetWithBlur(
context: context,
child: Column(
children: [
SizedBox(
height: 20,
),
BottomSheetHandlerBar(),
SizedBox(
height: 20,
),
Text(
'${widget.diet.name}',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
Text(
s.deleted,
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,
),
],
),
);
});
),
SizedBox(
height: 20,
),
],
),
);
},
height: 52,
width: 52,

View File

@@ -20,6 +20,7 @@ class MyDietsRepository {
String? types,
int? duration,
String? sorting,
String? state,
}) async {
try {
return (await myDietsService.getDiets(
@@ -28,6 +29,7 @@ class MyDietsRepository {
types: types,
duration: duration,
sorting: sorting,
state: state,
));
} catch (e) {
rethrow;

View File

@@ -12,13 +12,14 @@ abstract class MyDietsService {
@GET('/api/profile/my_diets')
Future<DietsPagination> getDiets({
@Query('page') required int page,
@Query('filters[name][\$startsWith]') String? query,
@Query('filters[name][\$startsWith]') String? query,
@Query('filters[state][\$eq]') String? state,
@Query('filters[type][\$contains]') String? types,
@Query('filters[duration][\$eq]') int? duration,
@Query('sort') String? sorting,
});
@POST('/api/diets/delete/{dietId}')
@DELETE('/api/diets/delete/{dietId}')
Future<void> deleteDiet({
@Path() required int dietId,
});

View File

@@ -21,6 +21,7 @@ class _MyDietsService implements MyDietsService {
Future<DietsPagination> getDiets({
required int page,
String? query,
String? state,
String? types,
int? duration,
String? sorting,
@@ -29,6 +30,7 @@ class _MyDietsService implements MyDietsService {
final queryParameters = <String, dynamic>{
r'page': page,
r'filters[name][$startsWith]': query,
r'filters[state][$eq]': state,
r'filters[type][$contains]': types,
r'filters[duration][$eq]': duration,
r'sort': sorting,
@@ -64,7 +66,7 @@ class _MyDietsService implements MyDietsService {
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<void>(
Options(method: 'POST', headers: _headers, extra: _extra)
Options(method: 'DELETE', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diets/delete/${dietId}',

View File

@@ -18,7 +18,7 @@ class ProfileModel with _$ProfileModel {
@JsonKey(name: 'is_entity_subscribed_by_me') required bool isEntitySubscribedByMe,
@JsonKey(name: "slug") required String slug,
@JsonKey(name: "profile_photo_url") required String profilePhotoUrl,
@JsonKey(name: "role") required String role,
@JsonKey(name: "roles") required List<String> roles,
@JsonKey(name: "badges") required List<BadgeModel> badges,
@JsonKey(name: "subscriptions") required List<ProfilePreviewModel> subscriptions,
@JsonKey(name: "subscribers") required List<ProfilePreviewModel> subscribers,

View File

@@ -42,8 +42,8 @@ mixin _$ProfileModel {
String get slug => throw _privateConstructorUsedError;
@JsonKey(name: "profile_photo_url")
String get profilePhotoUrl => throw _privateConstructorUsedError;
@JsonKey(name: "role")
String get role => throw _privateConstructorUsedError;
@JsonKey(name: "roles")
List<String> get roles => throw _privateConstructorUsedError;
@JsonKey(name: "badges")
List<BadgeModel> get badges => throw _privateConstructorUsedError;
@JsonKey(name: "subscriptions")
@@ -86,7 +86,7 @@ abstract class $ProfileModelCopyWith<$Res> {
@JsonKey(name: 'is_entity_subscribed_by_me') bool isEntitySubscribedByMe,
@JsonKey(name: "slug") String slug,
@JsonKey(name: "profile_photo_url") String profilePhotoUrl,
@JsonKey(name: "role") String role,
@JsonKey(name: "roles") List<String> roles,
@JsonKey(name: "badges") List<BadgeModel> badges,
@JsonKey(name: "subscriptions") List<ProfilePreviewModel> subscriptions,
@JsonKey(name: "subscribers") List<ProfilePreviewModel> subscribers,
@@ -123,7 +123,7 @@ class _$ProfileModelCopyWithImpl<$Res, $Val extends ProfileModel>
Object? isEntitySubscribedByMe = null,
Object? slug = null,
Object? profilePhotoUrl = null,
Object? role = null,
Object? roles = null,
Object? badges = null,
Object? subscriptions = null,
Object? subscribers = null,
@@ -175,10 +175,10 @@ class _$ProfileModelCopyWithImpl<$Res, $Val extends ProfileModel>
? _value.profilePhotoUrl
: profilePhotoUrl // ignore: cast_nullable_to_non_nullable
as String,
role: null == role
? _value.role
: role // ignore: cast_nullable_to_non_nullable
as String,
roles: null == roles
? _value.roles
: roles // ignore: cast_nullable_to_non_nullable
as List<String>,
badges: null == badges
? _value.badges
: badges // ignore: cast_nullable_to_non_nullable
@@ -237,7 +237,7 @@ abstract class _$$ProfileModelImplCopyWith<$Res>
@JsonKey(name: 'is_entity_subscribed_by_me') bool isEntitySubscribedByMe,
@JsonKey(name: "slug") String slug,
@JsonKey(name: "profile_photo_url") String profilePhotoUrl,
@JsonKey(name: "role") String role,
@JsonKey(name: "roles") List<String> roles,
@JsonKey(name: "badges") List<BadgeModel> badges,
@JsonKey(name: "subscriptions") List<ProfilePreviewModel> subscriptions,
@JsonKey(name: "subscribers") List<ProfilePreviewModel> subscribers,
@@ -273,7 +273,7 @@ class __$$ProfileModelImplCopyWithImpl<$Res>
Object? isEntitySubscribedByMe = null,
Object? slug = null,
Object? profilePhotoUrl = null,
Object? role = null,
Object? roles = null,
Object? badges = null,
Object? subscriptions = null,
Object? subscribers = null,
@@ -325,10 +325,10 @@ class __$$ProfileModelImplCopyWithImpl<$Res>
? _value.profilePhotoUrl
: profilePhotoUrl // ignore: cast_nullable_to_non_nullable
as String,
role: null == role
? _value.role
: role // ignore: cast_nullable_to_non_nullable
as String,
roles: null == roles
? _value._roles
: roles // ignore: cast_nullable_to_non_nullable
as List<String>,
badges: null == badges
? _value._badges
: badges // ignore: cast_nullable_to_non_nullable
@@ -369,7 +369,7 @@ class _$ProfileModelImpl implements _ProfileModel {
required this.isEntitySubscribedByMe,
@JsonKey(name: "slug") required this.slug,
@JsonKey(name: "profile_photo_url") required this.profilePhotoUrl,
@JsonKey(name: "role") required this.role,
@JsonKey(name: "roles") required final List<String> roles,
@JsonKey(name: "badges") required final List<BadgeModel> badges,
@JsonKey(name: "subscriptions")
required final List<ProfilePreviewModel> subscriptions,
@@ -378,7 +378,8 @@ class _$ProfileModelImpl implements _ProfileModel {
@JsonKey(name: "education_resource") this.educationResource,
@JsonKey(name: "cert_photos")
final List<DiplomasAndCertificatesModel>? diplomasAndCertificates})
: _badges = badges,
: _roles = roles,
_badges = badges,
_subscriptions = subscriptions,
_subscribers = subscribers,
_diplomasAndCertificates = diplomasAndCertificates;
@@ -419,9 +420,15 @@ class _$ProfileModelImpl implements _ProfileModel {
@override
@JsonKey(name: "profile_photo_url")
final String profilePhotoUrl;
final List<String> _roles;
@override
@JsonKey(name: "role")
final String role;
@JsonKey(name: "roles")
List<String> get roles {
if (_roles is EqualUnmodifiableListView) return _roles;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_roles);
}
final List<BadgeModel> _badges;
@override
@JsonKey(name: "badges")
@@ -466,7 +473,7 @@ class _$ProfileModelImpl implements _ProfileModel {
@override
String toString() {
return 'ProfileModel(id: $id, name: $name, email: $email, ratingPlace: $ratingPlace, emailVerifiedAt: $emailVerifiedAt, createdAt: $createdAt, updatedAt: $updatedAt, isPublicProfile: $isPublicProfile, isEntitySubscribedByMe: $isEntitySubscribedByMe, slug: $slug, profilePhotoUrl: $profilePhotoUrl, role: $role, badges: $badges, subscriptions: $subscriptions, subscribers: $subscribers, educationResource: $educationResource, diplomasAndCertificates: $diplomasAndCertificates)';
return 'ProfileModel(id: $id, name: $name, email: $email, ratingPlace: $ratingPlace, emailVerifiedAt: $emailVerifiedAt, createdAt: $createdAt, updatedAt: $updatedAt, isPublicProfile: $isPublicProfile, isEntitySubscribedByMe: $isEntitySubscribedByMe, slug: $slug, profilePhotoUrl: $profilePhotoUrl, roles: $roles, badges: $badges, subscriptions: $subscriptions, subscribers: $subscribers, educationResource: $educationResource, diplomasAndCertificates: $diplomasAndCertificates)';
}
@override
@@ -492,7 +499,7 @@ class _$ProfileModelImpl implements _ProfileModel {
(identical(other.slug, slug) || other.slug == slug) &&
(identical(other.profilePhotoUrl, profilePhotoUrl) ||
other.profilePhotoUrl == profilePhotoUrl) &&
(identical(other.role, role) || other.role == role) &&
const DeepCollectionEquality().equals(other._roles, _roles) &&
const DeepCollectionEquality().equals(other._badges, _badges) &&
const DeepCollectionEquality()
.equals(other._subscriptions, _subscriptions) &&
@@ -519,7 +526,7 @@ class _$ProfileModelImpl implements _ProfileModel {
isEntitySubscribedByMe,
slug,
profilePhotoUrl,
role,
const DeepCollectionEquality().hash(_roles),
const DeepCollectionEquality().hash(_badges),
const DeepCollectionEquality().hash(_subscriptions),
const DeepCollectionEquality().hash(_subscribers),
@@ -556,7 +563,7 @@ abstract class _ProfileModel implements ProfileModel {
required final bool isEntitySubscribedByMe,
@JsonKey(name: "slug") required final String slug,
@JsonKey(name: "profile_photo_url") required final String profilePhotoUrl,
@JsonKey(name: "role") required final String role,
@JsonKey(name: "roles") required final List<String> roles,
@JsonKey(name: "badges") required final List<BadgeModel> badges,
@JsonKey(name: "subscriptions")
required final List<ProfilePreviewModel> subscriptions,
@@ -605,8 +612,8 @@ abstract class _ProfileModel implements ProfileModel {
@JsonKey(name: "profile_photo_url")
String get profilePhotoUrl;
@override
@JsonKey(name: "role")
String get role;
@JsonKey(name: "roles")
List<String> get roles;
@override
@JsonKey(name: "badges")
List<BadgeModel> get badges;

View File

@@ -25,7 +25,7 @@ _$ProfileModelImpl _$$ProfileModelImplFromJson(Map<String, dynamic> json) =>
isEntitySubscribedByMe: json['is_entity_subscribed_by_me'] as bool,
slug: json['slug'] as String,
profilePhotoUrl: json['profile_photo_url'] as String,
role: json['role'] as String,
roles: (json['roles'] as List<dynamic>).map((e) => e as String).toList(),
badges: (json['badges'] as List<dynamic>)
.map((e) => BadgeModel.fromJson(e as Map<String, dynamic>))
.toList(),
@@ -58,7 +58,7 @@ Map<String, dynamic> _$$ProfileModelImplToJson(_$ProfileModelImpl instance) =>
'is_entity_subscribed_by_me': instance.isEntitySubscribedByMe,
'slug': instance.slug,
'profile_photo_url': instance.profilePhotoUrl,
'role': instance.role,
'roles': instance.roles,
'badges': instance.badges,
'subscriptions': instance.subscriptions,
'subscribers': instance.subscribers,

View File

@@ -81,7 +81,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
if (isFirstFetch) {
canSub = !state.profile.isEntitySubscribedByMe;
if (state.profile.role == 'consultant') {
if (state.profile.roles.contains('consultant')) {
plansCubit..getPlans(state.profile.slug);
}
isFirstFetch = false;
@@ -127,7 +127,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_header(state),
if (state.profile.role == 'consultant')
if (state.profile.roles.contains('consultant'))
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -192,10 +192,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
_subscriptionsAndSubscribers(state),
if (state.profile.badges.isNotEmpty) Padding(padding: EdgeInsets.only(bottom: 16), child: _badges(state)),
if (state.profile.role == 'consultant') _socialLinks(state),
if (state.profile.role == 'consultant') _education(state),
if (state.profile.role == 'consultant') _diplomasAndCertificates(state),
if (state.profile.role == 'consultant') _activePlans(state),
if (state.profile.roles.contains('consultant')) _socialLinks(state),
if (state.profile.roles.contains('consultant')) _education(state),
if (state.profile.roles.contains('consultant')) _diplomasAndCertificates(state),
if (state.profile.roles.contains('consultant')) _activePlans(state),
_blogPosts(state),
],
),
@@ -228,11 +228,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
_subscriptionsAndSubscribers(state),
if (state.profile.badges.isNotEmpty) Padding(padding: EdgeInsets.only(bottom: 16), child: _badges(state)),
if (state.profile.role == 'consultant') _socialLinks(state),
if (state.profile.role == 'consultant') _education(state),
if (state.profile.role == 'consultant') _diplomasAndCertificates(state),
if (state.profile.roles.contains('consultant')) _socialLinks(state),
if (state.profile.roles.contains('consultant')) _education(state),
if (state.profile.roles.contains('consultant')) _diplomasAndCertificates(state),
Padding(padding: EdgeInsets.only(bottom: 16), child: _charts()),
if (state.profile.role == 'consultant') _activePlans(state),
if (state.profile.roles.contains('consultant')) _activePlans(state),
_newBlogPostButton(),
_blogPosts(state),
],
@@ -242,7 +242,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
_activePlans(ProfileStateLoaded state) {
if (state.profile.role != 'consultant') {
if (!state.profile.roles.contains('consultant')) {
return const SizedBox.shrink();
}
return BlocBuilder<PlansCubit, PlansState>(
@@ -372,7 +372,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
_diplomasAndCertificates(ProfileStateLoaded state) {
if (state.profile.role != 'consultant' || state.profile.diplomasAndCertificates == null || state.profile.diplomasAndCertificates!.isEmpty) {
if (!state.profile.roles.contains('consultant') || state.profile.diplomasAndCertificates == null || state.profile.diplomasAndCertificates!.isEmpty) {
return const SizedBox.shrink();
}
return Padding(
@@ -456,7 +456,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
_education(ProfileStateLoaded state) {
if (state.profile.role != 'consultant' ||
if (!state.profile.roles.contains('consultant') ||
state.profile.educationResource?.completedCourses == null ||
state.profile.educationResource?.completedCourses?.length == 0) {
return const SizedBox.shrink();
@@ -549,7 +549,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
_socialLinks(ProfileStateLoaded state) {
if (state.profile.role != 'consultant') {
if (!state.profile.roles.contains('consultant')) {
return const SizedBox.shrink();
}
return Padding(

View File

@@ -84,8 +84,10 @@ class RecipeCreateEntity with _$RecipeCreateEntity {
TypeOfRecipe? typeOfRecipe,
int? countOfPortions,
double? energyInOnePortion,
String? totalCookTime, // hh:mm
String? activeCookTime, // hh:mm
int? totalCookHours,
int? totalCookMinutes,
int? activeCookHours,
int? activeCookMinutes,
String? description,
File? image,
String? videoUrl,
@@ -99,8 +101,8 @@ class RecipeCreateEntity with _$RecipeCreateEntity {
type: typeOfRecipe?.toApiType(),
servings: countOfPortions,
energyPerServing: energyInOnePortion?.toInt(),
totalCookingTime: totalCookTime?.split(':').fold(0, (value, element) => (int.tryParse(element) ?? 0)),
activeCookTime: activeCookTime?.split(':').fold(0, (value, element) => (int.tryParse(element) ?? 0)),
totalCookingTime: ((totalCookHours ?? 0) * 60) + (totalCookMinutes ?? 0),
activeCookTime: ((activeCookHours ?? 0) * 60) + (activeCookMinutes ?? 0),
description: description,
image: image?.path,
video_url: videoUrl,

View File

@@ -20,8 +20,10 @@ mixin _$RecipeCreateEntity {
TypeOfRecipe? get typeOfRecipe => throw _privateConstructorUsedError;
int? get countOfPortions => throw _privateConstructorUsedError;
double? get energyInOnePortion => throw _privateConstructorUsedError;
String? get totalCookTime => throw _privateConstructorUsedError; // hh:mm
String? get activeCookTime => throw _privateConstructorUsedError; // hh:mm
int? get totalCookHours => throw _privateConstructorUsedError;
int? get totalCookMinutes => throw _privateConstructorUsedError;
int? get activeCookHours => throw _privateConstructorUsedError;
int? get activeCookMinutes => throw _privateConstructorUsedError;
String? get description => throw _privateConstructorUsedError;
File? get image => throw _privateConstructorUsedError;
String? get videoUrl => throw _privateConstructorUsedError;
@@ -47,8 +49,10 @@ abstract class $RecipeCreateEntityCopyWith<$Res> {
TypeOfRecipe? typeOfRecipe,
int? countOfPortions,
double? energyInOnePortion,
String? totalCookTime,
String? activeCookTime,
int? totalCookHours,
int? totalCookMinutes,
int? activeCookHours,
int? activeCookMinutes,
String? description,
File? image,
String? videoUrl,
@@ -76,8 +80,10 @@ class _$RecipeCreateEntityCopyWithImpl<$Res, $Val extends RecipeCreateEntity>
Object? typeOfRecipe = freezed,
Object? countOfPortions = freezed,
Object? energyInOnePortion = freezed,
Object? totalCookTime = freezed,
Object? activeCookTime = freezed,
Object? totalCookHours = freezed,
Object? totalCookMinutes = freezed,
Object? activeCookHours = freezed,
Object? activeCookMinutes = freezed,
Object? description = freezed,
Object? image = freezed,
Object? videoUrl = freezed,
@@ -102,14 +108,22 @@ class _$RecipeCreateEntityCopyWithImpl<$Res, $Val extends RecipeCreateEntity>
? _value.energyInOnePortion
: energyInOnePortion // ignore: cast_nullable_to_non_nullable
as double?,
totalCookTime: freezed == totalCookTime
? _value.totalCookTime
: totalCookTime // ignore: cast_nullable_to_non_nullable
as String?,
activeCookTime: freezed == activeCookTime
? _value.activeCookTime
: activeCookTime // ignore: cast_nullable_to_non_nullable
as String?,
totalCookHours: freezed == totalCookHours
? _value.totalCookHours
: totalCookHours // ignore: cast_nullable_to_non_nullable
as int?,
totalCookMinutes: freezed == totalCookMinutes
? _value.totalCookMinutes
: totalCookMinutes // ignore: cast_nullable_to_non_nullable
as int?,
activeCookHours: freezed == activeCookHours
? _value.activeCookHours
: activeCookHours // ignore: cast_nullable_to_non_nullable
as int?,
activeCookMinutes: freezed == activeCookMinutes
? _value.activeCookMinutes
: activeCookMinutes // ignore: cast_nullable_to_non_nullable
as int?,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
@@ -151,8 +165,10 @@ abstract class _$$RecipeCreateEntityImplCopyWith<$Res>
TypeOfRecipe? typeOfRecipe,
int? countOfPortions,
double? energyInOnePortion,
String? totalCookTime,
String? activeCookTime,
int? totalCookHours,
int? totalCookMinutes,
int? activeCookHours,
int? activeCookMinutes,
String? description,
File? image,
String? videoUrl,
@@ -178,8 +194,10 @@ class __$$RecipeCreateEntityImplCopyWithImpl<$Res>
Object? typeOfRecipe = freezed,
Object? countOfPortions = freezed,
Object? energyInOnePortion = freezed,
Object? totalCookTime = freezed,
Object? activeCookTime = freezed,
Object? totalCookHours = freezed,
Object? totalCookMinutes = freezed,
Object? activeCookHours = freezed,
Object? activeCookMinutes = freezed,
Object? description = freezed,
Object? image = freezed,
Object? videoUrl = freezed,
@@ -204,14 +222,22 @@ class __$$RecipeCreateEntityImplCopyWithImpl<$Res>
? _value.energyInOnePortion
: energyInOnePortion // ignore: cast_nullable_to_non_nullable
as double?,
totalCookTime: freezed == totalCookTime
? _value.totalCookTime
: totalCookTime // ignore: cast_nullable_to_non_nullable
as String?,
activeCookTime: freezed == activeCookTime
? _value.activeCookTime
: activeCookTime // ignore: cast_nullable_to_non_nullable
as String?,
totalCookHours: freezed == totalCookHours
? _value.totalCookHours
: totalCookHours // ignore: cast_nullable_to_non_nullable
as int?,
totalCookMinutes: freezed == totalCookMinutes
? _value.totalCookMinutes
: totalCookMinutes // ignore: cast_nullable_to_non_nullable
as int?,
activeCookHours: freezed == activeCookHours
? _value.activeCookHours
: activeCookHours // ignore: cast_nullable_to_non_nullable
as int?,
activeCookMinutes: freezed == activeCookMinutes
? _value.activeCookMinutes
: activeCookMinutes // ignore: cast_nullable_to_non_nullable
as int?,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
@@ -248,8 +274,10 @@ class _$RecipeCreateEntityImpl extends _RecipeCreateEntity {
this.typeOfRecipe,
this.countOfPortions,
this.energyInOnePortion,
this.totalCookTime,
this.activeCookTime,
this.totalCookHours,
this.totalCookMinutes,
this.activeCookHours,
this.activeCookMinutes,
this.description,
this.image,
this.videoUrl,
@@ -270,11 +298,13 @@ class _$RecipeCreateEntityImpl extends _RecipeCreateEntity {
@override
final double? energyInOnePortion;
@override
final String? totalCookTime;
// hh:mm
final int? totalCookHours;
@override
final String? activeCookTime;
// hh:mm
final int? totalCookMinutes;
@override
final int? activeCookHours;
@override
final int? activeCookMinutes;
@override
final String? description;
@override
@@ -307,7 +337,7 @@ class _$RecipeCreateEntityImpl extends _RecipeCreateEntity {
@override
String toString() {
return 'RecipeCreateEntity(title: $title, typeOfRecipe: $typeOfRecipe, countOfPortions: $countOfPortions, energyInOnePortion: $energyInOnePortion, totalCookTime: $totalCookTime, activeCookTime: $activeCookTime, description: $description, image: $image, videoUrl: $videoUrl, ingredients: $ingredients, steps: $steps, tags: $tags)';
return 'RecipeCreateEntity(title: $title, typeOfRecipe: $typeOfRecipe, countOfPortions: $countOfPortions, energyInOnePortion: $energyInOnePortion, totalCookHours: $totalCookHours, totalCookMinutes: $totalCookMinutes, activeCookHours: $activeCookHours, activeCookMinutes: $activeCookMinutes, description: $description, image: $image, videoUrl: $videoUrl, ingredients: $ingredients, steps: $steps, tags: $tags)';
}
@override
@@ -322,10 +352,14 @@ class _$RecipeCreateEntityImpl extends _RecipeCreateEntity {
other.countOfPortions == countOfPortions) &&
(identical(other.energyInOnePortion, energyInOnePortion) ||
other.energyInOnePortion == energyInOnePortion) &&
(identical(other.totalCookTime, totalCookTime) ||
other.totalCookTime == totalCookTime) &&
(identical(other.activeCookTime, activeCookTime) ||
other.activeCookTime == activeCookTime) &&
(identical(other.totalCookHours, totalCookHours) ||
other.totalCookHours == totalCookHours) &&
(identical(other.totalCookMinutes, totalCookMinutes) ||
other.totalCookMinutes == totalCookMinutes) &&
(identical(other.activeCookHours, activeCookHours) ||
other.activeCookHours == activeCookHours) &&
(identical(other.activeCookMinutes, activeCookMinutes) ||
other.activeCookMinutes == activeCookMinutes) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.image, image) || other.image == image) &&
@@ -344,8 +378,10 @@ class _$RecipeCreateEntityImpl extends _RecipeCreateEntity {
typeOfRecipe,
countOfPortions,
energyInOnePortion,
totalCookTime,
activeCookTime,
totalCookHours,
totalCookMinutes,
activeCookHours,
activeCookMinutes,
description,
image,
videoUrl,
@@ -369,8 +405,10 @@ abstract class _RecipeCreateEntity extends RecipeCreateEntity {
final TypeOfRecipe? typeOfRecipe,
final int? countOfPortions,
final double? energyInOnePortion,
final String? totalCookTime,
final String? activeCookTime,
final int? totalCookHours,
final int? totalCookMinutes,
final int? activeCookHours,
final int? activeCookMinutes,
final String? description,
final File? image,
final String? videoUrl,
@@ -388,9 +426,13 @@ abstract class _RecipeCreateEntity extends RecipeCreateEntity {
@override
double? get energyInOnePortion;
@override
String? get totalCookTime; // hh:mm
int? get totalCookHours;
@override
String? get activeCookTime; // hh:mm
int? get totalCookMinutes;
@override
int? get activeCookHours;
@override
int? get activeCookMinutes;
@override
String? get description;
@override

View File

@@ -101,12 +101,20 @@ class CreateRecipeCubit extends Cubit<CreateRecipeState> {
emit(state.copyWith.entity(energyInOnePortion: energy));
}
replaceTotalTime(String time) {
emit(state.copyWith.entity(totalCookTime: time));
setTotalCookingMinutes(int minutes) {
emit(state.copyWith.entity(totalCookMinutes: minutes));
}
replaceActiveTime(String time) {
emit(state.copyWith.entity(activeCookTime: time));
setTotalCookingHours(int hours) {
emit(state.copyWith.entity(totalCookHours: hours));
}
setActiveCookingMinutes(int minutes) {
emit(state.copyWith.entity(activeCookMinutes: minutes));
}
setActiveCookingHours(int hours) {
emit(state.copyWith.entity(activeCookHours: hours));
}
replaceVideoUrl(String videoUrl) {
@@ -190,7 +198,7 @@ class CreateRecipeCubit extends Cubit<CreateRecipeState> {
}
bool validateActiveCookTime() {
if (state.entity.activeCookTime == null || state.entity.activeCookTime == '00:00') {
if (state.entity.activeCookHours == null && state.entity.activeCookMinutes == null) {
emit(state.copyWith(activeTimeValidationError: 'Поле не заполнено'));
return false;
} else {
@@ -200,7 +208,7 @@ class CreateRecipeCubit extends Cubit<CreateRecipeState> {
}
bool validateTotalCookTime() {
if (state.entity.totalCookTime == null || state.entity.totalCookTime == '00:00') {
if (state.entity.totalCookHours == null || state.entity.totalCookMinutes == null) {
emit(state.copyWith(cookingTimeValidationError: 'Поле не заполнено'));
return false;
} else {

View File

@@ -72,11 +72,9 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
hasError: state.cookingTimeValidationError != null,
textInputType: TextInputType.number,
onChanged: (value) {
if (createRecipeCubit.state.entity.totalCookTime == null) {
createRecipeCubit.replaceTotalTime('${value.padLeft(2, '0')}:00');
} else {
createRecipeCubit.replaceTotalTime('${value.padLeft(2, '0')}:${createRecipeCubit.state.entity.totalCookTime!.substring(3, 5)}');
}
final hours = int.tryParse(value);
if (hours == null) return;
createRecipeCubit.setTotalCookingHours(hours);
if (state.cookingTimeValidationError != null) {
createRecipeCubit.validateTotalCookTime();
}
@@ -100,11 +98,9 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
hasError: state.cookingTimeValidationError != null,
textInputType: TextInputType.number,
onChanged: (value) {
if (createRecipeCubit.state.entity.totalCookTime == null) {
createRecipeCubit.replaceTotalTime('00:${value.padLeft(2, '0')}');
} else {
createRecipeCubit.replaceTotalTime('${createRecipeCubit.state.entity.totalCookTime!.substring(0, 2)}:${value.padLeft(2, '0')}');
}
final minutes = int.tryParse(value);
if (minutes == null) return;
createRecipeCubit.setTotalCookingMinutes(minutes);
if (state.cookingTimeValidationError != null) {
createRecipeCubit.validateTotalCookTime();
}
@@ -162,11 +158,9 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
hasError: state.activeTimeValidationError != null,
textInputType: TextInputType.number,
onChanged: (value) {
if (createRecipeCubit.state.entity.activeCookTime == null) {
createRecipeCubit.replaceActiveTime('${value.padLeft(2, '0')}:00');
} else {
createRecipeCubit.replaceActiveTime('${value.padLeft(2, '0')}:${createRecipeCubit.state.entity.activeCookTime!.substring(3, 5)}');
}
final hours = int.tryParse(value);
if (hours == null) return;
createRecipeCubit.setActiveCookingHours(hours);
if (state.activeTimeValidationError != null) {
createRecipeCubit.validateActiveCookTime();
@@ -191,11 +185,9 @@ class _TimeOfCookWidgetState extends State<TimeOfCookWidget> {
hasError: state.activeTimeValidationError != null,
textInputType: TextInputType.number,
onChanged: (value) {
if (createRecipeCubit.state.entity.activeCookTime == null) {
createRecipeCubit.replaceActiveTime('00:${value.padLeft(2, '0')}');
} else {
createRecipeCubit.replaceActiveTime('${createRecipeCubit.state.entity.activeCookTime!.substring(0, 2)}:${value.padLeft(2, '0')}');
}
final minutes = int.tryParse(value);
if (minutes == null) return;
createRecipeCubit.setActiveCookingMinutes(minutes);
if (state.activeTimeValidationError != null) {
createRecipeCubit.validateActiveCookTime();

View File

@@ -9,11 +9,7 @@ part of 'recipe_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _RecipeService implements RecipeService {
_RecipeService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_RecipeService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -27,22 +23,16 @@ class _RecipeService implements RecipeService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<RecipeModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/recipes/show/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<RecipeModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/recipes/show/${id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late RecipeModel _value;
try {
@@ -60,30 +50,27 @@ class _RecipeService implements RecipeService {
final queryParameters = <String, dynamic>{r'name': name};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<Map<String, List<Product>>>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/diary/product_nutritional_values/filter',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<Map<String, List<Product>>>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/diary/product_nutritional_values/filter',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late Map<String, List<Product>> _value;
try {
_value = _result.data!.map((k, dynamic v) => MapEntry(
_value = _result.data!.map(
(k, dynamic v) => MapEntry(
k,
(v as List)
.map((i) => Product.fromJson(i as Map<String, dynamic>))
.toList()));
.toList(),
),
);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
@@ -97,51 +84,40 @@ class _RecipeService implements RecipeService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = formData;
final _options = _setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/recipes/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<void>(
Options(
method: 'POST',
headers: _headers,
extra: _extra,
contentType: 'multipart/form-data',
)
.compose(
_dio.options,
'/api/recipes/create',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
await _dio.fetch<void>(_options);
}
@override
Future<RecipeModel> editRecipe(
Map<String, Object?> recipe,
String id,
) async {
Future<RecipeModel> editRecipe(Map<String, Object?> recipe, String id) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = FormData.fromMap(recipe);
final _options = _setStreamType<RecipeModel>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/recipes/update/{id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<RecipeModel>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/recipes/update/{id}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late RecipeModel _value;
try {
@@ -159,22 +135,16 @@ class _RecipeService implements RecipeService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<RecipeTagModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/recipes/tags',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<RecipeTagModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/recipes/tags',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late RecipeTagModel _value;
try {
@@ -199,10 +169,7 @@ class _RecipeService implements RecipeService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -9,11 +9,7 @@ part of 'registration_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _RegistrationService implements RegistrationService {
_RegistrationService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_RegistrationService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -22,29 +18,24 @@ class _RegistrationService implements RegistrationService {
final ParseErrorLogger? errorLogger;
@override
Future<Map<String, String>> register(
{required Map<String, dynamic> sheet}) async {
Future<Map<String, String>> register({
required Map<String, dynamic> sheet,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(sheet);
final _options = _setStreamType<Map<String, String>>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/register',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<Map<String, String>>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/register',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late Map<String, String> _value;
try {
@@ -62,22 +53,16 @@ class _RegistrationService implements RegistrationService {
final queryParameters = <String, dynamic>{r'user_address': query};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<LocationModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/location_by_address',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<LocationModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/location_by_address',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late LocationModel _value;
try {
@@ -101,22 +86,16 @@ class _RegistrationService implements RegistrationService {
};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<LocationModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/location_by_coordinate',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<LocationModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/location_by_coordinate',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late LocationModel _value;
try {
@@ -141,10 +120,7 @@ class _RegistrationService implements RegistrationService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -56,7 +56,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
const SizedBox(height: 12),
_aboutEatvio(state),
const SizedBox(height: 12),
if (state.profile.role != 'consultant')
if (!state.profile.roles.contains('consultant'))
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _becomeConsultantButton(state),

View File

@@ -9,11 +9,7 @@ part of 'settings_service.dart';
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
class _SettingsService implements SettingsService {
_SettingsService(
this._dio, {
this.baseUrl,
this.errorLogger,
});
_SettingsService(this._dio, {this.baseUrl, this.errorLogger});
final Dio _dio;
@@ -27,22 +23,16 @@ class _SettingsService implements SettingsService {
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<ProfileSettingsModel>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/profile/settings',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<ProfileSettingsModel>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/profile/settings',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late ProfileSettingsModel _value;
try {
@@ -55,29 +45,24 @@ class _SettingsService implements SettingsService {
}
@override
Future<ProfileSettingsModel> updateProfileSettings(
{required Map<String, dynamic> data}) async {
Future<ProfileSettingsModel> updateProfileSettings({
required Map<String, dynamic> data,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(data);
final _options = _setStreamType<ProfileSettingsModel>(Options(
method: 'PUT',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/profile/settings/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<ProfileSettingsModel>(
Options(method: 'PUT', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/profile/settings/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late ProfileSettingsModel _value;
try {
@@ -90,29 +75,24 @@ class _SettingsService implements SettingsService {
}
@override
Future<ProfileDetailsModel> updateProfileDetails(
{required Map<String, dynamic> data}) async {
Future<ProfileDetailsModel> updateProfileDetails({
required Map<String, dynamic> data,
}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(data);
final _options = _setStreamType<ProfileDetailsModel>(Options(
method: 'PUT',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/api/profile/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
)));
final _options = _setStreamType<ProfileDetailsModel>(
Options(method: 'PUT', headers: _headers, extra: _extra)
.compose(
_dio.options,
'/api/profile/update',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
late ProfileDetailsModel _value;
try {
@@ -137,10 +117,7 @@ class _SettingsService implements SettingsService {
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}

View File

@@ -23,7 +23,7 @@ void main() {
isEntitySubscribedByMe: false,
slug: 'slug',
profilePhotoUrl: '',
role: 'user',
roles: ['user'],
badges: [],
subscriptions: [],
subscribers: [],