diff --git a/assets/icons/arrow_down2.svg b/assets/icons/arrow_down2.svg new file mode 100644 index 00000000..852a4b80 --- /dev/null +++ b/assets/icons/arrow_down2.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index ad931701..7f5a024d 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -11,6 +11,7 @@ import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.da import 'package:eatvio_app/features/complaining/presentation/complaining_screen.dart'; import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/become_consultant_screen.dart'; import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/stepper_become_consultant_screen.dart'; +import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart'; import 'package:eatvio_app/features/diary/presentation/pages/diary_screen.dart'; import 'package:eatvio_app/features/diets/presentation/pages/about_diet_screen.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; @@ -249,6 +250,11 @@ class AppRouter { name: 'complainingScreen', builder: (context, state) => ComplainingScreen(), ), + GoRoute( + path: CreateDietScreen.path, + name: CreateDietScreen.name, + builder: (context, state) => CreateDietScreen(), + ), ], ); } diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index cd75ebcc..44378eb1 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -1,7 +1,7 @@ import 'package:dio/dio.dart'; import 'package:eatvio_app/core/const.dart'; -import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart'; -import 'package:eatvio_app/core/data/diet/services/diet_service.dart'; +import 'package:eatvio_app/features/diets/repositories/diet_repository.dart'; +import 'package:eatvio_app/features/diets/services/diet_service.dart'; import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart'; import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart'; import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart'; diff --git a/lib/features/create_diet/models/create_diet_model.dart b/lib/features/create_diet/models/create_diet_model.dart new file mode 100644 index 00000000..6517e784 --- /dev/null +++ b/lib/features/create_diet/models/create_diet_model.dart @@ -0,0 +1,35 @@ +import 'dart:io'; + +import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart'; +import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_diet_model.freezed.dart'; + +@freezed +class CreateDietModel with _$CreateDietModel{ + const CreateDietModel._(); + + const factory CreateDietModel({ + String? name, + String? details, + String? state, + int? duration, + List? type, + File? image, + List>>? dailySchedule, + }) = _CreateDietModel; + + Future> toCreationJson() async => { + 'name': name, + 'duration': duration, + 'state': state, + 'type': type, + 'details': details, + 'image': image != null ? await ImageCompressUtility.compressFile(image!) : null, + }; + + Map toDailyScheduleCreationJson() => { + 'daily_schedule': dailySchedule, + }; +} \ No newline at end of file diff --git a/lib/features/create_diet/models/create_diet_model.freezed.dart b/lib/features/create_diet/models/create_diet_model.freezed.dart new file mode 100644 index 00000000..bc3eccbb --- /dev/null +++ b/lib/features/create_diet/models/create_diet_model.freezed.dart @@ -0,0 +1,299 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'create_diet_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$CreateDietModel { + String? get name => throw _privateConstructorUsedError; + String? get details => throw _privateConstructorUsedError; + String? get state => throw _privateConstructorUsedError; + int? get duration => throw _privateConstructorUsedError; + List? get type => throw _privateConstructorUsedError; + File? get image => throw _privateConstructorUsedError; + List>>? get dailySchedule => + throw _privateConstructorUsedError; + + /// Create a copy of CreateDietModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CreateDietModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CreateDietModelCopyWith<$Res> { + factory $CreateDietModelCopyWith( + CreateDietModel value, $Res Function(CreateDietModel) then) = + _$CreateDietModelCopyWithImpl<$Res, CreateDietModel>; + @useResult + $Res call( + {String? name, + String? details, + String? state, + int? duration, + List? type, + File? image, + List>>? dailySchedule}); +} + +/// @nodoc +class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel> + implements $CreateDietModelCopyWith<$Res> { + _$CreateDietModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CreateDietModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = freezed, + Object? details = freezed, + Object? state = freezed, + Object? duration = freezed, + Object? type = freezed, + Object? image = freezed, + Object? dailySchedule = freezed, + }) { + return _then(_value.copyWith( + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + details: freezed == details + ? _value.details + : details // ignore: cast_nullable_to_non_nullable + as String?, + state: freezed == state + ? _value.state + : state // ignore: cast_nullable_to_non_nullable + as String?, + duration: freezed == duration + ? _value.duration + : duration // ignore: cast_nullable_to_non_nullable + as int?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as List?, + image: freezed == image + ? _value.image + : image // ignore: cast_nullable_to_non_nullable + as File?, + dailySchedule: freezed == dailySchedule + ? _value.dailySchedule + : dailySchedule // ignore: cast_nullable_to_non_nullable + as List>>?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$CreateDietModelImplCopyWith<$Res> + implements $CreateDietModelCopyWith<$Res> { + factory _$$CreateDietModelImplCopyWith(_$CreateDietModelImpl value, + $Res Function(_$CreateDietModelImpl) then) = + __$$CreateDietModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String? name, + String? details, + String? state, + int? duration, + List? type, + File? image, + List>>? dailySchedule}); +} + +/// @nodoc +class __$$CreateDietModelImplCopyWithImpl<$Res> + extends _$CreateDietModelCopyWithImpl<$Res, _$CreateDietModelImpl> + implements _$$CreateDietModelImplCopyWith<$Res> { + __$$CreateDietModelImplCopyWithImpl( + _$CreateDietModelImpl _value, $Res Function(_$CreateDietModelImpl) _then) + : super(_value, _then); + + /// Create a copy of CreateDietModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = freezed, + Object? details = freezed, + Object? state = freezed, + Object? duration = freezed, + Object? type = freezed, + Object? image = freezed, + Object? dailySchedule = freezed, + }) { + return _then(_$CreateDietModelImpl( + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + details: freezed == details + ? _value.details + : details // ignore: cast_nullable_to_non_nullable + as String?, + state: freezed == state + ? _value.state + : state // ignore: cast_nullable_to_non_nullable + as String?, + duration: freezed == duration + ? _value.duration + : duration // ignore: cast_nullable_to_non_nullable + as int?, + type: freezed == type + ? _value._type + : type // ignore: cast_nullable_to_non_nullable + as List?, + image: freezed == image + ? _value.image + : image // ignore: cast_nullable_to_non_nullable + as File?, + dailySchedule: freezed == dailySchedule + ? _value._dailySchedule + : dailySchedule // ignore: cast_nullable_to_non_nullable + as List>>?, + )); + } +} + +/// @nodoc + +class _$CreateDietModelImpl extends _CreateDietModel { + const _$CreateDietModelImpl( + {this.name, + this.details, + this.state, + this.duration, + final List? type, + this.image, + final List>>? dailySchedule}) + : _type = type, + _dailySchedule = dailySchedule, + super._(); + + @override + final String? name; + @override + final String? details; + @override + final String? state; + @override + final int? duration; + final List? _type; + @override + List? get type { + final value = _type; + if (value == null) return null; + if (_type is EqualUnmodifiableListView) return _type; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + final File? image; + final List>>? _dailySchedule; + @override + List>>? get dailySchedule { + final value = _dailySchedule; + if (value == null) return null; + if (_dailySchedule is EqualUnmodifiableListView) return _dailySchedule; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'CreateDietModel(name: $name, details: $details, state: $state, duration: $duration, type: $type, image: $image, dailySchedule: $dailySchedule)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CreateDietModelImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.details, details) || other.details == details) && + (identical(other.state, state) || other.state == state) && + (identical(other.duration, duration) || + other.duration == duration) && + const DeepCollectionEquality().equals(other._type, _type) && + (identical(other.image, image) || other.image == image) && + const DeepCollectionEquality() + .equals(other._dailySchedule, _dailySchedule)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + name, + details, + state, + duration, + const DeepCollectionEquality().hash(_type), + image, + const DeepCollectionEquality().hash(_dailySchedule)); + + /// Create a copy of CreateDietModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CreateDietModelImplCopyWith<_$CreateDietModelImpl> get copyWith => + __$$CreateDietModelImplCopyWithImpl<_$CreateDietModelImpl>( + this, _$identity); +} + +abstract class _CreateDietModel extends CreateDietModel { + const factory _CreateDietModel( + {final String? name, + final String? details, + final String? state, + final int? duration, + final List? type, + final File? image, + final List>>? dailySchedule}) = + _$CreateDietModelImpl; + const _CreateDietModel._() : super._(); + + @override + String? get name; + @override + String? get details; + @override + String? get state; + @override + int? get duration; + @override + List? get type; + @override + File? get image; + @override + List>>? get dailySchedule; + + /// Create a copy of CreateDietModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CreateDietModelImplCopyWith<_$CreateDietModelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/create_diet/presentation/create_diet_screen.dart b/lib/features/create_diet/presentation/create_diet_screen.dart new file mode 100644 index 00000000..81db4990 --- /dev/null +++ b/lib/features/create_diet/presentation/create_diet_screen.dart @@ -0,0 +1,12 @@ +import 'package:flutter/widgets.dart'; + +class CreateDietScreen extends StatelessWidget { + static const name = 'createDietScreen'; + static const path = '/create-diet-screen'; + const CreateDietScreen({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} \ No newline at end of file diff --git a/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart b/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart new file mode 100644 index 00000000..bc093d41 --- /dev/null +++ b/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart @@ -0,0 +1,37 @@ +import 'dart:io'; + +import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart'; +import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class CreateDietCubit extends Cubit { + CreateDietCubit() : super(CreateDietState.initial()); + + void setDetails(String text) { + emit(state.copyWith(dietData: state.dietData.copyWith(details: text))); + } + + void setName(String name) { + emit(state.copyWith(dietData: state.dietData.copyWith(name: name))); + } + + void setDuration(int duration) { + emit(state.copyWith(dietData: state.dietData.copyWith(duration: duration))); + } + + void setImage(File image) { + emit(state.copyWith(dietData: state.dietData.copyWith(image: image))); + } + + void setDailySchedule(List>> dailySchedule) { + emit(state.copyWith(dietData: state.dietData.copyWith(dailySchedule: dailySchedule))); + } + + void setDietState(String dietState) { + emit(state.copyWith(dietData: state.dietData.copyWith(state: dietState))); + } + + void setDietType(List type) { + emit(state.copyWith(dietData: state.dietData.copyWith(type: type))); + } +} diff --git a/lib/features/create_diet/presentation/cubit/create_diet_state.dart b/lib/features/create_diet/presentation/cubit/create_diet_state.dart new file mode 100644 index 00000000..61ac70e9 --- /dev/null +++ b/lib/features/create_diet/presentation/cubit/create_diet_state.dart @@ -0,0 +1,15 @@ +import 'package:eatvio_app/features/create_diet/models/create_diet_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'create_diet_state.freezed.dart'; + +@freezed +class CreateDietState with _$CreateDietState { + const factory CreateDietState({ + required bool isLoading, + required String? errorMessage, + required CreateDietModel dietData, + }) = _CreateDietState; + + factory CreateDietState.initial() => CreateDietState(isLoading: false, errorMessage: null, dietData: CreateDietModel()); +} diff --git a/lib/features/create_diet/presentation/cubit/create_diet_state.freezed.dart b/lib/features/create_diet/presentation/cubit/create_diet_state.freezed.dart new file mode 100644 index 00000000..0a540986 --- /dev/null +++ b/lib/features/create_diet/presentation/cubit/create_diet_state.freezed.dart @@ -0,0 +1,201 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'create_diet_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$CreateDietState { + bool get isLoading => throw _privateConstructorUsedError; + String? get errorMessage => throw _privateConstructorUsedError; + CreateDietModel get dietData => throw _privateConstructorUsedError; + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CreateDietStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CreateDietStateCopyWith<$Res> { + factory $CreateDietStateCopyWith( + CreateDietState value, $Res Function(CreateDietState) then) = + _$CreateDietStateCopyWithImpl<$Res, CreateDietState>; + @useResult + $Res call({bool isLoading, String? errorMessage, CreateDietModel dietData}); + + $CreateDietModelCopyWith<$Res> get dietData; +} + +/// @nodoc +class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState> + implements $CreateDietStateCopyWith<$Res> { + _$CreateDietStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? isLoading = null, + Object? errorMessage = freezed, + Object? dietData = null, + }) { + return _then(_value.copyWith( + isLoading: null == isLoading + ? _value.isLoading + : isLoading // ignore: cast_nullable_to_non_nullable + as bool, + errorMessage: freezed == errorMessage + ? _value.errorMessage + : errorMessage // ignore: cast_nullable_to_non_nullable + as String?, + dietData: null == dietData + ? _value.dietData + : dietData // ignore: cast_nullable_to_non_nullable + as CreateDietModel, + ) as $Val); + } + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $CreateDietModelCopyWith<$Res> get dietData { + return $CreateDietModelCopyWith<$Res>(_value.dietData, (value) { + return _then(_value.copyWith(dietData: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$CreateDietStateImplCopyWith<$Res> + implements $CreateDietStateCopyWith<$Res> { + factory _$$CreateDietStateImplCopyWith(_$CreateDietStateImpl value, + $Res Function(_$CreateDietStateImpl) then) = + __$$CreateDietStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({bool isLoading, String? errorMessage, CreateDietModel dietData}); + + @override + $CreateDietModelCopyWith<$Res> get dietData; +} + +/// @nodoc +class __$$CreateDietStateImplCopyWithImpl<$Res> + extends _$CreateDietStateCopyWithImpl<$Res, _$CreateDietStateImpl> + implements _$$CreateDietStateImplCopyWith<$Res> { + __$$CreateDietStateImplCopyWithImpl( + _$CreateDietStateImpl _value, $Res Function(_$CreateDietStateImpl) _then) + : super(_value, _then); + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? isLoading = null, + Object? errorMessage = freezed, + Object? dietData = null, + }) { + return _then(_$CreateDietStateImpl( + isLoading: null == isLoading + ? _value.isLoading + : isLoading // ignore: cast_nullable_to_non_nullable + as bool, + errorMessage: freezed == errorMessage + ? _value.errorMessage + : errorMessage // ignore: cast_nullable_to_non_nullable + as String?, + dietData: null == dietData + ? _value.dietData + : dietData // ignore: cast_nullable_to_non_nullable + as CreateDietModel, + )); + } +} + +/// @nodoc + +class _$CreateDietStateImpl implements _CreateDietState { + const _$CreateDietStateImpl( + {required this.isLoading, + required this.errorMessage, + required this.dietData}); + + @override + final bool isLoading; + @override + final String? errorMessage; + @override + final CreateDietModel dietData; + + @override + String toString() { + return 'CreateDietState(isLoading: $isLoading, errorMessage: $errorMessage, dietData: $dietData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CreateDietStateImpl && + (identical(other.isLoading, isLoading) || + other.isLoading == isLoading) && + (identical(other.errorMessage, errorMessage) || + other.errorMessage == errorMessage) && + (identical(other.dietData, dietData) || + other.dietData == dietData)); + } + + @override + int get hashCode => + Object.hash(runtimeType, isLoading, errorMessage, dietData); + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CreateDietStateImplCopyWith<_$CreateDietStateImpl> get copyWith => + __$$CreateDietStateImplCopyWithImpl<_$CreateDietStateImpl>( + this, _$identity); +} + +abstract class _CreateDietState implements CreateDietState { + const factory _CreateDietState( + {required final bool isLoading, + required final String? errorMessage, + required final CreateDietModel dietData}) = _$CreateDietStateImpl; + + @override + bool get isLoading; + @override + String? get errorMessage; + @override + CreateDietModel get dietData; + + /// Create a copy of CreateDietState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CreateDietStateImplCopyWith<_$CreateDietStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/create_diet/services/create_diet_service.dart b/lib/features/create_diet/services/create_diet_service.dart new file mode 100644 index 00000000..93ec038d --- /dev/null +++ b/lib/features/create_diet/services/create_diet_service.dart @@ -0,0 +1,12 @@ +import 'package:dio/dio.dart'; +import 'package:retrofit/retrofit.dart'; + +part 'create_diet_service.g.dart'; + +@RestApi() +abstract class CreateDietService { + + factory CreateDietService(Dio dio, {String baseUrl}) = _CreateDietService; + +} + \ No newline at end of file diff --git a/lib/features/create_diet/services/create_diet_service.g.dart b/lib/features/create_diet/services/create_diet_service.g.dart new file mode 100644 index 00000000..a706620d --- /dev/null +++ b/lib/features/create_diet/services/create_diet_service.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_diet_service.dart'; + +// ************************************************************************** +// RetrofitGenerator +// ************************************************************************** + +// 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, + }); + + final Dio _dio; + + String? baseUrl; + + final ParseErrorLogger? errorLogger; + + RequestOptions _setStreamType(RequestOptions requestOptions) { + if (T != dynamic && + !(requestOptions.responseType == ResponseType.bytes || + requestOptions.responseType == ResponseType.stream)) { + if (T == String) { + requestOptions.responseType = ResponseType.plain; + } else { + requestOptions.responseType = ResponseType.json; + } + } + return requestOptions; + } + + String _combineBaseUrls( + String dioBaseUrl, + String? baseUrl, + ) { + if (baseUrl == null || baseUrl.trim().isEmpty) { + return dioBaseUrl; + } + + final url = Uri.parse(baseUrl); + + if (url.isAbsolute) { + return url.toString(); + } + + return Uri.parse(dioBaseUrl).resolveUri(url).toString(); + } +} diff --git a/lib/core/data/diet/models/diet_likes_model.dart b/lib/features/diets/models/diet_likes_model.dart similarity index 100% rename from lib/core/data/diet/models/diet_likes_model.dart rename to lib/features/diets/models/diet_likes_model.dart diff --git a/lib/core/data/diet/models/diet_likes_model.freezed.dart b/lib/features/diets/models/diet_likes_model.freezed.dart similarity index 100% rename from lib/core/data/diet/models/diet_likes_model.freezed.dart rename to lib/features/diets/models/diet_likes_model.freezed.dart diff --git a/lib/core/data/diet/models/diet_likes_model.g.dart b/lib/features/diets/models/diet_likes_model.g.dart similarity index 100% rename from lib/core/data/diet/models/diet_likes_model.g.dart rename to lib/features/diets/models/diet_likes_model.g.dart diff --git a/lib/features/diets/presentation/bloc/about_diet_cubit.dart b/lib/features/diets/presentation/bloc/about_diet_cubit.dart index 14fa564b..470da0de 100644 --- a/lib/features/diets/presentation/bloc/about_diet_cubit.dart +++ b/lib/features/diets/presentation/bloc/about_diet_cubit.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:developer'; import 'package:easy_debounce/easy_debounce.dart'; -import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart'; +import 'package:eatvio_app/features/diets/repositories/diet_repository.dart'; import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_state.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/features/diets/presentation/pages/about_diet_screen.dart b/lib/features/diets/presentation/pages/about_diet_screen.dart index e3053468..a229618d 100644 --- a/lib/features/diets/presentation/pages/about_diet_screen.dart +++ b/lib/features/diets/presentation/pages/about_diet_screen.dart @@ -560,7 +560,12 @@ class _AboutDietScreenState extends State { ], ), ), - CpfcContainer(calories: 0, protein: 0, fat: 0, carbohydrates: 0), + CpfcContainer( + calories: widget.diet.dailyNutrition[dayNumber].energy, + protein: widget.diet.dailyNutrition[dayNumber].proteins, + fat: widget.diet.dailyNutrition[dayNumber].fats, + carbohydrates: widget.diet.dailyNutrition[dayNumber].carbohydrates, + ), ], ), ), diff --git a/lib/features/diets/presentation/widgets/cpfc_container.dart b/lib/features/diets/presentation/widgets/cpfc_container.dart index 113c689d..d4663910 100644 --- a/lib/features/diets/presentation/widgets/cpfc_container.dart +++ b/lib/features/diets/presentation/widgets/cpfc_container.dart @@ -9,7 +9,7 @@ class CpfcContainer extends StatelessWidget { final double protein; final double fat; final double carbohydrates; - + final int roundDigit = 1; @override Widget build(BuildContext context) { final s = S.of(context); @@ -21,25 +21,25 @@ class CpfcContainer extends StatelessWidget { children: [ Column( children: [ - Text('$calories', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), + Text('${calories.toStringAsFixed(roundDigit)}', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), Text(s.calories, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)), ], ), Column( children: [ - Text('$protein', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), + Text('${protein.toStringAsFixed(roundDigit)}', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), Text(s.proteins, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)), ], ), Column( children: [ - Text('$fat', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), + Text('${fat.toStringAsFixed(roundDigit)}', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), Text(s.fats, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)), ], ), Column( children: [ - Text('$carbohydrates', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), + Text('${carbohydrates.toStringAsFixed(roundDigit)}', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)), Text(s.carbohydrates, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)), ], ), diff --git a/lib/core/data/diet/repositories/diet_repository.dart b/lib/features/diets/repositories/diet_repository.dart similarity index 95% rename from lib/core/data/diet/repositories/diet_repository.dart rename to lib/features/diets/repositories/diet_repository.dart index aff946b7..142ce800 100644 --- a/lib/core/data/diet/repositories/diet_repository.dart +++ b/lib/features/diets/repositories/diet_repository.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:eatvio_app/core/data/diet/models/diet_likes_model.dart'; -import 'package:eatvio_app/core/data/diet/services/diet_service.dart'; +import 'package:eatvio_app/features/diets/models/diet_likes_model.dart'; +import 'package:eatvio_app/features/diets/services/diet_service.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:equatable/equatable.dart'; diff --git a/lib/core/data/diet/services/diet_service.dart b/lib/features/diets/services/diet_service.dart similarity index 91% rename from lib/core/data/diet/services/diet_service.dart rename to lib/features/diets/services/diet_service.dart index 4baffdcb..0d9aebc3 100644 --- a/lib/core/data/diet/services/diet_service.dart +++ b/lib/features/diets/services/diet_service.dart @@ -1,5 +1,5 @@ import 'package:dio/dio.dart'; -import 'package:eatvio_app/core/data/diet/models/diet_likes_model.dart'; +import 'package:eatvio_app/features/diets/models/diet_likes_model.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:retrofit/retrofit.dart'; diff --git a/lib/core/data/diet/services/diet_service.g.dart b/lib/features/diets/services/diet_service.g.dart similarity index 100% rename from lib/core/data/diet/services/diet_service.g.dart rename to lib/features/diets/services/diet_service.g.dart diff --git a/lib/features/feed/models/diets_pagination_model.dart b/lib/features/feed/models/diets_pagination_model.dart index 462b899d..6fe4f677 100644 --- a/lib/features/feed/models/diets_pagination_model.dart +++ b/lib/features/feed/models/diets_pagination_model.dart @@ -33,10 +33,10 @@ class Diet with _$Diet { @JsonKey(name: "total_comments") required int totalComments, @JsonKey(name: "was_liked_by_me") required bool wasLikedByMe, @JsonKey(name: "is_favorite") required bool isFavorite, + @JsonKey(name: "daily_nutrition") required List dailyNutrition, }) = _Diet; factory Diet.fromJson(Map json) => _$DietFromJson(json); - } @freezed @@ -97,3 +97,15 @@ class EnumValues { return reverseMap; } } + +@freezed +class DailyNutrition with _$DailyNutrition { + const factory DailyNutrition({ + @JsonKey(name: 'energy') required double energy, + @JsonKey(name: 'proteins') required double proteins, + @JsonKey(name: 'fats') required double fats, + @JsonKey(name: 'carbohydrates') required double carbohydrates, + }) = _DailyNutrition; + + factory DailyNutrition.fromJson(Map json) => _$DailyNutritionFromJson(json); +} diff --git a/lib/features/feed/models/diets_pagination_model.freezed.dart b/lib/features/feed/models/diets_pagination_model.freezed.dart index 0bbb9b25..38789091 100644 --- a/lib/features/feed/models/diets_pagination_model.freezed.dart +++ b/lib/features/feed/models/diets_pagination_model.freezed.dart @@ -288,6 +288,8 @@ mixin _$Diet { bool get wasLikedByMe => throw _privateConstructorUsedError; @JsonKey(name: "is_favorite") bool get isFavorite => throw _privateConstructorUsedError; + @JsonKey(name: "daily_nutrition") + List get dailyNutrition => throw _privateConstructorUsedError; /// Serializes this Diet to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -318,7 +320,8 @@ abstract class $DietCopyWith<$Res> { @JsonKey(name: "total_views") int totalViews, @JsonKey(name: "total_comments") int totalComments, @JsonKey(name: "was_liked_by_me") bool wasLikedByMe, - @JsonKey(name: "is_favorite") bool isFavorite}); + @JsonKey(name: "is_favorite") bool isFavorite, + @JsonKey(name: "daily_nutrition") List dailyNutrition}); $DietTypeCopyWith<$Res> get type; $AuthorCopyWith<$Res> get author; @@ -353,6 +356,7 @@ class _$DietCopyWithImpl<$Res, $Val extends Diet> Object? totalComments = null, Object? wasLikedByMe = null, Object? isFavorite = null, + Object? dailyNutrition = null, }) { return _then(_value.copyWith( id: null == id @@ -411,6 +415,10 @@ class _$DietCopyWithImpl<$Res, $Val extends Diet> ? _value.isFavorite : isFavorite // ignore: cast_nullable_to_non_nullable as bool, + dailyNutrition: null == dailyNutrition + ? _value.dailyNutrition + : dailyNutrition // ignore: cast_nullable_to_non_nullable + as List, ) as $Val); } @@ -457,7 +465,8 @@ abstract class _$$DietImplCopyWith<$Res> implements $DietCopyWith<$Res> { @JsonKey(name: "total_views") int totalViews, @JsonKey(name: "total_comments") int totalComments, @JsonKey(name: "was_liked_by_me") bool wasLikedByMe, - @JsonKey(name: "is_favorite") bool isFavorite}); + @JsonKey(name: "is_favorite") bool isFavorite, + @JsonKey(name: "daily_nutrition") List dailyNutrition}); @override $DietTypeCopyWith<$Res> get type; @@ -491,6 +500,7 @@ class __$$DietImplCopyWithImpl<$Res> Object? totalComments = null, Object? wasLikedByMe = null, Object? isFavorite = null, + Object? dailyNutrition = null, }) { return _then(_$DietImpl( id: null == id @@ -549,6 +559,10 @@ class __$$DietImplCopyWithImpl<$Res> ? _value.isFavorite : isFavorite // ignore: cast_nullable_to_non_nullable as bool, + dailyNutrition: null == dailyNutrition + ? _value._dailyNutrition + : dailyNutrition // ignore: cast_nullable_to_non_nullable + as List, )); } } @@ -571,8 +585,11 @@ class _$DietImpl implements _Diet { @JsonKey(name: "total_views") required this.totalViews, @JsonKey(name: "total_comments") required this.totalComments, @JsonKey(name: "was_liked_by_me") required this.wasLikedByMe, - @JsonKey(name: "is_favorite") required this.isFavorite}) - : _dailySchedule = dailySchedule; + @JsonKey(name: "is_favorite") required this.isFavorite, + @JsonKey(name: "daily_nutrition") + required final List dailyNutrition}) + : _dailySchedule = dailySchedule, + _dailyNutrition = dailyNutrition; factory _$DietImpl.fromJson(Map json) => _$$DietImplFromJson(json); @@ -625,10 +642,18 @@ class _$DietImpl implements _Diet { @override @JsonKey(name: "is_favorite") final bool isFavorite; + final List _dailyNutrition; + @override + @JsonKey(name: "daily_nutrition") + List get dailyNutrition { + if (_dailyNutrition is EqualUnmodifiableListView) return _dailyNutrition; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_dailyNutrition); + } @override String toString() { - return 'Diet(id: $id, name: $name, image: $image, duration: $duration, state: $state, type: $type, details: $details, dailySchedule: $dailySchedule, author: $author, totalLikes: $totalLikes, totalViews: $totalViews, totalComments: $totalComments, wasLikedByMe: $wasLikedByMe, isFavorite: $isFavorite)'; + return 'Diet(id: $id, name: $name, image: $image, duration: $duration, state: $state, type: $type, details: $details, dailySchedule: $dailySchedule, author: $author, totalLikes: $totalLikes, totalViews: $totalViews, totalComments: $totalComments, wasLikedByMe: $wasLikedByMe, isFavorite: $isFavorite, dailyNutrition: $dailyNutrition)'; } @override @@ -656,7 +681,9 @@ class _$DietImpl implements _Diet { (identical(other.wasLikedByMe, wasLikedByMe) || other.wasLikedByMe == wasLikedByMe) && (identical(other.isFavorite, isFavorite) || - other.isFavorite == isFavorite)); + other.isFavorite == isFavorite) && + const DeepCollectionEquality() + .equals(other._dailyNutrition, _dailyNutrition)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -676,7 +703,8 @@ class _$DietImpl implements _Diet { totalViews, totalComments, wasLikedByMe, - isFavorite); + isFavorite, + const DeepCollectionEquality().hash(_dailyNutrition)); /// Create a copy of Diet /// with the given fields replaced by the non-null parameter values. @@ -696,22 +724,23 @@ class _$DietImpl implements _Diet { abstract class _Diet implements Diet { const factory _Diet( - {@JsonKey(name: "id") required final int id, - @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: "type") required final DietType type, - @JsonKey(name: "details") required final String details, - @JsonKey(name: "daily_schedule") - required final List>> dailySchedule, - @JsonKey(name: "author") required final Author author, - @JsonKey(name: "total_likes") required final int totalLikes, - @JsonKey(name: "total_views") required final int totalViews, - @JsonKey(name: "total_comments") required final int totalComments, - @JsonKey(name: "was_liked_by_me") required final bool wasLikedByMe, - @JsonKey(name: "is_favorite") required final bool isFavorite}) = - _$DietImpl; + {@JsonKey(name: "id") required final int id, + @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: "type") required final DietType type, + @JsonKey(name: "details") required final String details, + @JsonKey(name: "daily_schedule") + required final List>> dailySchedule, + @JsonKey(name: "author") required final Author author, + @JsonKey(name: "total_likes") required final int totalLikes, + @JsonKey(name: "total_views") required final int totalViews, + @JsonKey(name: "total_comments") required final int totalComments, + @JsonKey(name: "was_liked_by_me") required final bool wasLikedByMe, + @JsonKey(name: "is_favorite") required final bool isFavorite, + @JsonKey(name: "daily_nutrition") + required final List dailyNutrition}) = _$DietImpl; factory _Diet.fromJson(Map json) = _$DietImpl.fromJson; @@ -757,6 +786,9 @@ abstract class _Diet implements Diet { @override @JsonKey(name: "is_favorite") bool get isFavorite; + @override + @JsonKey(name: "daily_nutrition") + List get dailyNutrition; /// Create a copy of Diet /// with the given fields replaced by the non-null parameter values. @@ -1444,3 +1476,233 @@ abstract class _DietType implements DietType { _$$DietTypeImplCopyWith<_$DietTypeImpl> get copyWith => throw _privateConstructorUsedError; } + +DailyNutrition _$DailyNutritionFromJson(Map json) { + return _DailyNutrition.fromJson(json); +} + +/// @nodoc +mixin _$DailyNutrition { + @JsonKey(name: 'energy') + double get energy => throw _privateConstructorUsedError; + @JsonKey(name: 'proteins') + double get proteins => throw _privateConstructorUsedError; + @JsonKey(name: 'fats') + double get fats => throw _privateConstructorUsedError; + @JsonKey(name: 'carbohydrates') + double get carbohydrates => throw _privateConstructorUsedError; + + /// Serializes this DailyNutrition to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DailyNutrition + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DailyNutritionCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DailyNutritionCopyWith<$Res> { + factory $DailyNutritionCopyWith( + DailyNutrition value, $Res Function(DailyNutrition) then) = + _$DailyNutritionCopyWithImpl<$Res, DailyNutrition>; + @useResult + $Res call( + {@JsonKey(name: 'energy') double energy, + @JsonKey(name: 'proteins') double proteins, + @JsonKey(name: 'fats') double fats, + @JsonKey(name: 'carbohydrates') double carbohydrates}); +} + +/// @nodoc +class _$DailyNutritionCopyWithImpl<$Res, $Val extends DailyNutrition> + implements $DailyNutritionCopyWith<$Res> { + _$DailyNutritionCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DailyNutrition + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? energy = null, + Object? proteins = null, + Object? fats = null, + Object? carbohydrates = null, + }) { + return _then(_value.copyWith( + energy: null == energy + ? _value.energy + : energy // ignore: cast_nullable_to_non_nullable + as double, + proteins: null == proteins + ? _value.proteins + : proteins // ignore: cast_nullable_to_non_nullable + as double, + fats: null == fats + ? _value.fats + : fats // ignore: cast_nullable_to_non_nullable + as double, + carbohydrates: null == carbohydrates + ? _value.carbohydrates + : carbohydrates // ignore: cast_nullable_to_non_nullable + as double, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$DailyNutritionImplCopyWith<$Res> + implements $DailyNutritionCopyWith<$Res> { + factory _$$DailyNutritionImplCopyWith(_$DailyNutritionImpl value, + $Res Function(_$DailyNutritionImpl) then) = + __$$DailyNutritionImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: 'energy') double energy, + @JsonKey(name: 'proteins') double proteins, + @JsonKey(name: 'fats') double fats, + @JsonKey(name: 'carbohydrates') double carbohydrates}); +} + +/// @nodoc +class __$$DailyNutritionImplCopyWithImpl<$Res> + extends _$DailyNutritionCopyWithImpl<$Res, _$DailyNutritionImpl> + implements _$$DailyNutritionImplCopyWith<$Res> { + __$$DailyNutritionImplCopyWithImpl( + _$DailyNutritionImpl _value, $Res Function(_$DailyNutritionImpl) _then) + : super(_value, _then); + + /// Create a copy of DailyNutrition + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? energy = null, + Object? proteins = null, + Object? fats = null, + Object? carbohydrates = null, + }) { + return _then(_$DailyNutritionImpl( + energy: null == energy + ? _value.energy + : energy // ignore: cast_nullable_to_non_nullable + as double, + proteins: null == proteins + ? _value.proteins + : proteins // ignore: cast_nullable_to_non_nullable + as double, + fats: null == fats + ? _value.fats + : fats // ignore: cast_nullable_to_non_nullable + as double, + carbohydrates: null == carbohydrates + ? _value.carbohydrates + : carbohydrates // ignore: cast_nullable_to_non_nullable + as double, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$DailyNutritionImpl implements _DailyNutrition { + const _$DailyNutritionImpl( + {@JsonKey(name: 'energy') required this.energy, + @JsonKey(name: 'proteins') required this.proteins, + @JsonKey(name: 'fats') required this.fats, + @JsonKey(name: 'carbohydrates') required this.carbohydrates}); + + factory _$DailyNutritionImpl.fromJson(Map json) => + _$$DailyNutritionImplFromJson(json); + + @override + @JsonKey(name: 'energy') + final double energy; + @override + @JsonKey(name: 'proteins') + final double proteins; + @override + @JsonKey(name: 'fats') + final double fats; + @override + @JsonKey(name: 'carbohydrates') + final double carbohydrates; + + @override + String toString() { + return 'DailyNutrition(energy: $energy, proteins: $proteins, fats: $fats, carbohydrates: $carbohydrates)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DailyNutritionImpl && + (identical(other.energy, energy) || other.energy == energy) && + (identical(other.proteins, proteins) || + other.proteins == proteins) && + (identical(other.fats, fats) || other.fats == fats) && + (identical(other.carbohydrates, carbohydrates) || + other.carbohydrates == carbohydrates)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => + Object.hash(runtimeType, energy, proteins, fats, carbohydrates); + + /// Create a copy of DailyNutrition + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DailyNutritionImplCopyWith<_$DailyNutritionImpl> get copyWith => + __$$DailyNutritionImplCopyWithImpl<_$DailyNutritionImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$DailyNutritionImplToJson( + this, + ); + } +} + +abstract class _DailyNutrition implements DailyNutrition { + const factory _DailyNutrition( + {@JsonKey(name: 'energy') required final double energy, + @JsonKey(name: 'proteins') required final double proteins, + @JsonKey(name: 'fats') required final double fats, + @JsonKey(name: 'carbohydrates') + required final double carbohydrates}) = _$DailyNutritionImpl; + + factory _DailyNutrition.fromJson(Map json) = + _$DailyNutritionImpl.fromJson; + + @override + @JsonKey(name: 'energy') + double get energy; + @override + @JsonKey(name: 'proteins') + double get proteins; + @override + @JsonKey(name: 'fats') + double get fats; + @override + @JsonKey(name: 'carbohydrates') + double get carbohydrates; + + /// Create a copy of DailyNutrition + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DailyNutritionImplCopyWith<_$DailyNutritionImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/feed/models/diets_pagination_model.g.dart b/lib/features/feed/models/diets_pagination_model.g.dart index c79e3a26..61060256 100644 --- a/lib/features/feed/models/diets_pagination_model.g.dart +++ b/lib/features/feed/models/diets_pagination_model.g.dart @@ -45,6 +45,9 @@ _$DietImpl _$$DietImplFromJson(Map json) => _$DietImpl( totalComments: (json['total_comments'] as num).toInt(), wasLikedByMe: json['was_liked_by_me'] as bool, isFavorite: json['is_favorite'] as bool, + dailyNutrition: (json['daily_nutrition'] as List) + .map((e) => DailyNutrition.fromJson(e as Map)) + .toList(), ); Map _$$DietImplToJson(_$DietImpl instance) => @@ -63,6 +66,7 @@ Map _$$DietImplToJson(_$DietImpl instance) => 'total_comments': instance.totalComments, 'was_liked_by_me': instance.wasLikedByMe, 'is_favorite': instance.isFavorite, + 'daily_nutrition': instance.dailyNutrition, }; _$AuthorImpl _$$AuthorImplFromJson(Map json) => _$AuthorImpl( @@ -117,3 +121,20 @@ Map _$$DietTypeImplToJson(_$DietTypeImpl instance) => 'corb': instance.corb, 'meat': instance.meat, }; + +_$DailyNutritionImpl _$$DailyNutritionImplFromJson(Map json) => + _$DailyNutritionImpl( + energy: (json['energy'] as num).toDouble(), + proteins: (json['proteins'] as num).toDouble(), + fats: (json['fats'] as num).toDouble(), + carbohydrates: (json['carbohydrates'] as num).toDouble(), + ); + +Map _$$DailyNutritionImplToJson( + _$DailyNutritionImpl instance) => + { + 'energy': instance.energy, + 'proteins': instance.proteins, + 'fats': instance.fats, + 'carbohydrates': instance.carbohydrates, + }; diff --git a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart index 745df313..27e97425 100644 --- a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart +++ b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:developer'; import 'package:easy_debounce/easy_debounce.dart'; -import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart'; +import 'package:eatvio_app/features/diets/repositories/diet_repository.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart'; import 'package:eatvio_app/features/feed/repositories/feed_repository.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -14,6 +14,9 @@ class DietsCubit extends Cubit { late int lastPage; bool isLoading = false; String? _query; + String? _types; + int? _duration; + String? _sorting; late final StreamSubscription likesStateSubscription; late final StreamSubscription favoriteStateSubscription; late final StreamSubscription commentsStateSubscription; @@ -42,11 +45,20 @@ class DietsCubit extends Cubit { loadDiets({ String? query, + String? types, + int? duration, + String? sorting, }) async { try { _query = query; + _types = types; + _duration = duration; + _sorting = sorting; final dietsPagination = await feedRepository.getDiets( query: query, + types: types, + duration: duration, + sorting: sorting, ); lastPage = dietsPagination.meta.lastPage; emit( @@ -76,6 +88,9 @@ class DietsCubit extends Cubit { final dietPagination = await feedRepository.getDiets( page: currentPage, query: _query, + types: _types, + duration: _duration, + sorting: _sorting, ); isLoading = false; emit( diff --git a/lib/features/feed/presentation/pages/feed_screen.dart b/lib/features/feed/presentation/pages/feed_screen.dart index ca9fd146..a02b931b 100644 --- a/lib/features/feed/presentation/pages/feed_screen.dart +++ b/lib/features/feed/presentation/pages/feed_screen.dart @@ -140,7 +140,7 @@ class _FeedScreenState extends State { children: [ _searchBar(), SizedBox(width: 12), - _addBlogPostButton(), + _addItemButton(), ], ), ), @@ -469,9 +469,17 @@ class _FeedScreenState extends State { ); } - _addBlogPostButton() { + _addItemButton() { return InkWell( - onTap: () => GoRouter.of(context).pushNamed('blogPostCreateScreen'), + onTap: () { + switch (_selectedChipIndex) { + case 1: + GoRouter.of(context).pushNamed('recipeCreateScreen'); + break; + default: + GoRouter.of(context).pushNamed('blogPostCreateScreen'); + } + }, borderRadius: BorderRadius.circular(64), child: Ink( decoration: BoxDecoration( @@ -529,7 +537,7 @@ class _FeedScreenState extends State { recipesCubit.loadRecipesList(); break; case 2: - dietsCubit.loadDiets(query: query); + dietsCubit.loadDiets(query: query == '' ? null : query); break; } }, @@ -568,5 +576,4 @@ class _FeedScreenState extends State { ), ); } - } diff --git a/lib/features/feed/presentation/widgets/sorting_drop_down_filter.dart b/lib/features/feed/presentation/widgets/sorting_drop_down_filter.dart index c9e21c1e..9563130d 100644 --- a/lib/features/feed/presentation/widgets/sorting_drop_down_filter.dart +++ b/lib/features/feed/presentation/widgets/sorting_drop_down_filter.dart @@ -1,7 +1,9 @@ +import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; +import 'package:flutter_svg/flutter_svg.dart'; class SortingDropDownFilter extends StatefulWidget { const SortingDropDownFilter({super.key}); @@ -29,6 +31,11 @@ class _SortingDropDownFilterState extends State { @override Widget build(BuildContext context) { return DropdownButtonFormField( + icon: SvgPicture.asset( + 'assets/icons/arrow_down2.svg', + width: 12, + height: 8, + ), borderRadius: BorderRadius.circular(20), dropdownColor: appTheme.lightGray0, decoration: InputDecoration( @@ -43,12 +50,21 @@ class _SortingDropDownFilterState extends State { items: sortingTypes .mapIndexed( (index, value) => DropdownMenuItem( - child: Text(sortingTypes[index]), + child: Text( + sortingTypes[index], + style: TextStyles.textMMedium.copyWith(color: appTheme.black), + ), value: sortingTypes[index], ), ) .toList(), - onChanged: (value) {}, + onChanged: (value) { + if (value != null) { + setState(() { + selectedIndex = sortingTypes.indexOf(value); + }); + } + }, ); } } diff --git a/lib/features/feed/repositories/feed_repository.dart b/lib/features/feed/repositories/feed_repository.dart index 0556029c..5fe12d8a 100644 --- a/lib/features/feed/repositories/feed_repository.dart +++ b/lib/features/feed/repositories/feed_repository.dart @@ -45,11 +45,17 @@ class FeedRepository { Future getDiets({ int page = 1, String? query, + String? types, + int? duration, + String? sorting, }) async { try { return (await feedService.getDiets( page: page, query: query, + types: types, + duration: duration, + sorting: sorting, )); } catch (e) { rethrow; @@ -153,5 +159,4 @@ class FeedRepository { rethrow; } } - } diff --git a/lib/features/feed/services/feed_service.dart b/lib/features/feed/services/feed_service.dart index 8c08bf36..771a6a1f 100644 --- a/lib/features/feed/services/feed_service.dart +++ b/lib/features/feed/services/feed_service.dart @@ -27,7 +27,10 @@ abstract class FeedService { @GET('/api/diets/index') Future getDiets({ @Query('page') required int page, - @Query('query_search') String? query, + @Query('filters[name][\$startsWith]') String? query, + @Query('filters[type][\$contains]') String? types, + @Query('filters[duration][\$eq]') int? duration, + @Query('sort') String? sorting, }); @GET('/api/blogPosts/{id}/comments/show') diff --git a/lib/features/feed/services/feed_service.g.dart b/lib/features/feed/services/feed_service.g.dart index 952b5416..e7a83c0e 100644 --- a/lib/features/feed/services/feed_service.g.dart +++ b/lib/features/feed/services/feed_service.g.dart @@ -107,11 +107,17 @@ class _FeedService implements FeedService { Future getDiets({ required int page, String? query, + String? types, + int? duration, + String? sorting, }) async { final _extra = {}; final queryParameters = { r'page': page, - r'query_search': query, + r'filters[name][$startsWith]': query, + r'filters[type][$contains]': types, + r'filters[duration][$eq]': duration, + r'sort': sorting, }; queryParameters.removeWhere((k, v) => v == null); final _headers = {};