create diet screen

This commit is contained in:
Username1548
2024-11-25 16:01:02 +07:00
parent c3cb55f8a2
commit c78a90b603
42 changed files with 1742 additions and 918 deletions

View File

@@ -0,0 +1,4 @@
<svg width="81" height="73" viewBox="0 0 81 73" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.6449 0.101196C62.732 0.101196 80.6323 9.82685 80.6323 31.9923C80.6323 54.1326 62.732 72.1012 40.6449 72.1012C18.5327 72.1012 0.632324 54.1326 0.632324 31.9923C0.632324 9.82685 18.5327 0.101196 40.6449 0.101196Z" fill="#E6E6E6"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.5113 46.8649C35.2209 46.8649 30.0303 45.8397 25.1891 43.8609C20.3478 41.8583 15.9808 38.9258 12.3623 35.2542C10.6903 33.5854 10.7902 30.9151 12.537 29.3416C14.3088 27.7443 17.0788 27.8396 18.7507 29.5085C21.5457 32.3456 24.9146 34.6105 28.6578 36.1364C32.401 37.686 36.4187 38.4728 40.5113 38.4728C44.579 38.4728 48.5967 37.686 52.3399 36.1364C56.0831 34.6105 59.452 32.3456 62.247 29.5085C63.919 27.8396 66.6889 27.7443 68.4607 29.3416C70.2076 30.9151 70.3074 33.5854 68.6354 35.2542C65.017 38.9258 60.6499 41.8583 55.8086 43.8609C50.9674 45.8397 45.7768 46.8649 40.5113 46.8649Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

12
assets/icons/paste2.svg Normal file
View File

@@ -0,0 +1,12 @@
<svg width="29" height="24" viewBox="0 0 29 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1613_14151)">
<path d="M16.5541 0.16481L16.5534 0.164392L16.3686 0.0499992H10.7531C10.3598 0.0499992 9.99245 0.0498943 9.64914 0.0497952C7.19681 0.0490894 5.97179 0.0487385 5.27756 0.089756C4.88242 0.113102 4.6632 0.1497 4.48911 0.205793C4.35674 0.248446 4.25011 0.302238 4.1096 0.373129C4.06391 0.396177 4.01465 0.421034 3.95975 0.447903C3.76864 0.543461 3.64532 0.61331 3.51952 0.708944C3.39302 0.805105 3.26273 0.928288 3.05879 1.13223C2.85732 1.3337 2.73293 1.46635 2.6356 1.59518C2.53873 1.72339 2.46768 1.84911 2.37452 2.03776L2.37446 2.03789C2.34116 2.10484 2.31104 2.16186 2.28365 2.2137C2.21813 2.33772 2.16824 2.43215 2.12783 2.56233C2.07093 2.74562 2.03389 2.99896 2.01049 3.49571C1.97021 4.35069 1.97066 5.91289 1.97157 9.0505C1.97171 9.55835 1.97187 10.1075 1.97187 10.7016V18.1881L2.08218 18.3778C2.24559 18.6561 2.49994 18.7937 2.85937 18.7937C3.21879 18.7937 3.47314 18.6561 3.63656 18.3778C3.63656 18.3778 3.63657 18.3778 3.63657 18.3778L3.74687 18.1881V11.0344C3.74687 8.75386 3.75156 6.93264 3.75977 5.65515C3.76387 5.01642 3.76885 4.5135 3.77457 4.15701C3.78025 3.80279 3.78666 3.58892 3.79419 3.53245L3.79428 3.53177C3.86143 3.07613 4.03025 2.73822 4.3425 2.42117L4.34304 2.42062C4.66009 2.10837 4.998 1.93956 5.45365 1.87241L5.45418 1.87233C5.50937 1.86481 5.68394 1.85837 5.96104 1.8527C6.24009 1.84698 6.62704 1.842 7.11051 1.83789C8.07751 1.82969 9.43118 1.825 11.0812 1.825H16.36L16.5497 1.7147L16.5541 0.16481ZM16.5541 0.16481C16.8279 0.328245 16.9656 0.58279 16.9656 0.9375M16.5541 0.16481L16.9656 0.9375M16.9656 0.9375C16.9656 1.29685 16.828 1.55116 16.5499 1.71459L16.9656 0.9375Z" fill="#323F4B" stroke="#323F4B" stroke-width="0.1"/>
<path d="M21.0234 22.8985C20.6202 23.3016 20.489 23.4047 20.1093 23.5922L22.0312 6.62814C22.1249 6.98908 22.1249 7.16721 22.1249 13.8985C22.1249 20.4096 22.1475 21.0726 21.9035 21.6158C21.8534 21.7272 21.7921 21.8336 21.7171 21.9844C21.5296 22.3641 21.4265 22.4953 21.0234 22.8985ZM21.9827 6.64031L21.9828 6.64071C22.0279 6.81444 22.0515 6.9433 22.0632 7.87506C22.0749 8.80571 22.0749 10.5326 22.0749 13.8985C22.0749 14.445 22.0751 14.9504 22.0752 15.4179C22.0761 18.307 22.0766 19.7503 22.0363 20.5493C22.0129 21.0132 21.9759 21.2554 21.9191 21.4356C21.8779 21.566 21.8267 21.6638 21.7595 21.7924C21.733 21.843 21.7041 21.8983 21.6724 21.9621L21.6723 21.9623C21.5792 22.1508 21.5082 22.2753 21.4113 22.4023C21.314 22.53 21.1896 22.6615 20.988 22.8631C20.7864 23.0647 20.655 23.1891 20.5272 23.2864C20.4002 23.3833 20.2757 23.4543 20.0872 23.5474L20.087 23.5474C20.0387 23.5715 19.9945 23.5939 19.9531 23.615C19.8064 23.6895 19.6954 23.746 19.5615 23.7904C19.3911 23.8469 19.1828 23.884 18.8199 23.9079C18.1676 23.9509 17.0279 23.9506 14.736 23.9501C14.4724 23.9501 14.1935 23.95 13.8984 23.95C13.6032 23.95 13.3244 23.9501 13.0607 23.9501C10.7689 23.9506 9.62916 23.9509 8.97686 23.9079C8.61396 23.884 8.40563 23.8469 8.23529 23.7904C8.10133 23.746 7.9903 23.6895 7.84361 23.615C7.80225 23.5939 7.75805 23.5715 7.7097 23.5474L7.70958 23.5474C7.52103 23.4543 7.39652 23.3833 7.26951 23.2864C7.1418 23.1891 7.01031 23.0647 6.80873 22.8631C6.60715 22.6615 6.48276 22.53 6.3854 22.4023C6.28858 22.2753 6.21757 22.1508 6.12446 21.9623L6.1244 21.9621C6.09262 21.8982 6.06371 21.843 6.03728 21.7924C5.97001 21.6638 5.91885 21.566 5.8777 21.4356C5.82081 21.2554 5.78381 21.0132 5.76042 20.5493C5.72014 19.7503 5.7206 18.307 5.72151 15.4178C5.72165 14.9503 5.72181 14.445 5.72181 13.8985C5.72181 10.5326 5.72181 8.80571 5.73353 7.87506C5.74525 6.9433 5.76883 6.81444 5.81396 6.64071L5.81407 6.64027C6.07308 5.60424 6.79019 4.70695 7.73306 4.24014L7.73324 4.24005C7.77891 4.21722 7.82076 4.19584 7.86 4.17581C8.00453 4.10201 8.11348 4.04637 8.24663 4.00268C8.41467 3.94754 8.62224 3.91143 8.98552 3.8884C9.63598 3.84715 10.7735 3.84835 13.0525 3.85074C13.3241 3.85103 13.6119 3.85133 13.9171 3.85158H13.9171C16.3314 3.85158 17.5953 3.85276 18.2979 3.86447C19.0007 3.87618 19.1376 3.89847 19.3001 3.93911C20.6042 4.27679 21.6544 5.33163 21.9827 6.64031ZM9.20396 5.66924L9.20358 5.6693C8.74794 5.73645 8.41003 5.90527 8.09297 6.21751L8.09244 6.21806C7.78019 6.53511 7.61137 6.87302 7.54422 7.32866L7.54415 7.32918C7.53989 7.36029 7.5363 7.43735 7.533 7.55039C7.52965 7.66491 7.52656 7.81965 7.5237 8.00875C7.51798 8.38699 7.51322 8.90334 7.50941 9.51167C7.50179 10.7284 7.49798 12.3134 7.49798 13.8985C7.49798 15.4835 7.50179 17.0686 7.50941 18.2852C7.51322 18.8936 7.51798 19.4099 7.5237 19.7882C7.52656 19.9773 7.52965 20.132 7.533 20.2465C7.5363 20.3596 7.53989 20.4366 7.54415 20.4677L7.54422 20.4682C7.61137 20.9239 7.78019 21.2618 8.09243 21.5789L8.09298 21.5794C8.41003 21.8916 8.74794 22.0605 9.20358 22.1276L9.20403 22.1277C9.26278 22.1358 9.44753 22.1425 9.7211 22.1481C9.99668 22.1538 10.3666 22.1586 10.7992 22.1624C11.6645 22.17 12.7815 22.1738 13.8984 22.1738C15.0153 22.1738 16.1322 22.17 16.9975 22.1624C17.4302 22.1586 17.8001 22.1538 18.0756 22.1481C18.3492 22.1425 18.534 22.1358 18.5927 22.1277L18.5932 22.1276C19.0488 22.0605 19.3867 21.8916 19.7038 21.5794L19.7038 21.5794L19.7043 21.5789C20.0166 21.2618 20.1854 20.9239 20.2525 20.4682L20.2525 20.4682L20.2526 20.4677C20.2569 20.4366 20.2605 20.3596 20.2638 20.2465C20.2671 20.132 20.2702 19.9773 20.2731 19.7882C20.2788 19.4099 20.2835 18.8936 20.2873 18.2852C20.295 17.0686 20.2988 15.4835 20.2988 13.8985C20.2988 12.3134 20.295 10.7284 20.2873 9.51167C20.2835 8.90334 20.2788 8.38699 20.2731 8.00875C20.2702 7.81965 20.2671 7.66491 20.2638 7.55039C20.2605 7.43735 20.2569 7.36029 20.2526 7.32918L20.2525 7.32866C20.1854 6.87302 20.0166 6.53511 19.7043 6.21805L19.7038 6.21751C19.3968 5.9153 19.0403 5.73184 18.6351 5.67396L18.6351 5.67395C18.5814 5.66637 18.3991 5.66017 18.1265 5.65481C17.8518 5.6494 17.4807 5.64482 17.0457 5.64108C16.1754 5.63361 15.0484 5.62951 13.9213 5.62892C12.7941 5.62834 11.6668 5.63127 10.796 5.63786C10.3606 5.64116 9.9892 5.64537 9.71398 5.65052C9.44095 5.65563 9.25816 5.66168 9.20396 5.66924Z" fill="#323F4B" stroke="#323F4B" stroke-width="0.1"/>
</g>
<path d="M28 14.75C28.4142 14.75 28.75 14.4142 28.75 14C28.75 13.5858 28.4142 13.25 28 13.25V14.75ZM11.4697 13.4697C11.1768 13.7626 11.1768 14.2374 11.4697 14.5303L16.2426 19.3033C16.5355 19.5962 17.0104 19.5962 17.3033 19.3033C17.5962 19.0104 17.5962 18.5355 17.3033 18.2426L13.0607 14L17.3033 9.75736C17.5962 9.46447 17.5962 8.98959 17.3033 8.6967C17.0104 8.40381 16.5355 8.40381 16.2426 8.6967L11.4697 13.4697ZM28 13.25L12 13.25V14.75L28 14.75V13.25Z" fill="#323F4B"/>
<defs>
<clipPath id="clip0_1613_14151">
<rect width="24" height="24" fill="white" transform="matrix(-1 0 0 1 24 0)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -1 +1,5 @@
const String baseUrl = 'https://dev2.eatvio.com';
const List<int> durationValues = [7, 14, 21];
const List<String> typeValues = ['veg', 'light', 'carb', 'meat'];

View File

@@ -1,5 +1,8 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
import 'package:eatvio_app/features/create_diet/services/create_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';
@@ -74,6 +77,8 @@ Future<void> init() async {
sl.registerFactory<DiaryCubit>(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl()));
sl.registerFactory<AboutDietCubit>(() => AboutDietCubit(dietsRepository: sl()));
sl.registerFactory<BlogPostCreateCubit>(() => BlogPostCreateCubit(blogPostRepository: sl()));
sl.registerFactory<CreateDietCubit>(() => CreateDietCubit(createDietRepository: sl()));
// Repository
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
@@ -89,6 +94,7 @@ Future<void> init() async {
sl.registerLazySingleton<GlossaryRepository>(() => GlossaryRepository(glossaryService: sl()));
sl.registerLazySingleton<DietRepository>(() => DietRepository(dietsService: sl()));
sl.registerLazySingleton<BlogPostRepository>(() => BlogPostRepository(blogPostService: sl()));
sl.registerLazySingleton<CreateDietRepository>(() => CreateDietRepository(createDietService: sl()));
// Services
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
@@ -104,6 +110,7 @@ Future<void> init() async {
sl.registerLazySingleton<GlossaryService>(() => GlossaryService(sl()));
sl.registerLazySingleton<DietService>(() => DietService(sl()));
sl.registerLazySingleton<BlogPostService>(() => BlogPostService(sl()));
sl.registerLazySingleton<CreateDietService>(() => CreateDietService(sl()));
// External
sl.registerLazySingleton(

View File

@@ -178,6 +178,10 @@ class PrimaryColors {
Color get transparentBlue => Color(0xFF2F80ED).withOpacity(0.1);
Color get lightGray0 => Color(0xFFF6F6F6);
Color get lightGray00 => Color(0xFFE9E9EA);
Color get dottedBorder => Color(0xFFE6E6E6);
}
PrimaryColors get appTheme => ThemeHelper().themeColor();

View File

@@ -0,0 +1,41 @@
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
class CustomDropDownButton<T> extends StatelessWidget {
const CustomDropDownButton({
super.key,
required this.items,
required this.onChanged,
this.value,
this.hint,
});
final T? value;
final List<DropdownMenuItem<T>> items;
final void Function(T?)? onChanged;
final Widget? hint;
@override
Widget build(BuildContext context) {
return DropdownButtonFormField(
hint: hint,
icon: SvgPicture.asset(
'assets/icons/arrow_down2.svg',
width: 12,
height: 8,
),
borderRadius: BorderRadius.circular(20),
dropdownColor: appTheme.lightGray0,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(20)),
borderSide: BorderSide.none,
),
fillColor: appTheme.lightGray0,
filled: true,
),
value: value,
items: items,
onChanged: onChanged,
);
}
}

View File

@@ -13,7 +13,7 @@ class CustomTextFormField extends StatelessWidget {
this.obscureText = false,
this.textInputAction,
this.textInputType,
this.maxLines,
this.maxLines = 1,
this.hintText,
this.hintStyle,
this.prefix,
@@ -35,6 +35,8 @@ class CustomTextFormField extends StatelessWidget {
this.onEditingComplete,
this.minLines = 1,
this.maxLength,
this.expands = false,
this.textAlignVertical,
super.key,
});
@@ -49,7 +51,7 @@ class CustomTextFormField extends StatelessWidget {
final TextInputAction? textInputAction;
final TextInputType? textInputType;
final int? maxLines;
final int minLines;
final int? minLines;
final String? hintText;
final TextStyle? hintStyle;
final Widget? prefix;
@@ -69,12 +71,15 @@ class CustomTextFormField extends StatelessWidget {
final void Function(String?)? onSaved;
final void Function(String)? onChanged;
final int? maxLength;
final bool expands;
final TextAlignVertical? textAlignVertical;
@override
Widget build(BuildContext context) {
return Align(
alignment: alignment ?? Alignment.center,
child: TextFormField(
textAlignVertical: textAlignVertical,
expands: expands,
minLines: minLines,
maxLength: maxLength,
onChanged: onChanged,
@@ -88,7 +93,7 @@ class CustomTextFormField extends StatelessWidget {
),
obscureText: obscureText!,
textInputAction: textInputAction,
maxLines: maxLines ?? 1,
maxLines: maxLines,
initialValue: initialValue,
cursorColor: appTheme.blueA400,
decoration: InputDecoration(

View File

@@ -23,21 +23,14 @@ _$ConsultantProfileModelImpl _$$ConsultantProfileModelImplFromJson(
);
Map<String, dynamic> _$$ConsultantProfileModelImplToJson(
_$ConsultantProfileModelImpl instance) {
final val = <String, dynamic>{};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('has_medical_education', instance.hasMedicalEducation);
writeNotNull('social_links', instance.socialLinks);
writeNotNull('cert_photos', instance.photos);
writeNotNull('completed_courses', instance.certificates);
return val;
}
_$ConsultantProfileModelImpl instance) =>
<String, dynamic>{
if (instance.hasMedicalEducation case final value?)
'has_medical_education': value,
if (instance.socialLinks case final value?) 'social_links': value,
if (instance.photos case final value?) 'cert_photos': value,
if (instance.certificates case final value?) 'completed_courses': value,
};
_$SocialLinksModelImpl _$$SocialLinksModelImplFromJson(
Map<String, dynamic> json) =>
@@ -50,22 +43,15 @@ _$SocialLinksModelImpl _$$SocialLinksModelImplFromJson(
);
Map<String, dynamic> _$$SocialLinksModelImplToJson(
_$SocialLinksModelImpl instance) {
final val = <String, dynamic>{};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('vk_link', instance.vkLink);
writeNotNull('tg_link', instance.tgLink);
writeNotNull('fb_link', instance.fbLink);
writeNotNull('insta_link', instance.instaLink);
writeNotNull('personal_site_link', instance.personalSiteLink);
return val;
}
_$SocialLinksModelImpl instance) =>
<String, dynamic>{
if (instance.vkLink case final value?) 'vk_link': value,
if (instance.tgLink case final value?) 'tg_link': value,
if (instance.fbLink case final value?) 'fb_link': value,
if (instance.instaLink case final value?) 'insta_link': value,
if (instance.personalSiteLink case final value?)
'personal_site_link': value,
};
_$CertificatesModelImpl _$$CertificatesModelImplFromJson(
Map<String, dynamic> json) =>

View File

@@ -1,7 +1,9 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'create_diet_model.freezed.dart';
@@ -15,8 +17,8 @@ class CreateDietModel with _$CreateDietModel{
String? details,
String? state,
int? duration,
List<String>? type,
File? image,
required List<bool> type,
XFile? image,
List<List<List<DailySchedule>>>? dailySchedule,
}) = _CreateDietModel;
@@ -26,7 +28,7 @@ class CreateDietModel with _$CreateDietModel{
'state': state,
'type': type,
'details': details,
'image': image != null ? await ImageCompressUtility.compressFile(image!) : null,
'image': image != null ? await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image!.path))).path, filename: image!.name) : null,
};
Map<String, dynamic> toDailyScheduleCreationJson() => {

View File

@@ -20,8 +20,8 @@ mixin _$CreateDietModel {
String? get details => throw _privateConstructorUsedError;
String? get state => throw _privateConstructorUsedError;
int? get duration => throw _privateConstructorUsedError;
List<String>? get type => throw _privateConstructorUsedError;
File? get image => throw _privateConstructorUsedError;
List<bool> get type => throw _privateConstructorUsedError;
XFile? get image => throw _privateConstructorUsedError;
List<List<List<DailySchedule>>>? get dailySchedule =>
throw _privateConstructorUsedError;
@@ -43,8 +43,8 @@ abstract class $CreateDietModelCopyWith<$Res> {
String? details,
String? state,
int? duration,
List<String>? type,
File? image,
List<bool> type,
XFile? image,
List<List<List<DailySchedule>>>? dailySchedule});
}
@@ -67,7 +67,7 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
Object? details = freezed,
Object? state = freezed,
Object? duration = freezed,
Object? type = freezed,
Object? type = null,
Object? image = freezed,
Object? dailySchedule = freezed,
}) {
@@ -88,14 +88,14 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
? _value.duration
: duration // ignore: cast_nullable_to_non_nullable
as int?,
type: freezed == type
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as List<String>?,
as List<bool>,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as File?,
as XFile?,
dailySchedule: freezed == dailySchedule
? _value.dailySchedule
: dailySchedule // ignore: cast_nullable_to_non_nullable
@@ -117,8 +117,8 @@ abstract class _$$CreateDietModelImplCopyWith<$Res>
String? details,
String? state,
int? duration,
List<String>? type,
File? image,
List<bool> type,
XFile? image,
List<List<List<DailySchedule>>>? dailySchedule});
}
@@ -139,7 +139,7 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
Object? details = freezed,
Object? state = freezed,
Object? duration = freezed,
Object? type = freezed,
Object? type = null,
Object? image = freezed,
Object? dailySchedule = freezed,
}) {
@@ -160,14 +160,14 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
? _value.duration
: duration // ignore: cast_nullable_to_non_nullable
as int?,
type: freezed == type
type: null == type
? _value._type
: type // ignore: cast_nullable_to_non_nullable
as List<String>?,
as List<bool>,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as File?,
as XFile?,
dailySchedule: freezed == dailySchedule
? _value._dailySchedule
: dailySchedule // ignore: cast_nullable_to_non_nullable
@@ -184,7 +184,7 @@ class _$CreateDietModelImpl extends _CreateDietModel {
this.details,
this.state,
this.duration,
final List<String>? type,
required final List<bool> type,
this.image,
final List<List<List<DailySchedule>>>? dailySchedule})
: _type = type,
@@ -199,18 +199,16 @@ class _$CreateDietModelImpl extends _CreateDietModel {
final String? state;
@override
final int? duration;
final List<String>? _type;
final List<bool> _type;
@override
List<String>? get type {
final value = _type;
if (value == null) return null;
List<bool> get type {
if (_type is EqualUnmodifiableListView) return _type;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
return EqualUnmodifiableListView(_type);
}
@override
final File? image;
final XFile? image;
final List<List<List<DailySchedule>>>? _dailySchedule;
@override
List<List<List<DailySchedule>>>? get dailySchedule {
@@ -269,8 +267,8 @@ abstract class _CreateDietModel extends CreateDietModel {
final String? details,
final String? state,
final int? duration,
final List<String>? type,
final File? image,
required final List<bool> type,
final XFile? image,
final List<List<List<DailySchedule>>>? dailySchedule}) =
_$CreateDietModelImpl;
const _CreateDietModel._() : super._();
@@ -284,9 +282,9 @@ abstract class _CreateDietModel extends CreateDietModel {
@override
int? get duration;
@override
List<String>? get type;
List<bool> get type;
@override
File? get image;
XFile? get image;
@override
List<List<List<DailySchedule>>>? get dailySchedule;

View File

@@ -1,4 +1,20 @@
import 'package:flutter/widgets.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/utils/localization_utils.dart';
import 'package:eatvio_app/core/widgets/custom_text_form_field.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';
import 'package:eatvio_app/features/create_diet/presentation/widgets/day_widget.dart';
import 'package:eatvio_app/features/create_diet/presentation/widgets/duration_drop_down_widget.dart';
import 'package:eatvio_app/features/create_diet/presentation/widgets/image_picker_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/type_choice_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
class CreateDietScreen extends StatelessWidget {
static const name = 'createDietScreen';
@@ -7,6 +23,97 @@ class CreateDietScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Placeholder();
return BlocProvider(
create: (context) => sl<CreateDietCubit>(),
child: const CreateDietScreenContent(),
);
}
}
}
class CreateDietScreenContent extends StatelessWidget {
const CreateDietScreenContent({super.key});
@override
Widget build(BuildContext context) {
final s = S.of(context);
return Scaffold(
backgroundColor: appTheme.gray100,
appBar: AppBar(
centerTitle: true,
title: Text(
s.create_diet,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
),
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 8),
MainBackgroundBouble(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
SizedBox(height: 16),
CustomTextFormField(
hintText: s.enter_diet_name,
onChanged: (value) {
context.read<CreateDietCubit>().setName(value);
},
),
SizedBox(height: 12),
SizedBox(
height: 132,
child: CustomTextFormField(
textAlignVertical: TextAlignVertical.top,
maxLines: null,
minLines: null,
expands: true,
hintText: s.enter_diet_description,
onChanged: (value) {
context.read<CreateDietCubit>().setDetails(value);
},
),
),
SizedBox(height: 12),
DurationDropDownWidget(),
SizedBox(height: 12),
StatusDropDownWidget(),
SizedBox(height: 16),
TypeChoiceWidget(),
SizedBox(height: 16),
ImagePickerWidget(),
SizedBox(height: 16),
],
),
),
SizedBox(height: 16),
BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return MainBackgroundBouble(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Center(
child: Text(
s.diet_plan + ' (${state.dietData.duration ?? 0} ' + getDayForm(state.dietData.duration ?? 0, s) + ')',
style: TextStyles.headingXLSemibold.copyWith(
color: appTheme.black,
),
),
),
),
);
},
),
SizedBox(height: 8),
DayWidget(
index: 0,
),
],
),
),
);
}
}

View File

@@ -1,11 +1,14 @@
import 'dart:io';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
class CreateDietCubit extends Cubit<CreateDietState> {
CreateDietCubit() : super(CreateDietState.initial());
final CreateDietRepository createDietRepository;
static const _dietStateValues = ['active', 'draft', 'personal'];
CreateDietCubit({required this.createDietRepository}) : super(CreateDietState.initial());
void setDetails(String text) {
emit(state.copyWith(dietData: state.dietData.copyWith(details: text)));
@@ -15,11 +18,18 @@ class CreateDietCubit extends Cubit<CreateDietState> {
emit(state.copyWith(dietData: state.dietData.copyWith(name: name)));
}
void setDuration(int duration) {
emit(state.copyWith(dietData: state.dietData.copyWith(duration: duration)));
void setDuration(int index) {
emit(
state.copyWith(
durationIndex: index,
dietData: state.dietData.copyWith(
duration: durationValues[index],
),
),
);
}
void setImage(File image) {
void setImage(XFile? image) {
emit(state.copyWith(dietData: state.dietData.copyWith(image: image)));
}
@@ -27,11 +37,11 @@ class CreateDietCubit extends Cubit<CreateDietState> {
emit(state.copyWith(dietData: state.dietData.copyWith(dailySchedule: dailySchedule)));
}
void setDietState(String dietState) {
emit(state.copyWith(dietData: state.dietData.copyWith(state: dietState)));
void setDietState(int index) {
emit(state.copyWith(dietStateIndex: index, dietData: state.dietData.copyWith(state: _dietStateValues[index])));
}
void setDietType(List<String> type) {
void setDietType(List<bool> type) {
emit(state.copyWith(dietData: state.dietData.copyWith(type: type)));
}
}

View File

@@ -9,7 +9,9 @@ class CreateDietState with _$CreateDietState {
required bool isLoading,
required String? errorMessage,
required CreateDietModel dietData,
int? durationIndex,
int? dietStateIndex,
}) = _CreateDietState;
factory CreateDietState.initial() => CreateDietState(isLoading: false, errorMessage: null, dietData: CreateDietModel());
factory CreateDietState.initial() => CreateDietState(isLoading: false, errorMessage: null, dietData: CreateDietModel(type: [false, false, false, false]));
}

View File

@@ -19,6 +19,8 @@ mixin _$CreateDietState {
bool get isLoading => throw _privateConstructorUsedError;
String? get errorMessage => throw _privateConstructorUsedError;
CreateDietModel get dietData => throw _privateConstructorUsedError;
int? get durationIndex => throw _privateConstructorUsedError;
int? get dietStateIndex => throw _privateConstructorUsedError;
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.
@@ -33,7 +35,12 @@ abstract class $CreateDietStateCopyWith<$Res> {
CreateDietState value, $Res Function(CreateDietState) then) =
_$CreateDietStateCopyWithImpl<$Res, CreateDietState>;
@useResult
$Res call({bool isLoading, String? errorMessage, CreateDietModel dietData});
$Res call(
{bool isLoading,
String? errorMessage,
CreateDietModel dietData,
int? durationIndex,
int? dietStateIndex});
$CreateDietModelCopyWith<$Res> get dietData;
}
@@ -56,6 +63,8 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
Object? isLoading = null,
Object? errorMessage = freezed,
Object? dietData = null,
Object? durationIndex = freezed,
Object? dietStateIndex = freezed,
}) {
return _then(_value.copyWith(
isLoading: null == isLoading
@@ -70,6 +79,14 @@ class _$CreateDietStateCopyWithImpl<$Res, $Val extends CreateDietState>
? _value.dietData
: dietData // ignore: cast_nullable_to_non_nullable
as CreateDietModel,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int?,
dietStateIndex: freezed == dietStateIndex
? _value.dietStateIndex
: dietStateIndex // ignore: cast_nullable_to_non_nullable
as int?,
) as $Val);
}
@@ -92,7 +109,12 @@ abstract class _$$CreateDietStateImplCopyWith<$Res>
__$$CreateDietStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({bool isLoading, String? errorMessage, CreateDietModel dietData});
$Res call(
{bool isLoading,
String? errorMessage,
CreateDietModel dietData,
int? durationIndex,
int? dietStateIndex});
@override
$CreateDietModelCopyWith<$Res> get dietData;
@@ -114,6 +136,8 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
Object? isLoading = null,
Object? errorMessage = freezed,
Object? dietData = null,
Object? durationIndex = freezed,
Object? dietStateIndex = freezed,
}) {
return _then(_$CreateDietStateImpl(
isLoading: null == isLoading
@@ -128,6 +152,14 @@ class __$$CreateDietStateImplCopyWithImpl<$Res>
? _value.dietData
: dietData // ignore: cast_nullable_to_non_nullable
as CreateDietModel,
durationIndex: freezed == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int?,
dietStateIndex: freezed == dietStateIndex
? _value.dietStateIndex
: dietStateIndex // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
@@ -138,7 +170,9 @@ class _$CreateDietStateImpl implements _CreateDietState {
const _$CreateDietStateImpl(
{required this.isLoading,
required this.errorMessage,
required this.dietData});
required this.dietData,
this.durationIndex,
this.dietStateIndex});
@override
final bool isLoading;
@@ -146,10 +180,14 @@ class _$CreateDietStateImpl implements _CreateDietState {
final String? errorMessage;
@override
final CreateDietModel dietData;
@override
final int? durationIndex;
@override
final int? dietStateIndex;
@override
String toString() {
return 'CreateDietState(isLoading: $isLoading, errorMessage: $errorMessage, dietData: $dietData)';
return 'CreateDietState(isLoading: $isLoading, errorMessage: $errorMessage, dietData: $dietData, durationIndex: $durationIndex, dietStateIndex: $dietStateIndex)';
}
@override
@@ -162,12 +200,16 @@ class _$CreateDietStateImpl implements _CreateDietState {
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage) &&
(identical(other.dietData, dietData) ||
other.dietData == dietData));
other.dietData == dietData) &&
(identical(other.durationIndex, durationIndex) ||
other.durationIndex == durationIndex) &&
(identical(other.dietStateIndex, dietStateIndex) ||
other.dietStateIndex == dietStateIndex));
}
@override
int get hashCode =>
Object.hash(runtimeType, isLoading, errorMessage, dietData);
int get hashCode => Object.hash(runtimeType, isLoading, errorMessage,
dietData, durationIndex, dietStateIndex);
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.
@@ -183,7 +225,9 @@ abstract class _CreateDietState implements CreateDietState {
const factory _CreateDietState(
{required final bool isLoading,
required final String? errorMessage,
required final CreateDietModel dietData}) = _$CreateDietStateImpl;
required final CreateDietModel dietData,
final int? durationIndex,
final int? dietStateIndex}) = _$CreateDietStateImpl;
@override
bool get isLoading;
@@ -191,6 +235,10 @@ abstract class _CreateDietState implements CreateDietState {
String? get errorMessage;
@override
CreateDietModel get dietData;
@override
int? get durationIndex;
@override
int? get dietStateIndex;
/// Create a copy of CreateDietState
/// with the given fields replaced by the non-null parameter values.

View File

@@ -0,0 +1,178 @@
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/custom_divider.dart';
import 'package:eatvio_app/core/widgets/custom_outlined_button.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';
import 'package:eatvio_app/features/feed/presentation/widgets/choice_chip_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
class DayWidget extends StatefulWidget {
const DayWidget({
super.key,
required this.index,
});
final int index;
@override
State<DayWidget> createState() => _DayWidgetState();
}
class _DayWidgetState extends State<DayWidget> {
int _selectedDayIndex = 0;
final chipsLabelList = ['1', '2', '3', '4', '5'];
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return MainBackgroundBouble(
child: Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
s.day + ' ${widget.index + 1}',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
),
Spacer(),
SvgPicture.asset(
'assets/icons/copy2.svg',
width: 20,
height: 24,
colorFilter: ColorFilter.mode(appTheme.black, BlendMode.srcIn),
),
],
),
SizedBox(
height: 12,
),
CustomDivider(),
SizedBox(
height: 12,
),
Text(
s.meal,
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
SizedBox(height: 16),
Row(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
fontSize: TextStyles.textMMedium.fontSize,
fontWeight: TextStyles.textMMedium.fontWeight,
index: 0,
selectedChipIndex: _selectedDayIndex,
onSelected: (selectedValue) {
setState(() {
_selectedDayIndex = 0;
});
},
),
Spacer(),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
fontSize: TextStyles.textMMedium.fontSize,
fontWeight: TextStyles.textMMedium.fontWeight,
index: 1,
selectedChipIndex: _selectedDayIndex,
onSelected: (selectedValue) {
setState(() {
_selectedDayIndex = 1;
});
},
),
Spacer(),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
fontSize: TextStyles.textMMedium.fontSize,
fontWeight: TextStyles.textMMedium.fontWeight,
index: 2,
selectedChipIndex: _selectedDayIndex,
onSelected: (selectedValue) {
setState(() {
_selectedDayIndex = 2;
});
},
),
Spacer(),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
fontSize: TextStyles.textMMedium.fontSize,
fontWeight: TextStyles.textMMedium.fontWeight,
index: 3,
selectedChipIndex: _selectedDayIndex,
onSelected: (selectedValue) {
setState(() {
_selectedDayIndex = 3;
});
},
),
Spacer(),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
fontSize: TextStyles.textMMedium.fontSize,
fontWeight: TextStyles.textMMedium.fontWeight,
index: 4,
selectedChipIndex: _selectedDayIndex,
onSelected: (selectedValue) {
setState(() {
_selectedDayIndex = 4;
});
},
),
],
),
SizedBox(height: 16),
Row(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 14),
decoration: BoxDecoration(color: appTheme.gray50, borderRadius: BorderRadius.all(Radius.circular(12))),
child: SvgPicture.asset(
'assets/icons/paste2.svg',
width: 28,
height: 24,
),
),
SizedBox(width: 8),
Expanded(
child: CustomOutlinedButton(
text: s.add,
height: 52,
buttonTextStyle: TextStyles.textMSemibold.copyWith(
color: appTheme.whiteA700,
),
buttonStyle: ButtonStyle(
side: WidgetStatePropertyAll(BorderSide.none),
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
),
),
),
],
),
SizedBox(height: 20),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,65 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/utils/localization_utils.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class DurationDropDownWidget extends StatefulWidget {
const DurationDropDownWidget({super.key});
@override
State<DurationDropDownWidget> createState() => _DurationDropDownWidgetState();
}
class _DurationDropDownWidgetState extends State<DurationDropDownWidget> {
final List<String> durationDropDownTitles = [];
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (durationDropDownTitles.isEmpty) {
durationValues.forEach((element) {
durationDropDownTitles.add('$element ${getDayForm(element, s)}');
});
}
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return CustomDropDownButton(
hint: Text(
s.choose_diet_duration,
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
onChanged: (value) {
if (value != null) {
context.read<CreateDietCubit>().setDuration(durationDropDownTitles.indexOf(value));
}
},
items: durationDropDownTitles
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
durationDropDownTitles[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: durationDropDownTitles[index],
),
)
.toList(),
value: state.durationIndex == null ? null : durationDropDownTitles[state.durationIndex ?? 0],
);
},
);
}
}

View File

@@ -0,0 +1,122 @@
import 'dart:io';
import 'package:dotted_border/dotted_border.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerWidget extends StatefulWidget {
const ImagePickerWidget({super.key});
@override
State<ImagePickerWidget> createState() => _ImagePickerWidgetState();
}
class _ImagePickerWidgetState extends State<ImagePickerWidget> {
void _showImagePickerOptions(S s, CreateDietCubit cubit) {
showCupertinoModalPopup<void>(
context: context,
builder: (context) => CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.camera);
cubit.setImage(image);
Navigator.of(context).pop();
},
child: Row(
children: [
Icon(Icons.photo_camera),
SizedBox(width: 8),
Text(s.photo),
],
),
),
CupertinoActionSheetAction(
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
cubit.setImage(image);
Navigator.of(context).pop();
},
child: Row(
children: [
Icon(Icons.photo),
SizedBox(width: 8),
Text(s.gallery),
],
),
),
],
cancelButton: CupertinoActionSheetAction(
onPressed: () => Navigator.of(context).pop(),
isDestructiveAction: true,
child: const Text('Отмена'),
),
),
);
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return GestureDetector(
onTap: () {
_showImagePickerOptions(s, context.read<CreateDietCubit>());
},
child: Container(
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,
color: appTheme.gray50,
),
width: MediaQuery.sizeOf(context).width,
padding: state.dietData.image != null ? null : EdgeInsets.all(8),
child: state.dietData.image != null
? null
: Stack(
children: [
DottedBorder(
stackFit: StackFit.expand,
dashPattern: [14, 14],
color: appTheme.dottedBorder,
borderType: BorderType.RRect,
radius: Radius.circular(12),
child: SizedBox.expand(),
),
Center(
child: Column(
children: [
SizedBox(
height: 48,
),
SvgPicture.asset('assets/icons/eatvio_logo.svg'),
SizedBox(
height: 24,
),
Text(
s.add_cover,
style: TextStyles.textMMedium.copyWith(color: appTheme.gray),
),
],
),
),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,63 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:collection/collection.dart';
class StatusDropDownWidget extends StatefulWidget {
const StatusDropDownWidget({super.key});
@override
State<StatusDropDownWidget> createState() => _StatusDropDownWidgetState();
}
class _StatusDropDownWidgetState extends State<StatusDropDownWidget> {
final List<String> dietStateTitles = [];
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (dietStateTitles.isEmpty) {
dietStateTitles.add(s.active_diet_state);
dietStateTitles.add(s.inactive_diet_state);
dietStateTitles.add(s.personal_diet_state);
}
}
@override
Widget build(BuildContext context) {
final s = S.of(context);
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return CustomDropDownButton(
hint: Text(
s.diet_state,
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
onChanged: (value) {
if (value != null) {
context.read<CreateDietCubit>().setDietState(dietStateTitles.indexOf(value));
}
},
items: dietStateTitles
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
dietStateTitles[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: dietStateTitles[index],
),
)
.toList(),
value: state.dietStateIndex == null ? null : dietStateTitles[state.dietStateIndex ?? 0],
);
},
);
}
}

View File

@@ -0,0 +1,100 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
class TypeChoiceWidget extends StatefulWidget {
TypeChoiceWidget({super.key});
@override
State<TypeChoiceWidget> createState() => _TypeChoiceWidgetState();
}
class _TypeChoiceWidgetState extends State<TypeChoiceWidget> {
final List<(String, String)> choiceContent = [];
@override
void didChangeDependencies() {
super.didChangeDependencies();
final s = S.of(context);
if (choiceContent.isEmpty) {
choiceContent.add(
(
'assets/icons/meat2.svg',
s.meat,
),
);
choiceContent.add(
(
'assets/icons/broccoli.svg',
s.vegan,
),
);
choiceContent.add(
(
'assets/icons/bread.svg',
s.carb_type,
),
);
choiceContent.add(
(
'assets/icons/cocktail.svg',
s.light_type,
),
);
}
}
@override
Widget build(BuildContext context) {
return BlocBuilder<CreateDietCubit, CreateDietState>(
builder: (context, state) {
return Row(
children: [
...List.generate(4, (index) {
return Expanded(
child: GestureDetector(
onTap: () {
final dietTypes = [...state.dietData.type];
dietTypes[index] = !dietTypes[index];
context.read<CreateDietCubit>().setDietType(dietTypes);
},
child: Container(
margin: EdgeInsets.only(right: index == 3 ? 0 : 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: state.dietData.type[index] ? appTheme.cardBackground : appTheme.whiteA700,
border: Border.all(
width: 1,
color: state.dietData.type[index] ? appTheme.blueA400 : appTheme.lightGray00,
),
),
height: 80,
child: Column(
children: [
SizedBox(height: 16),
SvgPicture.asset(
choiceContent[index].$1,
height: 30,
),
SizedBox(height: 8),
Text(
choiceContent[index].$2,
overflow: TextOverflow.clip,
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
),
],
),
),
),
);
}),
],
);
},
);
}
}

View File

@@ -0,0 +1,25 @@
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
class CreateDietRepository {
final CreateDietService createDietService;
CreateDietRepository({required this.createDietService});
Future<Diet> createDiet({
required Map<String, dynamic> model,
}) {
return createDietService.createDiet(
model: model,
);
}
Future<void> createDietDailySchedule({
required int id,
required Map<String, dynamic> model,
}) {
return createDietService.createDietDailySchedule(
id: id,
model: model,
);
}
}

View File

@@ -1,12 +1,22 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:retrofit/retrofit.dart';
part 'create_diet_service.g.dart';
@RestApi()
abstract class CreateDietService {
factory CreateDietService(Dio dio, {String baseUrl}) = _CreateDietService;
@POST('/api/diets/create')
@MultiPart()
Future<Diet> createDiet({
@Body() required Map<String, dynamic> model,
});
@POST('/api/diets/create/{id}/daily_schedule')
Future<void> createDietDailySchedule({
@Path() required int id,
@Body() required Map<String, dynamic> model,
});
}

View File

@@ -21,6 +21,70 @@ class _CreateDietService implements CreateDietService {
final ParseErrorLogger? errorLogger;
@override
Future<Diet> createDiet({required Map<String, dynamic> model}) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(model);
final _options = _setStreamType<Diet>(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 _result = await _dio.fetch<Map<String, dynamic>>(_options);
late Diet _value;
try {
_value = Diet.fromJson(_result.data!);
} on Object catch (e, s) {
errorLogger?.logError(e, s, _options);
rethrow;
}
return _value;
}
@override
Future<void> createDietDailySchedule({
required int id,
required Map<String, dynamic> model,
}) 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);
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||

View File

@@ -13,7 +13,7 @@ import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart'
import 'package:eatvio_app/features/diets/presentation/widgets/cpfc_container.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/start_diet_bottom_sheet.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';

View File

@@ -1,7 +1,7 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/utils/toasts.dart';
import 'package:eatvio_app/core/widgets/custom_divider.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';

View File

@@ -1,4 +1,4 @@
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
@@ -23,15 +23,15 @@ class _TypeBadgesState extends State<TypeBadges> {
Widget build(BuildContext context) {
final s = S.of(context);
final List<(String, Widget)> badgeSource = [];
if (widget.type.alko == true) {
if (widget.type.light == true) {
badgeSource.add(
(
'assets/icons/cocktail.svg',
_InfoOverlayEntry(
onClose: closeOverlay,
assetPath: 'assets/icons/cocktail.svg',
title: s.alko_type,
description: s.alko_type_desc,
title: s.light_type,
description: s.light_type_desc,
)
),
);
@@ -49,15 +49,15 @@ class _TypeBadgesState extends State<TypeBadges> {
),
);
}
if (widget.type.corb == true) {
if (widget.type.carb == true) {
badgeSource.add(
(
'assets/icons/bread.svg',
_InfoOverlayEntry(
onClose: closeOverlay,
assetPath: 'assets/icons/bread.svg',
title: s.corb_type,
description: s.corb_type_desc,
title: s.carb_type,
description: s.carb_type_desc,
)
),
);

View File

@@ -77,9 +77,9 @@ final portionValues = EnumValues({"grams": Portion.GRAMS, "milliliters": Portion
@freezed
class DietType with _$DietType {
const factory DietType({
@JsonKey(name: "alko") bool? alko,
@JsonKey(name: "light") bool? light,
@JsonKey(name: "veg") bool? veg,
@JsonKey(name: "corb") bool? corb,
@JsonKey(name: "carb") bool? carb,
@JsonKey(name: "meat") bool? meat,
}) = _DietType;

View File

@@ -1259,12 +1259,12 @@ DietType _$DietTypeFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$DietType {
@JsonKey(name: "alko")
bool? get alko => throw _privateConstructorUsedError;
@JsonKey(name: "light")
bool? get light => throw _privateConstructorUsedError;
@JsonKey(name: "veg")
bool? get veg => throw _privateConstructorUsedError;
@JsonKey(name: "corb")
bool? get corb => throw _privateConstructorUsedError;
@JsonKey(name: "carb")
bool? get carb => throw _privateConstructorUsedError;
@JsonKey(name: "meat")
bool? get meat => throw _privateConstructorUsedError;
@@ -1284,9 +1284,9 @@ abstract class $DietTypeCopyWith<$Res> {
_$DietTypeCopyWithImpl<$Res, DietType>;
@useResult
$Res call(
{@JsonKey(name: "alko") bool? alko,
{@JsonKey(name: "light") bool? light,
@JsonKey(name: "veg") bool? veg,
@JsonKey(name: "corb") bool? corb,
@JsonKey(name: "carb") bool? carb,
@JsonKey(name: "meat") bool? meat});
}
@@ -1305,23 +1305,23 @@ class _$DietTypeCopyWithImpl<$Res, $Val extends DietType>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? alko = freezed,
Object? light = freezed,
Object? veg = freezed,
Object? corb = freezed,
Object? carb = freezed,
Object? meat = freezed,
}) {
return _then(_value.copyWith(
alko: freezed == alko
? _value.alko
: alko // ignore: cast_nullable_to_non_nullable
light: freezed == light
? _value.light
: light // ignore: cast_nullable_to_non_nullable
as bool?,
veg: freezed == veg
? _value.veg
: veg // ignore: cast_nullable_to_non_nullable
as bool?,
corb: freezed == corb
? _value.corb
: corb // ignore: cast_nullable_to_non_nullable
carb: freezed == carb
? _value.carb
: carb // ignore: cast_nullable_to_non_nullable
as bool?,
meat: freezed == meat
? _value.meat
@@ -1340,9 +1340,9 @@ abstract class _$$DietTypeImplCopyWith<$Res>
@override
@useResult
$Res call(
{@JsonKey(name: "alko") bool? alko,
{@JsonKey(name: "light") bool? light,
@JsonKey(name: "veg") bool? veg,
@JsonKey(name: "corb") bool? corb,
@JsonKey(name: "carb") bool? carb,
@JsonKey(name: "meat") bool? meat});
}
@@ -1359,23 +1359,23 @@ class __$$DietTypeImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? alko = freezed,
Object? light = freezed,
Object? veg = freezed,
Object? corb = freezed,
Object? carb = freezed,
Object? meat = freezed,
}) {
return _then(_$DietTypeImpl(
alko: freezed == alko
? _value.alko
: alko // ignore: cast_nullable_to_non_nullable
light: freezed == light
? _value.light
: light // ignore: cast_nullable_to_non_nullable
as bool?,
veg: freezed == veg
? _value.veg
: veg // ignore: cast_nullable_to_non_nullable
as bool?,
corb: freezed == corb
? _value.corb
: corb // ignore: cast_nullable_to_non_nullable
carb: freezed == carb
? _value.carb
: carb // ignore: cast_nullable_to_non_nullable
as bool?,
meat: freezed == meat
? _value.meat
@@ -1389,30 +1389,30 @@ class __$$DietTypeImplCopyWithImpl<$Res>
@JsonSerializable()
class _$DietTypeImpl implements _DietType {
const _$DietTypeImpl(
{@JsonKey(name: "alko") this.alko,
{@JsonKey(name: "light") this.light,
@JsonKey(name: "veg") this.veg,
@JsonKey(name: "corb") this.corb,
@JsonKey(name: "carb") this.carb,
@JsonKey(name: "meat") this.meat});
factory _$DietTypeImpl.fromJson(Map<String, dynamic> json) =>
_$$DietTypeImplFromJson(json);
@override
@JsonKey(name: "alko")
final bool? alko;
@JsonKey(name: "light")
final bool? light;
@override
@JsonKey(name: "veg")
final bool? veg;
@override
@JsonKey(name: "corb")
final bool? corb;
@JsonKey(name: "carb")
final bool? carb;
@override
@JsonKey(name: "meat")
final bool? meat;
@override
String toString() {
return 'DietType(alko: $alko, veg: $veg, corb: $corb, meat: $meat)';
return 'DietType(light: $light, veg: $veg, carb: $carb, meat: $meat)';
}
@override
@@ -1420,15 +1420,15 @@ class _$DietTypeImpl implements _DietType {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DietTypeImpl &&
(identical(other.alko, alko) || other.alko == alko) &&
(identical(other.light, light) || other.light == light) &&
(identical(other.veg, veg) || other.veg == veg) &&
(identical(other.corb, corb) || other.corb == corb) &&
(identical(other.carb, carb) || other.carb == carb) &&
(identical(other.meat, meat) || other.meat == meat));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, alko, veg, corb, meat);
int get hashCode => Object.hash(runtimeType, light, veg, carb, meat);
/// Create a copy of DietType
/// with the given fields replaced by the non-null parameter values.
@@ -1448,23 +1448,23 @@ class _$DietTypeImpl implements _DietType {
abstract class _DietType implements DietType {
const factory _DietType(
{@JsonKey(name: "alko") final bool? alko,
{@JsonKey(name: "light") final bool? light,
@JsonKey(name: "veg") final bool? veg,
@JsonKey(name: "corb") final bool? corb,
@JsonKey(name: "carb") final bool? carb,
@JsonKey(name: "meat") final bool? meat}) = _$DietTypeImpl;
factory _DietType.fromJson(Map<String, dynamic> json) =
_$DietTypeImpl.fromJson;
@override
@JsonKey(name: "alko")
bool? get alko;
@JsonKey(name: "light")
bool? get light;
@override
@JsonKey(name: "veg")
bool? get veg;
@override
@JsonKey(name: "corb")
bool? get corb;
@JsonKey(name: "carb")
bool? get carb;
@override
@JsonKey(name: "meat")
bool? get meat;

View File

@@ -108,17 +108,17 @@ const _$PortionEnumMap = {
_$DietTypeImpl _$$DietTypeImplFromJson(Map<String, dynamic> json) =>
_$DietTypeImpl(
alko: json['alko'] as bool?,
light: json['light'] as bool?,
veg: json['veg'] as bool?,
corb: json['corb'] as bool?,
carb: json['carb'] as bool?,
meat: json['meat'] as bool?,
);
Map<String, dynamic> _$$DietTypeImplToJson(_$DietTypeImpl instance) =>
<String, dynamic>{
'alko': instance.alko,
'light': instance.light,
'veg': instance.veg,
'corb': instance.corb,
'carb': instance.carb,
'meat': instance.meat,
};

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:developer';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/const.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';
@@ -14,16 +15,23 @@ class DietsCubit extends Cubit<DietsState> {
late int lastPage;
bool isLoading = false;
String? _query;
String? _types;
int? _duration;
String? _sorting;
static const List<String?> _sortingValues = [
null,
'chosen_diets_count:desc',
'created_at:desc',
'created_at',
'name',
'name:desc',
];
static const List<int?> _durationValues = [null, ...durationValues];
static const List<String?> _types = [null, ...typeValues];
late final StreamSubscription likesStateSubscription;
late final StreamSubscription favoriteStateSubscription;
late final StreamSubscription commentsStateSubscription;
DietsCubit({
required this.feedRepository,
required this.dietsRepository,
}) : super(const DietsState.loading()) {
}) : super(DietsState.initial()) {
likesStateSubscription = dietsRepository.dietLikeState.listen((likesState) {
_changeDietLikeState(likesState);
});
@@ -43,35 +51,43 @@ class DietsCubit extends Cubit<DietsState> {
super.close();
}
void changeTypeFilter(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(typeIndex: index), errorMessage: null));
loadDiets(query: _query);
}
void changeSortingType(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(sortingIndex: index), errorMessage: null));
loadDiets(query: _query);
}
void changeDurationFilter(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(durationIndex: index), errorMessage: null));
loadDiets(query: _query);
}
loadDiets({
String? query,
String? types,
int? duration,
String? sorting,
}) async {
try {
_query = query;
_types = types;
_duration = duration;
_sorting = sorting;
final type = _types[state.filterState.typeIndex];
final duration = _durationValues[state.filterState.durationIndex];
final sorting = _sortingValues[state.filterState.sortingIndex];
final dietsPagination = await feedRepository.getDiets(
query: query,
types: types,
types: type,
duration: duration,
sorting: sorting,
);
lastPage = dietsPagination.meta.lastPage;
emit(
DietsState.loaded(
dietsList: dietsPagination.data,
isLoading: isLoading,
),
state.copyWith(dietsList: dietsPagination.data, isLoading: isLoading, errorMessage: null),
);
} catch (e) {
emit(
DietsState.error(
errorMessage: e.toString(),
),
state.copyWith(errorMessage: e.toString()),
);
}
}
@@ -80,7 +96,7 @@ class DietsCubit extends Cubit<DietsState> {
if (currentPage < lastPage && !isLoading) {
isLoading = true;
emit((state as DietsStateLoaded).copyWith(isLoading: isLoading));
emit((state.copyWith(isLoading: isLoading, errorMessage: null)));
try {
if (currentPage < lastPage) {
@@ -88,31 +104,30 @@ class DietsCubit extends Cubit<DietsState> {
final dietPagination = await feedRepository.getDiets(
page: currentPage,
query: _query,
types: _types,
duration: _duration,
sorting: _sorting,
types: _types[state.filterState.typeIndex],
duration: _durationValues[state.filterState.durationIndex],
sorting: _sortingValues[state.filterState.sortingIndex],
);
isLoading = false;
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...(state as DietsStateLoaded).dietsList,
...state.dietsList,
...dietPagination.data,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
} catch (e) {
emit(DietsState.error(errorMessage: e.toString()));
emit(state.copyWith(errorMessage: e.toString()));
}
}
}
Future<void> likeDiet(int id, int index) async {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[index];
if (currentDiet.wasLikedByMe) {
@@ -121,11 +136,12 @@ class DietsCubit extends Cubit<DietsState> {
wasLikedByMe: false,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
} else {
@@ -134,11 +150,12 @@ class DietsCubit extends Cubit<DietsState> {
wasLikedByMe: true,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
@@ -154,17 +171,18 @@ class DietsCubit extends Cubit<DietsState> {
);
dietsForModification[index] = actualDiet;
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
} catch (e) {
log(e.toString());
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...currentDiets,
],
@@ -177,9 +195,7 @@ class DietsCubit extends Cubit<DietsState> {
}
void _changeDietLikeState(DietLikesState likesState) {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[likesState.index];
@@ -188,19 +204,18 @@ class DietsCubit extends Cubit<DietsState> {
wasLikedByMe: likesState.wasLikedByMe,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
void _changeDietFavoriteState(DietFavoriteState favoriteState) {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[favoriteState.index];
@@ -208,19 +223,18 @@ class DietsCubit extends Cubit<DietsState> {
isFavorite: favoriteState.isFavorite,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
void _changeDietCommentsState(DietCommentsState commentsState) {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[commentsState.index];
@@ -228,18 +242,18 @@ class DietsCubit extends Cubit<DietsState> {
totalComments: commentsState.totalComments,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
Future<void> addDietToFavorite(int id, int index) async {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[index];
@@ -247,11 +261,12 @@ class DietsCubit extends Cubit<DietsState> {
isFavorite: true,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
EasyDebounce.debounce(
@@ -262,21 +277,23 @@ class DietsCubit extends Cubit<DietsState> {
final diet = await dietsRepository.addToFavorite(id);
dietsForModification[index] = diet;
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
} catch (e) {
log(e.toString());
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...currentDiets,
],
isLoading: isLoading,
errorMessage: null,
),
);
}
@@ -285,8 +302,7 @@ class DietsCubit extends Cubit<DietsState> {
}
Future<void> removeDietFromFavorite(int id, int index) async {
if (state is! DietsStateLoaded) return;
final currentDiets = (state as DietsStateLoaded).dietsList;
final currentDiets = state.dietsList;
final dietsForModification = [...currentDiets];
final currentDiet = currentDiets[index];
@@ -294,11 +310,12 @@ class DietsCubit extends Cubit<DietsState> {
isFavorite: false,
);
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
EasyDebounce.debounce(
@@ -309,21 +326,23 @@ class DietsCubit extends Cubit<DietsState> {
final diet = await dietsRepository.removeFromFavorite(id);
dietsForModification[index] = diet;
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...dietsForModification,
],
isLoading: isLoading,
errorMessage: null,
),
);
} catch (e) {
log(e.toString());
emit(
DietsState.loaded(
state.copyWith(
dietsList: [
...currentDiets,
],
isLoading: isLoading,
errorMessage: null,
),
);
}

View File

@@ -4,17 +4,31 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'diets_state.freezed.dart';
@freezed
abstract class DietsState with _$DietsState {
const factory DietsState() = _DietsState;
const factory DietsState.loading() = DietsStateLoading;
const factory DietsState.loaded({
class DietsState with _$DietsState {
const factory DietsState({
required DietsFilterState filterState,
required List<Diet> dietsList,
required bool isLoading,
}) = DietsStateLoaded;
required String? errorMessage,
}) = _DietsState;
const factory DietsState.error({
required String errorMessage,
}) = DietsStateError;
factory DietsState.initial() => DietsState(
filterState: DietsFilterState(
durationIndex: 0,
sortingIndex: 0,
typeIndex: 0,
),
dietsList: [],
isLoading: true,
errorMessage: null,
);
}
@freezed
class DietsFilterState with _$DietsFilterState {
const factory DietsFilterState({
required int sortingIndex,
required int durationIndex,
required int typeIndex,
}) = _DietsFilterState;
}

View File

@@ -16,55 +16,15 @@ final _privateConstructorUsedError = UnsupportedError(
/// @nodoc
mixin _$DietsState {
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
required TResult Function(String errorMessage) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult? Function(String errorMessage)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_DietsState value) $default, {
required TResult Function(DietsStateLoading value) loading,
required TResult Function(DietsStateLoaded value) loaded,
required TResult Function(DietsStateError value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_DietsState value)? $default, {
TResult? Function(DietsStateLoading value)? loading,
TResult? Function(DietsStateLoaded value)? loaded,
TResult? Function(DietsStateError value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_DietsState value)? $default, {
TResult Function(DietsStateLoading value)? loading,
TResult Function(DietsStateLoaded value)? loaded,
TResult Function(DietsStateError value)? error,
required TResult orElse(),
}) =>
DietsFilterState get filterState => throw _privateConstructorUsedError;
List<Diet> get dietsList => throw _privateConstructorUsedError;
bool get isLoading => throw _privateConstructorUsedError;
String? get errorMessage => throw _privateConstructorUsedError;
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$DietsStateCopyWith<DietsState> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -73,6 +33,14 @@ abstract class $DietsStateCopyWith<$Res> {
factory $DietsStateCopyWith(
DietsState value, $Res Function(DietsState) then) =
_$DietsStateCopyWithImpl<$Res, DietsState>;
@useResult
$Res call(
{DietsFilterState filterState,
List<Diet> dietsList,
bool isLoading,
String? errorMessage});
$DietsFilterStateCopyWith<$Res> get filterState;
}
/// @nodoc
@@ -87,13 +55,61 @@ class _$DietsStateCopyWithImpl<$Res, $Val extends DietsState>
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? filterState = null,
Object? dietsList = null,
Object? isLoading = null,
Object? errorMessage = freezed,
}) {
return _then(_value.copyWith(
filterState: null == filterState
? _value.filterState
: filterState // ignore: cast_nullable_to_non_nullable
as DietsFilterState,
dietsList: null == dietsList
? _value.dietsList
: dietsList // ignore: cast_nullable_to_non_nullable
as List<Diet>,
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?,
) as $Val);
}
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$DietsFilterStateCopyWith<$Res> get filterState {
return $DietsFilterStateCopyWith<$Res>(_value.filterState, (value) {
return _then(_value.copyWith(filterState: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$DietsStateImplCopyWith<$Res> {
abstract class _$$DietsStateImplCopyWith<$Res>
implements $DietsStateCopyWith<$Res> {
factory _$$DietsStateImplCopyWith(
_$DietsStateImpl value, $Res Function(_$DietsStateImpl) then) =
__$$DietsStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{DietsFilterState filterState,
List<Diet> dietsList,
bool isLoading,
String? errorMessage});
@override
$DietsFilterStateCopyWith<$Res> get filterState;
}
/// @nodoc
@@ -106,249 +122,19 @@ class __$$DietsStateImplCopyWithImpl<$Res>
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$DietsStateImpl implements _DietsState {
const _$DietsStateImpl();
@override
String toString() {
return 'DietsState()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$DietsStateImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
required TResult Function(String errorMessage) error,
}) {
return $default();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return $default?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_DietsState value) $default, {
required TResult Function(DietsStateLoading value) loading,
required TResult Function(DietsStateLoaded value) loaded,
required TResult Function(DietsStateError value) error,
}) {
return $default(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_DietsState value)? $default, {
TResult? Function(DietsStateLoading value)? loading,
TResult? Function(DietsStateLoaded value)? loaded,
TResult? Function(DietsStateError value)? error,
}) {
return $default?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_DietsState value)? $default, {
TResult Function(DietsStateLoading value)? loading,
TResult Function(DietsStateLoaded value)? loaded,
TResult Function(DietsStateError value)? error,
required TResult orElse(),
}) {
if ($default != null) {
return $default(this);
}
return orElse();
}
}
abstract class _DietsState implements DietsState {
const factory _DietsState() = _$DietsStateImpl;
}
/// @nodoc
abstract class _$$DietsStateLoadingImplCopyWith<$Res> {
factory _$$DietsStateLoadingImplCopyWith(_$DietsStateLoadingImpl value,
$Res Function(_$DietsStateLoadingImpl) then) =
__$$DietsStateLoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$DietsStateLoadingImplCopyWithImpl<$Res>
extends _$DietsStateCopyWithImpl<$Res, _$DietsStateLoadingImpl>
implements _$$DietsStateLoadingImplCopyWith<$Res> {
__$$DietsStateLoadingImplCopyWithImpl(_$DietsStateLoadingImpl _value,
$Res Function(_$DietsStateLoadingImpl) _then)
: super(_value, _then);
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$DietsStateLoadingImpl implements DietsStateLoading {
const _$DietsStateLoadingImpl();
@override
String toString() {
return 'DietsState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$DietsStateLoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
required TResult Function(String errorMessage) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_DietsState value) $default, {
required TResult Function(DietsStateLoading value) loading,
required TResult Function(DietsStateLoaded value) loaded,
required TResult Function(DietsStateError value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_DietsState value)? $default, {
TResult? Function(DietsStateLoading value)? loading,
TResult? Function(DietsStateLoaded value)? loaded,
TResult? Function(DietsStateError value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_DietsState value)? $default, {
TResult Function(DietsStateLoading value)? loading,
TResult Function(DietsStateLoaded value)? loaded,
TResult Function(DietsStateError value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class DietsStateLoading implements DietsState {
const factory DietsStateLoading() = _$DietsStateLoadingImpl;
}
/// @nodoc
abstract class _$$DietsStateLoadedImplCopyWith<$Res> {
factory _$$DietsStateLoadedImplCopyWith(_$DietsStateLoadedImpl value,
$Res Function(_$DietsStateLoadedImpl) then) =
__$$DietsStateLoadedImplCopyWithImpl<$Res>;
@useResult
$Res call({List<Diet> dietsList, bool isLoading});
}
/// @nodoc
class __$$DietsStateLoadedImplCopyWithImpl<$Res>
extends _$DietsStateCopyWithImpl<$Res, _$DietsStateLoadedImpl>
implements _$$DietsStateLoadedImplCopyWith<$Res> {
__$$DietsStateLoadedImplCopyWithImpl(_$DietsStateLoadedImpl _value,
$Res Function(_$DietsStateLoadedImpl) _then)
: super(_value, _then);
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? filterState = null,
Object? dietsList = null,
Object? isLoading = null,
Object? errorMessage = freezed,
}) {
return _then(_$DietsStateLoadedImpl(
return _then(_$DietsStateImpl(
filterState: null == filterState
? _value.filterState
: filterState // ignore: cast_nullable_to_non_nullable
as DietsFilterState,
dietsList: null == dietsList
? _value._dietsList
: dietsList // ignore: cast_nullable_to_non_nullable
@@ -357,17 +143,26 @@ class __$$DietsStateLoadedImplCopyWithImpl<$Res>
? _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?,
));
}
}
/// @nodoc
class _$DietsStateLoadedImpl implements DietsStateLoaded {
const _$DietsStateLoadedImpl(
{required final List<Diet> dietsList, required this.isLoading})
class _$DietsStateImpl implements _DietsState {
const _$DietsStateImpl(
{required this.filterState,
required final List<Diet> dietsList,
required this.isLoading,
required this.errorMessage})
: _dietsList = dietsList;
@override
final DietsFilterState filterState;
final List<Diet> _dietsList;
@override
List<Diet> get dietsList {
@@ -378,277 +173,233 @@ class _$DietsStateLoadedImpl implements DietsStateLoaded {
@override
final bool isLoading;
@override
final String? errorMessage;
@override
String toString() {
return 'DietsState.loaded(dietsList: $dietsList, isLoading: $isLoading)';
return 'DietsState(filterState: $filterState, dietsList: $dietsList, isLoading: $isLoading, errorMessage: $errorMessage)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DietsStateLoadedImpl &&
other is _$DietsStateImpl &&
(identical(other.filterState, filterState) ||
other.filterState == filterState) &&
const DeepCollectionEquality()
.equals(other._dietsList, _dietsList) &&
(identical(other.isLoading, isLoading) ||
other.isLoading == isLoading));
other.isLoading == isLoading) &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
}
@override
int get hashCode => Object.hash(
runtimeType, const DeepCollectionEquality().hash(_dietsList), isLoading);
int get hashCode => Object.hash(runtimeType, filterState,
const DeepCollectionEquality().hash(_dietsList), isLoading, errorMessage);
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$DietsStateLoadedImplCopyWith<_$DietsStateLoadedImpl> get copyWith =>
__$$DietsStateLoadedImplCopyWithImpl<_$DietsStateLoadedImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
required TResult Function(String errorMessage) error,
}) {
return loaded(dietsList, isLoading);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return loaded?.call(dietsList, isLoading);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(dietsList, isLoading);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_DietsState value) $default, {
required TResult Function(DietsStateLoading value) loading,
required TResult Function(DietsStateLoaded value) loaded,
required TResult Function(DietsStateError value) error,
}) {
return loaded(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_DietsState value)? $default, {
TResult? Function(DietsStateLoading value)? loading,
TResult? Function(DietsStateLoaded value)? loaded,
TResult? Function(DietsStateError value)? error,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_DietsState value)? $default, {
TResult Function(DietsStateLoading value)? loading,
TResult Function(DietsStateLoaded value)? loaded,
TResult Function(DietsStateError value)? error,
required TResult orElse(),
}) {
if (loaded != null) {
return loaded(this);
}
return orElse();
}
_$$DietsStateImplCopyWith<_$DietsStateImpl> get copyWith =>
__$$DietsStateImplCopyWithImpl<_$DietsStateImpl>(this, _$identity);
}
abstract class DietsStateLoaded implements DietsState {
const factory DietsStateLoaded(
{required final List<Diet> dietsList,
required final bool isLoading}) = _$DietsStateLoadedImpl;
abstract class _DietsState implements DietsState {
const factory _DietsState(
{required final DietsFilterState filterState,
required final List<Diet> dietsList,
required final bool isLoading,
required final String? errorMessage}) = _$DietsStateImpl;
@override
DietsFilterState get filterState;
@override
List<Diet> get dietsList;
@override
bool get isLoading;
@override
String? get errorMessage;
/// Create a copy of DietsState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$DietsStateLoadedImplCopyWith<_$DietsStateLoadedImpl> get copyWith =>
_$$DietsStateImplCopyWith<_$DietsStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$DietsStateErrorImplCopyWith<$Res> {
factory _$$DietsStateErrorImplCopyWith(_$DietsStateErrorImpl value,
$Res Function(_$DietsStateErrorImpl) then) =
__$$DietsStateErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String errorMessage});
mixin _$DietsFilterState {
int get sortingIndex => throw _privateConstructorUsedError;
int get durationIndex => throw _privateConstructorUsedError;
int get typeIndex => throw _privateConstructorUsedError;
/// Create a copy of DietsFilterState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$DietsFilterStateCopyWith<DietsFilterState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
class __$$DietsStateErrorImplCopyWithImpl<$Res>
extends _$DietsStateCopyWithImpl<$Res, _$DietsStateErrorImpl>
implements _$$DietsStateErrorImplCopyWith<$Res> {
__$$DietsStateErrorImplCopyWithImpl(
_$DietsStateErrorImpl _value, $Res Function(_$DietsStateErrorImpl) _then)
: super(_value, _then);
abstract class $DietsFilterStateCopyWith<$Res> {
factory $DietsFilterStateCopyWith(
DietsFilterState value, $Res Function(DietsFilterState) then) =
_$DietsFilterStateCopyWithImpl<$Res, DietsFilterState>;
@useResult
$Res call({int sortingIndex, int durationIndex, int typeIndex});
}
/// Create a copy of DietsState
/// @nodoc
class _$DietsFilterStateCopyWithImpl<$Res, $Val extends DietsFilterState>
implements $DietsFilterStateCopyWith<$Res> {
_$DietsFilterStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of DietsFilterState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? errorMessage = null,
Object? sortingIndex = null,
Object? durationIndex = null,
Object? typeIndex = null,
}) {
return _then(_$DietsStateErrorImpl(
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
return _then(_value.copyWith(
sortingIndex: null == sortingIndex
? _value.sortingIndex
: sortingIndex // ignore: cast_nullable_to_non_nullable
as int,
durationIndex: null == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int,
typeIndex: null == typeIndex
? _value.typeIndex
: typeIndex // ignore: cast_nullable_to_non_nullable
as int,
) as $Val);
}
}
/// @nodoc
abstract class _$$DietsFilterStateImplCopyWith<$Res>
implements $DietsFilterStateCopyWith<$Res> {
factory _$$DietsFilterStateImplCopyWith(_$DietsFilterStateImpl value,
$Res Function(_$DietsFilterStateImpl) then) =
__$$DietsFilterStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int sortingIndex, int durationIndex, int typeIndex});
}
/// @nodoc
class __$$DietsFilterStateImplCopyWithImpl<$Res>
extends _$DietsFilterStateCopyWithImpl<$Res, _$DietsFilterStateImpl>
implements _$$DietsFilterStateImplCopyWith<$Res> {
__$$DietsFilterStateImplCopyWithImpl(_$DietsFilterStateImpl _value,
$Res Function(_$DietsFilterStateImpl) _then)
: super(_value, _then);
/// Create a copy of DietsFilterState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? sortingIndex = null,
Object? durationIndex = null,
Object? typeIndex = null,
}) {
return _then(_$DietsFilterStateImpl(
sortingIndex: null == sortingIndex
? _value.sortingIndex
: sortingIndex // ignore: cast_nullable_to_non_nullable
as int,
durationIndex: null == durationIndex
? _value.durationIndex
: durationIndex // ignore: cast_nullable_to_non_nullable
as int,
typeIndex: null == typeIndex
? _value.typeIndex
: typeIndex // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
class _$DietsStateErrorImpl implements DietsStateError {
const _$DietsStateErrorImpl({required this.errorMessage});
class _$DietsFilterStateImpl implements _DietsFilterState {
const _$DietsFilterStateImpl(
{required this.sortingIndex,
required this.durationIndex,
required this.typeIndex});
@override
final String errorMessage;
final int sortingIndex;
@override
final int durationIndex;
@override
final int typeIndex;
@override
String toString() {
return 'DietsState.error(errorMessage: $errorMessage)';
return 'DietsFilterState(sortingIndex: $sortingIndex, durationIndex: $durationIndex, typeIndex: $typeIndex)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$DietsStateErrorImpl &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
other is _$DietsFilterStateImpl &&
(identical(other.sortingIndex, sortingIndex) ||
other.sortingIndex == sortingIndex) &&
(identical(other.durationIndex, durationIndex) ||
other.durationIndex == durationIndex) &&
(identical(other.typeIndex, typeIndex) ||
other.typeIndex == typeIndex));
}
@override
int get hashCode => Object.hash(runtimeType, errorMessage);
int get hashCode =>
Object.hash(runtimeType, sortingIndex, durationIndex, typeIndex);
/// Create a copy of DietsState
/// Create a copy of DietsFilterState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$DietsStateErrorImplCopyWith<_$DietsStateErrorImpl> get copyWith =>
__$$DietsStateErrorImplCopyWithImpl<_$DietsStateErrorImpl>(
_$$DietsFilterStateImplCopyWith<_$DietsFilterStateImpl> get copyWith =>
__$$DietsFilterStateImplCopyWithImpl<_$DietsFilterStateImpl>(
this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>(
TResult Function() $default, {
required TResult Function() loading,
required TResult Function(List<Diet> dietsList, bool isLoading) loaded,
required TResult Function(String errorMessage) error,
}) {
return error(errorMessage);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>(
TResult? Function()? $default, {
TResult? Function()? loading,
TResult? Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult? Function(String errorMessage)? error,
}) {
return error?.call(errorMessage);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>(
TResult Function()? $default, {
TResult Function()? loading,
TResult Function(List<Diet> dietsList, bool isLoading)? loaded,
TResult Function(String errorMessage)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(errorMessage);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>(
TResult Function(_DietsState value) $default, {
required TResult Function(DietsStateLoading value) loading,
required TResult Function(DietsStateLoaded value) loaded,
required TResult Function(DietsStateError value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>(
TResult? Function(_DietsState value)? $default, {
TResult? Function(DietsStateLoading value)? loading,
TResult? Function(DietsStateLoaded value)? loaded,
TResult? Function(DietsStateError value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>(
TResult Function(_DietsState value)? $default, {
TResult Function(DietsStateLoading value)? loading,
TResult Function(DietsStateLoaded value)? loaded,
TResult Function(DietsStateError value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class DietsStateError implements DietsState {
const factory DietsStateError({required final String errorMessage}) =
_$DietsStateErrorImpl;
abstract class _DietsFilterState implements DietsFilterState {
const factory _DietsFilterState(
{required final int sortingIndex,
required final int durationIndex,
required final int typeIndex}) = _$DietsFilterStateImpl;
String get errorMessage;
@override
int get sortingIndex;
@override
int get durationIndex;
@override
int get typeIndex;
/// Create a copy of DietsState
/// Create a copy of DietsFilterState
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$DietsStateErrorImplCopyWith<_$DietsStateErrorImpl> get copyWith =>
_$$DietsFilterStateImplCopyWith<_$DietsFilterStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -1,4 +1,5 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
@@ -284,9 +285,33 @@ class _FeedScreenState extends State<FeedScreen> {
onRefresh: () => dietsCubit.loadDiets(),
child: BlocBuilder<DietsCubit, DietsState>(
builder: (BuildContext context, DietsState state) {
if (state is DietsStateLoaded) {
if (state.isLoading) {
return Scaffold(
backgroundColor: Colors.grey.shade200,
body: Center(
child: SizedBox(
height: 32,
width: 32,
child: RiveAnimation.asset(
'assets/rive_animations/loading.riv',
),
),
),
);
} else if (state.errorMessage != null) {
return Scaffold(
backgroundColor: Colors.grey.shade200,
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text(state.errorMessage ?? ''),
),
),
);
} else {
return Stack(
children: [
SizedBox.expand(),
ListView.separated(
padding: EdgeInsets.symmetric(vertical: 8),
shrinkWrap: true,
@@ -303,34 +328,13 @@ class _FeedScreenState extends State<FeedScreen> {
right: 0,
bottom: 74,
child: FilterBadge(
filterBottomSheet: DietFilterBottomSheet(),
filterBottomSheet: DietFilterBottomSheet(
dietsCubit: dietsCubit,
),
),
),
],
);
} else if (state is DietsStateError) {
return Scaffold(
backgroundColor: Colors.grey.shade200,
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text(state.errorMessage),
),
),
);
} else {
return Scaffold(
backgroundColor: Colors.grey.shade200,
body: Center(
child: SizedBox(
height: 32,
width: 32,
child: RiveAnimation.asset(
'assets/rive_animations/loading.riv',
),
),
),
);
}
},
),
@@ -472,12 +476,12 @@ class _FeedScreenState extends State<FeedScreen> {
_addItemButton() {
return InkWell(
onTap: () {
switch (_selectedChipIndex) {
case 1:
GoRouter.of(context).pushNamed('recipeCreateScreen');
switch (_selectedChipIndex) {
case 2:
GoRouter.of(context).pushNamed(CreateDietScreen.name);
break;
default:
GoRouter.of(context).pushNamed('blogPostCreateScreen');
GoRouter.of(context).pushNamed('blogPostCreateScreen');
}
},
borderRadius: BorderRadius.circular(64),

View File

@@ -2,11 +2,27 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class ChoiceChipWidget extends StatelessWidget {
const ChoiceChipWidget({super.key, required this.chipsLabelList, required this.index, required this.selectedChipIndex, required this.onSelected});
const ChoiceChipWidget({
super.key,
required this.chipsLabelList,
required this.index,
required this.selectedChipIndex,
required this.onSelected,
this.padding,
this.fontSize,
this.activeColor,
this.inactiveColor,
this.fontWeight,
});
final List<String> chipsLabelList;
final int index;
final int selectedChipIndex;
final double? fontSize;
final Color? activeColor;
final Color? inactiveColor;
final FontWeight? fontWeight;
final void Function(bool) onSelected;
final EdgeInsetsGeometry? padding;
@override
Widget build(BuildContext context) {
return ChoiceChip(
@@ -17,12 +33,12 @@ class ChoiceChipWidget extends StatelessWidget {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
label: Text(chipsLabelList[index]),
labelStyle: TextStyle(
color: index == selectedChipIndex ? Colors.white : appTheme.gray600,
fontWeight: FontWeight.w500,
fontSize: 12,
color: index == selectedChipIndex ? activeColor ?? Colors.white : inactiveColor ?? appTheme.gray600,
fontWeight: fontWeight ?? FontWeight.w500,
fontSize: fontSize ?? 12,
),
selected: selectedChipIndex == index,
backgroundColor: appTheme.gray100,

View File

@@ -1,5 +1,7 @@
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
import 'package:eatvio_app/core/widgets/custom_divider.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/duration_choice_filter_widget.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/sorting_drop_down_filter.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/type_choice_filter_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
@@ -8,8 +10,8 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class DietFilterBottomSheet extends StatelessWidget {
const DietFilterBottomSheet({super.key});
const DietFilterBottomSheet({super.key, required this.dietsCubit});
final DietsCubit dietsCubit;
@override
Widget build(BuildContext context) {
final s = S.of(context);
@@ -29,7 +31,7 @@ class DietFilterBottomSheet extends StatelessWidget {
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
),
SizedBox(height: 12),
SortingDropDownFilter(),
SortingDropDownFilter(cubit: dietsCubit,),
SizedBox(
height: 16,
),
@@ -44,7 +46,7 @@ class DietFilterBottomSheet extends StatelessWidget {
SizedBox(
height: 12,
),
TypeChoiceFilterWidget(),
TypeChoiceFilterWidget(cubit: dietsCubit,),
SizedBox(
height: 16,
),
@@ -59,7 +61,7 @@ class DietFilterBottomSheet extends StatelessWidget {
SizedBox(
height: 12,
),
TypeChoiceFilterWidget(),
DurationChoiceFilterWidget(cubit: dietsCubit,),
SizedBox(
height: 24,
),

View File

@@ -1,84 +1,85 @@
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/utils/localization_utils.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/choice_chip_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class DurationChoiceFilterWidget extends StatefulWidget {
const DurationChoiceFilterWidget({super.key});
const DurationChoiceFilterWidget({super.key, required this.cubit});
final DietsCubit cubit;
@override
State<DurationChoiceFilterWidget> createState() => _DurationChoiceFilterWidgetState();
}
class _DurationChoiceFilterWidgetState extends State<DurationChoiceFilterWidget> {
final List<String> chipsLabelList = [];
int selectedChipIndex = 0;
@override
void didChangeDependencies() {
final s = S.of(context);
super.didChangeDependencies();
if (chipsLabelList.isEmpty) {
chipsLabelList.add(s.all);
chipsLabelList.add('7 ${getDayForm(7, s)}');
chipsLabelList.add('14 ${getDayForm(14, s)}');
chipsLabelList.add('21 ${getDayForm(21, s)}');
durationValues.forEach((element) {
chipsLabelList.add('${element} ${getDayForm(element, s)}');
});
}
}
@override
Widget build(BuildContext context) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 0;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 1;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 2;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 3;
});
},
),
],
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.cubit,
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.cubit.changeDurationFilter(0);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.cubit.changeDurationFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.cubit.changeDurationFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.cubit.changeDurationFilter(3);
},
),
],
);
},
);
}
}

View File

@@ -1,20 +1,22 @@
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.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';
import 'package:flutter_bloc/flutter_bloc.dart';
class SortingDropDownFilter extends StatefulWidget {
const SortingDropDownFilter({super.key});
const SortingDropDownFilter({super.key, required this.cubit});
final DietsCubit cubit;
@override
State<SortingDropDownFilter> createState() => _SortingDropDownFilterState();
}
class _SortingDropDownFilterState extends State<SortingDropDownFilter> {
final List<String> sortingTypes = [];
int selectedIndex = 0;
@override
void didChangeDependencies() {
super.didChangeDependencies();
@@ -30,40 +32,28 @@ class _SortingDropDownFilterState extends State<SortingDropDownFilter> {
@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(
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(20)),
borderSide: BorderSide.none,
),
fillColor: appTheme.lightGray0,
filled: true,
),
value: sortingTypes[selectedIndex],
items: sortingTypes
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
sortingTypes[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: sortingTypes[index],
),
)
.toList(),
onChanged: (value) {
if (value != null) {
setState(() {
selectedIndex = sortingTypes.indexOf(value);
});
}
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.cubit,
builder: (context, state) {
return CustomDropDownButton(
items: sortingTypes
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
sortingTypes[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: sortingTypes[index],
),
)
.toList(),
value: sortingTypes[state.filterState.sortingIndex],
onChanged: (value) {
if (value != null) {
widget.cubit.changeSortingType(sortingTypes.indexOf(value));
}
},
);
},
);
}

View File

@@ -1,17 +1,19 @@
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/choice_chip_widget.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class TypeChoiceFilterWidget extends StatefulWidget {
const TypeChoiceFilterWidget({super.key});
const TypeChoiceFilterWidget({super.key, required this.cubit});
final DietsCubit cubit;
@override
State<TypeChoiceFilterWidget> createState() => _TypeChoiceFilterWidgetState();
}
class _TypeChoiceFilterWidgetState extends State<TypeChoiceFilterWidget> {
final List<String> chipsLabelList = [];
int selectedChipIndex = 0;
@override
void didChangeDependencies() {
final s = S.of(context);
@@ -19,79 +21,74 @@ class _TypeChoiceFilterWidgetState extends State<TypeChoiceFilterWidget> {
if (chipsLabelList.isEmpty) {
chipsLabelList.add(s.all);
chipsLabelList.add(s.vegan_type);
chipsLabelList.add(s.alko_type);
chipsLabelList.add(s.corb_type);
chipsLabelList.add(s.light_type);
chipsLabelList.add(s.carb_type);
chipsLabelList.add(s.meat_type);
}
}
@override
Widget build(BuildContext context) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 0;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 1;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 2;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 3;
});
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 4,
selectedChipIndex: selectedChipIndex,
onSelected: (selectedValue) {
setState(() {
selectedChipIndex = 4;
});
},
),
],
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.cubit,
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.cubit.changeTypeFilter(0);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.cubit.changeTypeFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.cubit.changeTypeFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.cubit.changeTypeFilter(3);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 4,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.cubit.changeTypeFilter(4);
},
),
],
);
},
);
}
}

View File

@@ -26,13 +26,13 @@ class MessageLookup extends MessageLookupByLibrary {
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
"active": MessageLookupByLibrary.simpleMessage("Активен"),
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
"additional_information":
MessageLookupByLibrary.simpleMessage("Дополнительная информация"),
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
"alko_type": MessageLookupByLibrary.simpleMessage("Алкоголь"),
"alko_type_desc": MessageLookupByLibrary.simpleMessage(
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
"all": MessageLookupByLibrary.simpleMessage("Все"),
"allergies_presence":
MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
@@ -47,11 +47,16 @@ class MessageLookup extends MessageLookupByLibrary {
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
"chest_circumference":
MessageLookupByLibrary.simpleMessage("Обхват груди"),
"choose_diet_duration":
MessageLookupByLibrary.simpleMessage("Выберите срок диеты"),
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
"circumference_empty": MessageLookupByLibrary.simpleMessage(
@@ -70,16 +75,15 @@ class MessageLookup extends MessageLookupByLibrary {
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
"corb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
"corb_type_desc": MessageLookupByLibrary.simpleMessage(
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
"country": MessageLookupByLibrary.simpleMessage("Страна"),
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
"day": MessageLookupByLibrary.simpleMessage("День"),
"days": MessageLookupByLibrary.simpleMessage("дней"),
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
"diet_time": MessageLookupByLibrary.simpleMessage("Время прохождения"),
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
"do_you_have_hypertension_tendency":
@@ -98,6 +102,10 @@ class MessageLookup extends MessageLookupByLibrary {
"Некорректный адрес электронной почты"),
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
"Введите любую дополнительную информацию на своё усмотрение:"),
"enter_diet_description":
MessageLookupByLibrary.simpleMessage("Введите описание диеты"),
"enter_diet_name":
MessageLookupByLibrary.simpleMessage("Выведите название диеты"),
"enter_information":
MessageLookupByLibrary.simpleMessage("Введите информацию..."),
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
@@ -116,6 +124,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Имя обязательно для заполнения"),
"first_name_short": MessageLookupByLibrary.simpleMessage(
"В имени должен быть минимум 1 символ"),
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
"gr": MessageLookupByLibrary.simpleMessage("гр"),
"grams": MessageLookupByLibrary.simpleMessage("гр"),
"height_measurements":
@@ -125,6 +134,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Обхват бедер"),
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
"initial_measurements":
MessageLookupByLibrary.simpleMessage("Первичные замеры"),
"language": MessageLookupByLibrary.simpleMessage("Язык"),
@@ -134,11 +144,15 @@ class MessageLookup extends MessageLookupByLibrary {
"last_name_short": MessageLookupByLibrary.simpleMessage(
"В фамилии должен быть минимум 6 символов"),
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
"light_type_desc": MessageLookupByLibrary.simpleMessage(
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
"link_was_copied":
MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
@@ -173,6 +187,9 @@ class MessageLookup extends MessageLookupByLibrary {
"password_short": MessageLookupByLibrary.simpleMessage(
"В пароле должно быть минимум 6 символов"),
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
"personal_diet_state":
MessageLookupByLibrary.simpleMessage("Персональная"),
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
"place_of_living":
MessageLookupByLibrary.simpleMessage("Место проживания"),
"plans_complete":
@@ -202,6 +219,7 @@ class MessageLookup extends MessageLookupByLibrary {
"user_registration":
MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),

View File

@@ -1210,11 +1210,11 @@ class S {
);
}
/// `Алкоголь`
String get alko_type {
/// `Легкая`
String get light_type {
return Intl.message(
'Алкоголь',
name: 'alko_type',
'Легкая',
name: 'light_type',
desc: '',
args: [],
);
@@ -1231,10 +1231,10 @@ class S {
}
/// `Мучное`
String get corb_type {
String get carb_type {
return Intl.message(
'Мучное',
name: 'corb_type',
name: 'carb_type',
desc: '',
args: [],
);
@@ -1251,20 +1251,20 @@ class S {
}
/// `С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.`
String get alko_type_desc {
String get light_type_desc {
return Intl.message(
'С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.',
name: 'alko_type_desc',
name: 'light_type_desc',
desc: '',
args: [],
);
}
/// `Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.`
String get corb_type_desc {
String get carb_type_desc {
return Intl.message(
'Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.',
name: 'corb_type_desc',
name: 'carb_type_desc',
desc: '',
args: [],
);
@@ -1469,6 +1469,146 @@ class S {
args: [],
);
}
/// `Создание диеты`
String get create_diet {
return Intl.message(
'Создание диеты',
name: 'create_diet',
desc: '',
args: [],
);
}
/// `Выведите название диеты`
String get enter_diet_name {
return Intl.message(
'Выведите название диеты',
name: 'enter_diet_name',
desc: '',
args: [],
);
}
/// `Введите описание диеты`
String get enter_diet_description {
return Intl.message(
'Введите описание диеты',
name: 'enter_diet_description',
desc: '',
args: [],
);
}
/// `Выберите срок диеты`
String get choose_diet_duration {
return Intl.message(
'Выберите срок диеты',
name: 'choose_diet_duration',
desc: '',
args: [],
);
}
/// `Статус диеты`
String get diet_state {
return Intl.message(
'Статус диеты',
name: 'diet_state',
desc: '',
args: [],
);
}
/// `Активная`
String get active_diet_state {
return Intl.message(
'Активная',
name: 'active_diet_state',
desc: '',
args: [],
);
}
/// `Черновик`
String get inactive_diet_state {
return Intl.message(
'Черновик',
name: 'inactive_diet_state',
desc: '',
args: [],
);
}
/// `Персональная`
String get personal_diet_state {
return Intl.message(
'Персональная',
name: 'personal_diet_state',
desc: '',
args: [],
);
}
/// `Мясо`
String get meat {
return Intl.message(
'Мясо',
name: 'meat',
desc: '',
args: [],
);
}
/// `Веган.`
String get vegan {
return Intl.message(
'Веган.',
name: 'vegan',
desc: '',
args: [],
);
}
/// `Фото`
String get photo {
return Intl.message(
'Фото',
name: 'photo',
desc: '',
args: [],
);
}
/// `Галерея`
String get gallery {
return Intl.message(
'Галерея',
name: 'gallery',
desc: '',
args: [],
);
}
/// `Добавьте обложку`
String get add_cover {
return Intl.message(
'Добавьте обложку',
name: 'add_cover',
desc: '',
args: [],
);
}
/// `Добавить`
String get add {
return Intl.message(
'Добавить',
name: 'add',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@@ -115,12 +115,12 @@
"share": "Поделиться",
"complain": "Пожаловаться",
"vegan_type": "Вегетарианская",
"alko_type": "Алкоголь",
"light_type": "Легкая",
"meat_type": "С мясом",
"corb_type": "Мучное",
"carb_type": "Мучное",
"vegan_type_desc": "Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.",
"alko_type_desc": "С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",
"corb_type_desc": "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
"light_type_desc": "С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",
"carb_type_desc": "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
"meat_type_desc": "Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.",
"diet_plan": "План диеты",
"calories": "Калории",
@@ -140,5 +140,19 @@
"most_old": "Самые старые",
"most_liked": "Больше всего лайкнутых",
"most_copleted": "Больше всего пройденных",
"by_default": "По умолчянию"
"by_default": "По умолчянию",
"create_diet": "Создание диеты",
"enter_diet_name": "Выведите название диеты",
"enter_diet_description": "Введите описание диеты",
"choose_diet_duration": "Выберите срок диеты",
"diet_state": "Статус диеты",
"active_diet_state": "Активная",
"inactive_diet_state": "Черновик",
"personal_diet_state": "Персональная",
"meat": "Мясо",
"vegan": "Веган.",
"photo": "Фото",
"gallery": "Галерея",
"add_cover": "Добавьте обложку",
"add": "Добавить"
}

View File

@@ -56,6 +56,7 @@ dependencies:
flutter_rating_bar: ^4.0.1
flutter_image_compress: ^2.3.0
image: ^4.3.0
dotted_border: ^2.1.0
dev_dependencies:
build_runner: ^2.4.13