forked from eatvio/eatvio_app
added plan pagination and updated plans creation screen
This commit is contained in:
3
assets/icons/question_mark.svg
Normal file
3
assets/icons/question_mark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.8" d="M6.39817 10.4C6.62161 10.4 6.81111 10.3228 6.96667 10.1685C7.12222 10.0143 7.2 9.82539 7.2 9.60183C7.2 9.37839 7.12283 9.18889 6.9685 9.03333C6.81428 8.87778 6.62539 8.8 6.40183 8.8C6.17839 8.8 5.98889 8.87717 5.83333 9.0315C5.67778 9.18572 5.6 9.37461 5.6 9.59817C5.6 9.82161 5.67717 10.0111 5.8315 10.1667C5.98572 10.3222 6.17461 10.4 6.39817 10.4ZM6.40467 12.8C5.52378 12.8 4.69444 12.6333 3.91667 12.3C3.13889 11.9667 2.45833 11.5083 1.875 10.925C1.29167 10.3417 0.833333 9.66133 0.5 8.884C0.166667 8.10667 0 7.27611 0 6.39233C0 5.50856 0.166667 4.68056 0.5 3.90833C0.833333 3.13611 1.29167 2.45833 1.875 1.875C2.45833 1.29167 3.13867 0.833333 3.916 0.5C4.69333 0.166667 5.52389 0 6.40767 0C7.29144 0 8.11944 0.166667 8.89167 0.5C9.66389 0.833333 10.3417 1.29167 10.925 1.875C11.5083 2.45833 11.9667 3.13733 12.3 3.912C12.6333 4.68678 12.8 5.51456 12.8 6.39533C12.8 7.27622 12.6333 8.10555 12.3 8.88333C11.9667 9.66111 11.5083 10.3417 10.925 10.925C10.3417 11.5083 9.66267 11.9667 8.888 12.3C8.11322 12.6333 7.28544 12.8 6.40467 12.8ZM6.4 11.6C7.84444 11.6 9.07222 11.0944 10.0833 10.0833C11.0944 9.07222 11.6 7.84444 11.6 6.4C11.6 4.95556 11.0944 3.72778 10.0833 2.71667C9.07222 1.70556 7.84444 1.2 6.4 1.2C4.95556 1.2 3.72778 1.70556 2.71667 2.71667C1.70556 3.72778 1.2 4.95556 1.2 6.4C1.2 7.84444 1.70556 9.07222 2.71667 10.0833C3.72778 11.0944 4.95556 11.6 6.4 11.6ZM6.45383 3.53333C6.73506 3.53333 6.97972 3.62339 7.18783 3.8035C7.39594 3.9835 7.5 4.20855 7.5 4.47867C7.5 4.72622 7.42778 4.94444 7.28333 5.13333C7.13889 5.32222 6.97222 5.49444 6.78333 5.65C6.52778 5.87222 6.3 6.12222 6.1 6.4C5.9 6.67778 5.80556 6.98889 5.81667 7.33333C5.81667 7.48889 5.87267 7.61389 5.98467 7.70833C6.09667 7.80278 6.22733 7.85 6.37667 7.85C6.53667 7.85 6.67222 7.80278 6.78333 7.70833C6.89444 7.61389 6.96667 7.48889 7 7.33333C7.05556 7.08889 7.16111 6.87311 7.31667 6.686C7.47222 6.49878 7.63889 6.32011 7.81667 6.15C8.07222 5.90556 8.28055 5.63333 8.44167 5.33333C8.60278 5.03333 8.68333 4.71111 8.68333 4.36667C8.68333 3.8 8.46389 3.33056 8.025 2.95833C7.58611 2.58611 7.06439 2.4 6.45983 2.4C6.04217 2.4 5.64722 2.49167 5.275 2.675C4.90278 2.85833 4.60467 3.12928 4.38067 3.48783C4.29356 3.61817 4.26944 3.76111 4.30833 3.91667C4.34722 4.07222 4.43889 4.18333 4.58333 4.25C4.73889 4.32778 4.89444 4.34444 5.05 4.3C5.20556 4.25556 5.33333 4.17222 5.43333 4.05C5.55556 3.89444 5.70556 3.76944 5.88333 3.675C6.06111 3.58056 6.25128 3.53333 6.45383 3.53333Z" fill="#323F4B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
6
assets/icons/trash_can.svg
Normal file
6
assets/icons/trash_can.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="22" height="24" viewBox="0 0 22 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.49914 0.0902882C6.87114 0.315243 6.38842 0.802647 6.16815 1.44002C6.09785 1.63686 6.0791 1.82901 6.0791 2.25548V2.8085H4.12012C2.29704 2.8085 2.1377 2.81318 1.894 2.89754C1.40659 3.06626 1.00823 3.38963 0.717667 3.8536C0.333368 4.47223 0.370861 5.48453 0.806712 6.12659C0.998862 6.40779 1.42065 6.75928 1.69716 6.86707L1.88462 6.93737L2.51262 14.4968C2.85474 18.6585 3.15468 22.164 3.17812 22.2859C3.31403 23.0311 3.9186 23.6965 4.66845 23.9262C4.99182 24.0246 17.0082 24.0246 17.3316 23.9262C17.6737 23.8231 17.9033 23.6872 18.1892 23.4294C18.4798 23.1576 18.7516 22.6749 18.8219 22.2906C18.8453 22.164 19.1453 18.6585 19.4874 14.5015L20.1154 6.93737L20.3028 6.86707C20.5794 6.75928 21.0011 6.40779 21.1933 6.12659C21.6291 5.48453 21.6666 4.47223 21.2823 3.8536C20.9918 3.38963 20.5934 3.06626 20.106 2.89754C19.8623 2.81318 19.703 2.8085 17.8799 2.8085H15.9209V2.25548C15.9209 1.82901 15.9022 1.63686 15.8319 1.44002C15.6116 0.793274 15.1242 0.30587 14.4821 0.0856018C14.2291 0.00124359 14.0697 -0.00344276 10.9813 0.00124359C7.94905 0.00124359 7.72878 0.0106163 7.49914 0.0902882ZM14.1306 1.51969C14.3931 1.67904 14.4774 1.87119 14.5056 2.36796L14.529 2.8085H11H7.47102L7.49445 2.36796C7.52726 1.77277 7.66785 1.54313 8.0709 1.44471C8.15057 1.42596 9.50967 1.4119 11.0937 1.41659C13.8869 1.42596 13.9807 1.43065 14.1306 1.51969ZM19.7639 4.34101C19.9795 4.47223 20.092 4.67375 20.092 4.91746C20.092 5.16116 19.9795 5.36268 19.7639 5.4939L19.5999 5.59701H11C2.4845 5.59701 2.40015 5.59701 2.24549 5.50328C1.71122 5.1799 1.83307 4.40662 2.44233 4.25665C2.522 4.2379 6.41654 4.22853 11.0937 4.22853L19.5999 4.2379L19.7639 4.34101ZM18.6391 7.05922C18.6391 7.08265 18.3626 10.4476 18.0252 14.5484C17.5378 20.4534 17.3972 22.0328 17.3362 22.1593C17.2378 22.3609 17.0738 22.4827 16.8301 22.539C16.5864 22.5952 5.41361 22.5952 5.16991 22.539C4.92621 22.4827 4.76218 22.3609 4.66376 22.1593C4.60283 22.0328 4.46224 20.4534 3.97483 14.5484C3.6374 10.4476 3.36089 7.08265 3.36089 7.05922C3.36089 7.04047 6.80084 7.02641 11 7.02641C15.2039 7.02641 18.6391 7.04047 18.6391 7.05922Z" fill="#6D6F71"/>
|
||||
<path d="M6.38842 8.52135C6.14471 8.6807 6.0791 8.84004 6.0791 9.25246C6.0791 9.45867 6.23844 12.1206 6.42591 15.1669C6.80552 21.2501 6.76334 20.8845 7.0914 21.0907C7.3023 21.2173 7.69128 21.2126 7.88812 21.0767C8.12713 20.9126 8.18806 20.7674 8.18806 20.3503C8.18806 20.1487 8.02872 17.4915 7.84125 14.4405C7.50382 9.00407 7.49445 8.89628 7.38665 8.74162C7.32573 8.65258 7.22262 8.54947 7.15233 8.50729C6.97424 8.3995 6.56182 8.40888 6.38842 8.52135Z" fill="#6D6F71"/>
|
||||
<path d="M10.6063 8.52138C10.536 8.56825 10.4329 8.67135 10.3861 8.74165C10.3017 8.87288 10.297 9.07908 10.297 14.8061C10.297 20.5331 10.3017 20.7393 10.3861 20.8705C10.5314 21.0861 10.7094 21.1798 11 21.1798C11.2906 21.1798 11.4687 21.0861 11.614 20.8705C11.6983 20.7393 11.703 20.5331 11.703 14.8061C11.703 9.07908 11.6983 8.87288 11.614 8.74165C11.4687 8.52607 11.2906 8.43234 11 8.43234C10.8266 8.43234 10.7001 8.46046 10.6063 8.52138Z" fill="#6D6F71"/>
|
||||
<path d="M14.8243 8.52148C14.4962 8.73706 14.5384 8.34808 14.1588 14.4453C13.9713 17.4916 13.812 20.1535 13.812 20.3598C13.812 20.7722 13.8776 20.9315 14.1213 21.0909C14.304 21.2127 14.7118 21.2127 14.9086 21.0909C15.2367 20.8847 15.1945 21.2502 15.5741 15.167C15.7616 12.1208 15.9209 9.45879 15.9209 9.25258C15.9209 8.84017 15.8553 8.68082 15.6116 8.52148C15.4241 8.39963 15.007 8.39963 14.8243 8.52148Z" fill="#6D6F71"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -23,7 +23,7 @@ import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit
|
||||
import 'package:eatvio_app/features/feed/presentation/pages/feed_screen.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/pages/menu_screen.dart';
|
||||
import 'package:eatvio_app/features/notifications/presentation/pages/notifications_screen.dart';
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/pages/about_plan_screen.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/pages/profile_screen.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/pages/subs_screen.dart';
|
||||
|
||||
@@ -26,7 +26,7 @@ import 'package:eatvio_app/features/consultant/become_consultant/services/consul
|
||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
|
||||
import 'package:eatvio_app/features/diary/services/diary_service.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
@@ -35,9 +35,7 @@ import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
import 'package:eatvio_app/features/feed/services/feed_service.dart';
|
||||
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
|
||||
import 'package:eatvio_app/features/glossary/services/glossary_service.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/bloc/plans_cubit/plans_cubit.dart';
|
||||
import 'package:eatvio_app/features/plans/repositories/plans_repository.dart';
|
||||
import 'package:eatvio_app/features/plans/services/plans_service.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/bloc/sub_cubit/sub_cubit.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
@@ -73,7 +71,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl(), dietsRepository: sl()));
|
||||
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<ChatSelectCubit>(() => ChatSelectCubit(chatRepository: sl()));
|
||||
sl.registerFactory<PlansCubit>(() => PlansCubit(plansRepository: sl()));
|
||||
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl()));
|
||||
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl()));
|
||||
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
||||
sl.registerFactory<DiaryCubit>(() => DiaryCubit(diaryRepository: sl(), glossaryRepository: sl()));
|
||||
@@ -91,7 +89,6 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<CalendarRepository>(() => CalendarRepository(calendarService: sl()));
|
||||
sl.registerLazySingleton<ProfileRepository>(() => ProfileRepository(profileService: sl()));
|
||||
sl.registerLazySingleton<RecipeRepository>(() => RecipeRepository(recipeService: sl()));
|
||||
sl.registerLazySingleton<PlansRepository>(() => PlansRepository(plansService: sl()));
|
||||
sl.registerLazySingleton<SettingsRepository>(() => SettingsRepository(settingsService: sl()));
|
||||
sl.registerLazySingleton<ConsultantRepository>(() => ConsultantRepository(consultantService: sl()));
|
||||
sl.registerLazySingleton<DiaryRepository>(() => DiaryRepository(diaryService: sl()));
|
||||
@@ -107,7 +104,6 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<CalendarService>(() => CalendarService(sl()));
|
||||
sl.registerLazySingleton<ProfileService>(() => ProfileService(sl()));
|
||||
sl.registerLazySingleton<RecipeService>(() => RecipeService(sl()));
|
||||
sl.registerLazySingleton<PlansService>(() => PlansService(sl()));
|
||||
sl.registerLazySingleton<SettingsService>(() => SettingsService(sl()));
|
||||
sl.registerLazySingleton<ConsultantService>(() => ConsultantService(sl()));
|
||||
sl.registerLazySingleton<DiaryService>(() => DiaryService(sl()));
|
||||
|
||||
@@ -79,6 +79,7 @@ class CustomTextFormField extends StatelessWidget {
|
||||
return Align(
|
||||
alignment: alignment ?? Alignment.center,
|
||||
child: TextFormField(
|
||||
|
||||
textAlignVertical: textAlignVertical,
|
||||
expands: expands,
|
||||
minLines: minLines,
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
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';
|
||||
@@ -17,21 +13,8 @@ class CreateDietModel with _$CreateDietModel {
|
||||
String? details,
|
||||
String? state,
|
||||
int? duration,
|
||||
required List<bool> type,
|
||||
required Map<String, bool> type,
|
||||
XFile? image,
|
||||
List<List<List<DailySchedule>>>? dailySchedule,
|
||||
}) = _CreateDietModel;
|
||||
|
||||
Future<Map<String, dynamic>> toCreationJson() async => {
|
||||
'name': name,
|
||||
'duration': duration,
|
||||
'state': state,
|
||||
'type': type,
|
||||
'details': details,
|
||||
'image': image != null ? await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image!.path))).path, filename: image!.name) : null,
|
||||
};
|
||||
|
||||
Map<String, dynamic> toDailyScheduleCreationJson() => {
|
||||
'daily_schedule': dailySchedule?.map((element) => element.map((element) => element.map((element) => element.toJson()).toList()).toList()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ mixin _$CreateDietModel {
|
||||
String? get details => throw _privateConstructorUsedError;
|
||||
String? get state => throw _privateConstructorUsedError;
|
||||
int? get duration => throw _privateConstructorUsedError;
|
||||
List<bool> get type => throw _privateConstructorUsedError;
|
||||
Map<String, bool> get type => throw _privateConstructorUsedError;
|
||||
XFile? get image => throw _privateConstructorUsedError;
|
||||
List<List<List<DailySchedule>>>? get dailySchedule =>
|
||||
throw _privateConstructorUsedError;
|
||||
@@ -43,7 +43,7 @@ abstract class $CreateDietModelCopyWith<$Res> {
|
||||
String? details,
|
||||
String? state,
|
||||
int? duration,
|
||||
List<bool> type,
|
||||
Map<String, bool> type,
|
||||
XFile? image,
|
||||
List<List<List<DailySchedule>>>? dailySchedule});
|
||||
}
|
||||
@@ -91,7 +91,7 @@ class _$CreateDietModelCopyWithImpl<$Res, $Val extends CreateDietModel>
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as List<bool>,
|
||||
as Map<String, bool>,
|
||||
image: freezed == image
|
||||
? _value.image
|
||||
: image // ignore: cast_nullable_to_non_nullable
|
||||
@@ -117,7 +117,7 @@ abstract class _$$CreateDietModelImplCopyWith<$Res>
|
||||
String? details,
|
||||
String? state,
|
||||
int? duration,
|
||||
List<bool> type,
|
||||
Map<String, bool> type,
|
||||
XFile? image,
|
||||
List<List<List<DailySchedule>>>? dailySchedule});
|
||||
}
|
||||
@@ -163,7 +163,7 @@ class __$$CreateDietModelImplCopyWithImpl<$Res>
|
||||
type: null == type
|
||||
? _value._type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as List<bool>,
|
||||
as Map<String, bool>,
|
||||
image: freezed == image
|
||||
? _value.image
|
||||
: image // ignore: cast_nullable_to_non_nullable
|
||||
@@ -184,7 +184,7 @@ class _$CreateDietModelImpl extends _CreateDietModel {
|
||||
this.details,
|
||||
this.state,
|
||||
this.duration,
|
||||
required final List<bool> type,
|
||||
required final Map<String, bool> type,
|
||||
this.image,
|
||||
final List<List<List<DailySchedule>>>? dailySchedule})
|
||||
: _type = type,
|
||||
@@ -199,12 +199,12 @@ class _$CreateDietModelImpl extends _CreateDietModel {
|
||||
final String? state;
|
||||
@override
|
||||
final int? duration;
|
||||
final List<bool> _type;
|
||||
final Map<String, bool> _type;
|
||||
@override
|
||||
List<bool> get type {
|
||||
if (_type is EqualUnmodifiableListView) return _type;
|
||||
Map<String, bool> get type {
|
||||
if (_type is EqualUnmodifiableMapView) return _type;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_type);
|
||||
return EqualUnmodifiableMapView(_type);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -267,7 +267,7 @@ abstract class _CreateDietModel extends CreateDietModel {
|
||||
final String? details,
|
||||
final String? state,
|
||||
final int? duration,
|
||||
required final List<bool> type,
|
||||
required final Map<String, bool> type,
|
||||
final XFile? image,
|
||||
final List<List<List<DailySchedule>>>? dailySchedule}) =
|
||||
_$CreateDietModelImpl;
|
||||
@@ -282,7 +282,7 @@ abstract class _CreateDietModel extends CreateDietModel {
|
||||
@override
|
||||
int? get duration;
|
||||
@override
|
||||
List<bool> get type;
|
||||
Map<String, bool> get type;
|
||||
@override
|
||||
XFile? get image;
|
||||
@override
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/core/locator_service.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';
|
||||
@@ -89,7 +93,9 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
emit(state.copyWith(dietStateIndex: index, dietData: state.dietData.copyWith(state: _dietStateValues[index])));
|
||||
}
|
||||
|
||||
void setDietType(List<bool> type) {
|
||||
void setDietType({required String key, required bool value}) {
|
||||
final type = Map<String, bool>.from(state.dietData.type);
|
||||
type[key] = value;
|
||||
emit(state.copyWith(dietData: state.dietData.copyWith(type: type)));
|
||||
}
|
||||
|
||||
@@ -248,19 +254,24 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
}
|
||||
|
||||
Future<void> publishDiet() async {
|
||||
// бек судя по всему с багом
|
||||
// try {
|
||||
// final model = await state.dietData.toCreationJson();
|
||||
// model.remove('image');
|
||||
// final dailySchedule = await state.dietData.toDailyScheduleCreationJson();
|
||||
// final dio = sl<Dio>();
|
||||
// final qwe = await dio.post('/api/diets/create', data: model);
|
||||
// // final diet = await createDietRepository.createDiet(model: model);
|
||||
// // final qwe2 = createDietRepository.createDietDailySchedule(id: diet.id, model: dailySchedule);
|
||||
// } catch (e, stackTrace) {
|
||||
// print(e);
|
||||
// print('---------------------------------');
|
||||
// print(stackTrace);
|
||||
// }
|
||||
try {
|
||||
// final types = jsonEncode(state.dietData.type);
|
||||
// if (state.dietData.image == null) {
|
||||
// return;
|
||||
// }
|
||||
// final image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
// final diet = await createDietRepository.createDiet(
|
||||
// name: state.dietData.name,
|
||||
// duration: state.dietData.duration,
|
||||
// state: state.dietData.state,
|
||||
// image: image,
|
||||
// type: types,
|
||||
// details: state.dietData.details,
|
||||
// );
|
||||
} catch (e, stackTrace) {
|
||||
print(e);
|
||||
print('---------------------------------');
|
||||
print(stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/features/create_diet/models/create_diet_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
@@ -6,14 +7,20 @@ part 'create_diet_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class CreateDietState with _$CreateDietState {
|
||||
const factory CreateDietState({
|
||||
const factory CreateDietState({
|
||||
required bool isLoading,
|
||||
required String? errorMessage,
|
||||
required CreateDietModel dietData,
|
||||
List<List<DailySchedule>>? copiedDay,
|
||||
required CreateDietModel dietData,
|
||||
List<List<DailySchedule>>? copiedDay,
|
||||
int? durationIndex,
|
||||
int? dietStateIndex,
|
||||
}) = _CreateDietState;
|
||||
|
||||
factory CreateDietState.initial() => CreateDietState(isLoading: false, errorMessage: null, dietData: CreateDietModel(type: [false, false, false, false]));
|
||||
factory CreateDietState.initial() => CreateDietState(
|
||||
isLoading: false,
|
||||
errorMessage: null,
|
||||
dietData: CreateDietModel(
|
||||
type: Map.fromIterable(typeValues, value: (element) => false),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
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/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||
@@ -18,15 +19,11 @@ class _DietTypeChoiceWidgetState extends State<DietTypeChoiceWidget> {
|
||||
final List<(String, String)> choiceContent = [];
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
// const List<String> typeValues = ['veg', 'light', 'carb', 'meat'];
|
||||
super.didChangeDependencies();
|
||||
final s = S.of(context);
|
||||
if (choiceContent.isEmpty) {
|
||||
choiceContent.add(
|
||||
(
|
||||
'assets/icons/meat2.svg',
|
||||
s.meat,
|
||||
),
|
||||
);
|
||||
|
||||
choiceContent.add(
|
||||
(
|
||||
'assets/icons/broccoli.svg',
|
||||
@@ -35,14 +32,20 @@ class _DietTypeChoiceWidgetState extends State<DietTypeChoiceWidget> {
|
||||
);
|
||||
choiceContent.add(
|
||||
(
|
||||
'assets/icons/bread.svg',
|
||||
s.carb_type,
|
||||
'assets/icons/cocktail.svg',
|
||||
s.light_type,
|
||||
),
|
||||
);
|
||||
choiceContent.add(
|
||||
(
|
||||
'assets/icons/cocktail.svg',
|
||||
s.light_type,
|
||||
'assets/icons/bread.svg',
|
||||
s.carb_type,
|
||||
),
|
||||
);
|
||||
choiceContent.add(
|
||||
(
|
||||
'assets/icons/meat2.svg',
|
||||
s.meat,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -58,18 +61,18 @@ class _DietTypeChoiceWidgetState extends State<DietTypeChoiceWidget> {
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
final dietTypes = [...state.dietData.type];
|
||||
dietTypes[index] = !dietTypes[index];
|
||||
context.read<CreateDietCubit>().setDietType(dietTypes);
|
||||
final key = typeValues[index];
|
||||
final value = !(state.dietData.type[key] ?? true);
|
||||
context.read<CreateDietCubit>().setDietType(key: key, value: value);
|
||||
},
|
||||
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,
|
||||
color: state.dietData.type[typeValues[index]] == true ? appTheme.cardBackground : appTheme.whiteA700,
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: state.dietData.type[index] ? appTheme.blueA400 : appTheme.lightGray00,
|
||||
color: state.dietData.type[typeValues[index]] == true ? appTheme.blueA400 : appTheme.lightGray00,
|
||||
),
|
||||
),
|
||||
height: 80,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
|
||||
@@ -6,10 +8,20 @@ class CreateDietRepository {
|
||||
CreateDietRepository({required this.createDietService});
|
||||
|
||||
Future<Diet> createDiet({
|
||||
required Map<String, dynamic> model,
|
||||
String? name,
|
||||
int? duration,
|
||||
String? state,
|
||||
String? type,
|
||||
String? details,
|
||||
File? image,
|
||||
}) {
|
||||
return createDietService.createDiet(
|
||||
model: model,
|
||||
name: name,
|
||||
duration: duration,
|
||||
state: state,
|
||||
type: type,
|
||||
details: details,
|
||||
image: image,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
@@ -11,7 +13,12 @@ abstract class CreateDietService {
|
||||
@POST('/api/diets/create')
|
||||
@MultiPart()
|
||||
Future<Diet> createDiet({
|
||||
@Body() required Map<String, dynamic> model,
|
||||
@Part(name: 'name') String? name,
|
||||
@Part(name: 'duration') int? duration,
|
||||
@Part(name: 'state') String? state,
|
||||
@Part(name: 'type') String? type,
|
||||
@Part(name: 'details') String? details,
|
||||
@Part(name: 'image') File? image,
|
||||
});
|
||||
|
||||
@POST('/api/diets/create/{id}/daily_schedule')
|
||||
|
||||
@@ -22,12 +22,60 @@ class _CreateDietService implements CreateDietService {
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<Diet> createDiet({required Map<String, dynamic> model}) async {
|
||||
Future<Diet> createDiet({
|
||||
String? name,
|
||||
int? duration,
|
||||
String? state,
|
||||
String? type,
|
||||
String? details,
|
||||
File? image,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
queryParameters.removeWhere((k, v) => v == null);
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = <String, dynamic>{};
|
||||
_data.addAll(model);
|
||||
final _data = FormData();
|
||||
if (name != null) {
|
||||
_data.fields.add(MapEntry(
|
||||
'name',
|
||||
name,
|
||||
));
|
||||
}
|
||||
if (duration != null) {
|
||||
_data.fields.add(MapEntry(
|
||||
'duration',
|
||||
duration.toString(),
|
||||
));
|
||||
}
|
||||
if (state != null) {
|
||||
_data.fields.add(MapEntry(
|
||||
'state',
|
||||
state,
|
||||
));
|
||||
}
|
||||
if (type != null) {
|
||||
_data.fields.add(MapEntry(
|
||||
'type',
|
||||
type,
|
||||
));
|
||||
}
|
||||
if (details != null) {
|
||||
_data.fields.add(MapEntry(
|
||||
'details',
|
||||
details,
|
||||
));
|
||||
}
|
||||
if (image != null) {
|
||||
if (image != null) {
|
||||
_data.files.add(MapEntry(
|
||||
'image',
|
||||
MultipartFile.fromFileSync(
|
||||
image.path,
|
||||
filename: image.path.split(Platform.pathSeparator).last,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
final _options = _setStreamType<Diet>(Options(
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
@@ -16,7 +16,7 @@ class CreatePlanModel with _$CreatePlanModel {
|
||||
String? name,
|
||||
String? details,
|
||||
String? state,
|
||||
int? duration,
|
||||
int? duration,
|
||||
required List<bool> type,
|
||||
XFile? image,
|
||||
required List<PacketOptions> options,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
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/widgets/custom_outlined_button.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_plan/presentation/cubit/create_plan_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/widgets/option_widget.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/widgets/options_count_button.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/widgets/plan_duration_drop_down_widget.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/widgets/plan_image_picker_widget.dart';
|
||||
@@ -118,7 +121,7 @@ class CreatePlanScreenContent extends StatelessWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Text(
|
||||
s.plan_desc,
|
||||
s.services,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
@@ -127,16 +130,80 @@ class CreatePlanScreenContent extends StatelessWidget {
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
OptionsCountButton(),
|
||||
SizedBox(height: 200),
|
||||
SizedBox(height: 20),
|
||||
BlocBuilder<CreatePlanCubit, CreatePlanState>(
|
||||
buildWhen: (previous, current) => previous.selectedOptionIndex != current.selectedOptionIndex,
|
||||
builder: (context, state) {
|
||||
if (state.selectedOptionIndex == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Text(
|
||||
'${s.option} ${(state.selectedOptionIndex ?? 0) + 1}',
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.blueGray400),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
OptionWidget(),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {},
|
||||
text: s.to_draft,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.dottedBorder),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
CustomOutlinedButton(
|
||||
onPressed: () async {},
|
||||
text: s.preview,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.dottedBorder),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {},
|
||||
text: s.publish,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24.0),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SelectExactOptionWidget(),
|
||||
),
|
||||
BlocBuilder<CreatePlanCubit, CreatePlanState>(
|
||||
builder: (context, state) {
|
||||
if (state.selectedOptionIndex == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24.0),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SelectExactOptionWidget(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -14,6 +14,45 @@ class CreatePlanCubit extends Cubit<CreatePlanState> {
|
||||
emit(state.copyWith(planData: state.planData.copyWith(name: name)));
|
||||
}
|
||||
|
||||
void setOptionTitle(String title) {
|
||||
final options = [...state.planData.options];
|
||||
options[state.selectedOptionIndex ?? 0] = options[state.selectedOptionIndex ?? 0].copyWith(short: title);
|
||||
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||
}
|
||||
|
||||
void setPrice(double price){
|
||||
final selectedOptionIndex = state.selectedOptionIndex ?? 0;
|
||||
final options = [...state.planData.options];
|
||||
options[selectedOptionIndex] = options[selectedOptionIndex].copyWith(price: price);
|
||||
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||
}
|
||||
|
||||
void setOptionDescription(String description) {
|
||||
final options = [...state.planData.options];
|
||||
options[state.selectedOptionIndex ?? 0] = options[state.selectedOptionIndex ?? 0].copyWith(description: description);
|
||||
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||
}
|
||||
|
||||
void setOptionContent(String content, index) {
|
||||
final options = [...state.planData.options];
|
||||
final items = [...options[state.selectedOptionIndex ?? 0].items];
|
||||
if (items.length <= index) {
|
||||
items.add(content);
|
||||
}else {
|
||||
items[index] = content;
|
||||
}
|
||||
options[state.selectedOptionIndex ?? 0] = options[state.selectedOptionIndex ?? 0].copyWith(items: items);
|
||||
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||
}
|
||||
|
||||
void removeOptionContentItem(int index) {
|
||||
final options = [...state.planData.options];
|
||||
final updatedItems = [...options[state.selectedOptionIndex ?? 0].items];
|
||||
updatedItems.removeAt(index);
|
||||
options[state.selectedOptionIndex ?? 0] = options[state.selectedOptionIndex ?? 0].copyWith(items: updatedItems);
|
||||
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||
}
|
||||
|
||||
void setDuration(int index) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:eatvio_app/features/create_plan/models/create_plan_model.dart';
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'create_plan_state.freezed.dart';
|
||||
@@ -9,7 +9,7 @@ class CreatePlanState with _$CreatePlanState {
|
||||
const factory CreatePlanState({
|
||||
required bool isLoading,
|
||||
required String? errorMessage,
|
||||
required CreatePlanModel planData,
|
||||
required CreatePlanModel planData,
|
||||
int? durationIndex,
|
||||
int? selectedOptionIndex,
|
||||
}) = _CreatePlanState;
|
||||
@@ -20,6 +20,6 @@ class CreatePlanState with _$CreatePlanState {
|
||||
planData: CreatePlanModel(
|
||||
type: [false, false, false, false],
|
||||
options: [PacketOptions.empty(), PacketOptions.empty(), PacketOptions.empty()],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class AddItemWidget extends StatefulWidget {
|
||||
AddItemWidget({
|
||||
super.key,
|
||||
required this.canBeDeleted,
|
||||
required this.enableHint,
|
||||
required this.index,
|
||||
required this.items,
|
||||
});
|
||||
final int index;
|
||||
final bool canBeDeleted;
|
||||
final bool enableHint;
|
||||
final List<String> items;
|
||||
@override
|
||||
State<AddItemWidget> createState() => _AddItemWidgetState();
|
||||
}
|
||||
|
||||
class _AddItemWidgetState extends State<AddItemWidget> {
|
||||
final controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void didUpdateWidget(oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (!widget.canBeDeleted && widget.items.length >= widget.index) {
|
||||
controller.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
if (widget.items.length > widget.index && controller.text != widget.items[widget.index]) {
|
||||
controller.text = widget.items[widget.index];
|
||||
}
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CustomTextFormField(
|
||||
controller: controller,
|
||||
hintText: widget.enableHint ? s.option_content_hint_text : null,
|
||||
onChanged: (value) {
|
||||
context.read<CreatePlanCubit>().setOptionContent(value, widget.index);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (widget.canBeDeleted) ...[
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CreatePlanCubit>().removeOptionContentItem(widget.index);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.lightGray0,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: SvgPicture.asset('assets/icons/trash_can.svg', width: 20, height: 24),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,320 @@
|
||||
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_text_form_field.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/widgets/add_item_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_portal/flutter_portal.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class OptionWidget extends StatelessWidget {
|
||||
const OptionWidget({super.key});
|
||||
class OptionWidget extends StatefulWidget {
|
||||
OptionWidget({super.key});
|
||||
|
||||
@override
|
||||
State<OptionWidget> createState() => _OptionWidgetState();
|
||||
}
|
||||
|
||||
class _OptionWidgetState extends State<OptionWidget> {
|
||||
final customerPriceController = TextEditingController()..text = '1200₽';
|
||||
final creatorPriceController = TextEditingController()..text = '1000₽';
|
||||
final optionTitleController = TextEditingController();
|
||||
final optionDescriptionController = TextEditingController();
|
||||
bool firstExplanationVisible = false;
|
||||
bool isChecked = false;
|
||||
bool secondExplanationVisible = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
customerPriceController.addListener(() {
|
||||
if (!customerPriceController.text.endsWith('₽')) {
|
||||
final textWithoutCurrency = customerPriceController.text.replaceAll('₽', '');
|
||||
customerPriceController.value = TextEditingValue(
|
||||
text: "$textWithoutCurrency₽",
|
||||
selection: TextSelection.collapsed(offset: textWithoutCurrency.length),
|
||||
);
|
||||
}
|
||||
final price = double.tryParse(customerPriceController.text.replaceAll('₽', ''));
|
||||
if (price != null && price < 1200) {
|
||||
customerPriceController.value = TextEditingValue(
|
||||
text: "1200₽",
|
||||
selection: TextSelection.collapsed(offset: 4),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
creatorPriceController.addListener(() {
|
||||
if (!creatorPriceController.text.endsWith('₽')) {
|
||||
final textWithoutCurrency = creatorPriceController.text.replaceAll('₽', '');
|
||||
creatorPriceController.value = TextEditingValue(
|
||||
text: "$textWithoutCurrency₽",
|
||||
selection: TextSelection.collapsed(offset: textWithoutCurrency.length),
|
||||
);
|
||||
}
|
||||
final price = double.tryParse(creatorPriceController.text.replaceAll('₽', ''));
|
||||
if (price != null && price < 1000) {
|
||||
creatorPriceController.value = TextEditingValue(
|
||||
text: "1000₽",
|
||||
selection: TextSelection.collapsed(offset: 4),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Placeholder();
|
||||
final s = S.of(context);
|
||||
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
|
||||
builder: (context, state) {
|
||||
final optionNameHintText = switch (state.selectedOptionIndex ?? 1) {
|
||||
0 => s.economy,
|
||||
2 => s.comfort,
|
||||
_ => s.standard,
|
||||
};
|
||||
final selectedOptionIndex = state.selectedOptionIndex ?? 0;
|
||||
|
||||
optionTitleController.text = state.planData.options[selectedOptionIndex].short;
|
||||
optionDescriptionController.text = state.planData.options[selectedOptionIndex].description;
|
||||
return MainBackgroundBouble(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
s.option_title,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
hintText: optionNameHintText,
|
||||
controller: optionTitleController,
|
||||
onChanged: (value) {
|
||||
context.read<CreatePlanCubit>().setOptionTitle(value);
|
||||
},
|
||||
maxLength: 150,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text(
|
||||
s.option_desc,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
SizedBox(
|
||||
height: 120,
|
||||
child: CustomTextFormField(
|
||||
controller: optionDescriptionController,
|
||||
textAlignVertical: TextAlignVertical.top,
|
||||
maxLength: 1000,
|
||||
minLines: null,
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
hintText: s.option_desc_hint_text,
|
||||
onChanged: (value) {
|
||||
context.read<CreatePlanCubit>().setOptionDescription(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
s.you_will_get,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
_PriceExplanationWidget(),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
controller: creatorPriceController,
|
||||
onChanged: (value) {
|
||||
double? price = double.tryParse(value.replaceAll('₽', ''));
|
||||
if (price != null) {
|
||||
price = price * 1.2;
|
||||
customerPriceController.text = price.toStringAsFixed(2);
|
||||
context.read<CreatePlanCubit>().setPrice(price);
|
||||
}
|
||||
},
|
||||
maxLength: 20,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
s.customer_price,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
_PriceExplanationWidget(),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
controller: customerPriceController,
|
||||
textInputType: TextInputType.numberWithOptions(decimal: true),
|
||||
onChanged: (value) {
|
||||
final price = double.tryParse(value.replaceAll('₽', ''));
|
||||
if (price != null) {
|
||||
creatorPriceController.text = (price * 0.8).toStringAsFixed(2);
|
||||
context.read<CreatePlanCubit>().setPrice(price);
|
||||
}
|
||||
},
|
||||
maxLength: 20,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
s.minimal_customer_price,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
CustomDivider(),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
s.option_content,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
reverse: false,
|
||||
itemBuilder: (context, index) {
|
||||
final items = state.planData.options[selectedOptionIndex].items;
|
||||
|
||||
if (items.isEmpty) {
|
||||
return AddItemWidget(
|
||||
index: index,
|
||||
canBeDeleted: false,
|
||||
enableHint: true,
|
||||
items: items,
|
||||
);
|
||||
} else {
|
||||
if (index < items.length) {
|
||||
return AddItemWidget(
|
||||
canBeDeleted: true,
|
||||
enableHint: false,
|
||||
index: index,
|
||||
items: items,
|
||||
);
|
||||
} else {
|
||||
return AddItemWidget(
|
||||
canBeDeleted: false,
|
||||
enableHint: false,
|
||||
index: index,
|
||||
items: items,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
itemCount: state.planData.options[selectedOptionIndex].items.length + 1,
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
CustomDivider(),
|
||||
SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: isChecked,
|
||||
activeColor: appTheme.gray,
|
||||
checkColor: appTheme.gray,
|
||||
fillColor: WidgetStatePropertyAll(Colors.transparent),
|
||||
side: WidgetStateBorderSide.resolveWith(
|
||||
(Set<WidgetState> states) {
|
||||
return BorderSide(width: 1, color: appTheme.gray);
|
||||
},
|
||||
),
|
||||
onChanged: (bool? value) {
|
||||
setState(() {
|
||||
isChecked = value ?? false;
|
||||
});
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
s.option_personal_diet_desc,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _PriceExplanationWidget extends StatefulWidget {
|
||||
const _PriceExplanationWidget();
|
||||
|
||||
@override
|
||||
State<_PriceExplanationWidget> createState() => _PriceExplanationWidgetState();
|
||||
}
|
||||
|
||||
class _PriceExplanationWidgetState extends State<_PriceExplanationWidget> {
|
||||
bool visible = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return PortalTarget(
|
||||
closeDuration: Duration(milliseconds: 300),
|
||||
portalFollower: AnimatedContainer(
|
||||
padding: EdgeInsets.all(10),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: visible ? appTheme.black : Colors.transparent,
|
||||
),
|
||||
child: AnimatedDefaultTextStyle(
|
||||
style: TextStyles.textMMediumAuto.copyWith(
|
||||
color: visible ? appTheme.whiteA700 : Colors.transparent,
|
||||
),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: Text(
|
||||
s.price_explanation,
|
||||
),
|
||||
),
|
||||
),
|
||||
visible: visible,
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.bottomLeft,
|
||||
target: Alignment.topRight,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
visible = !visible;
|
||||
});
|
||||
},
|
||||
child: SvgPicture.asset('assets/icons/question_mark.svg', height: 12, width: 12),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class _AnimatedOptionButton extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
@@ -69,7 +69,7 @@ class _AnimatedOptionButton extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
style: TextStyles.textMSemibold.copyWith(
|
||||
color: isSelected ? appTheme.whiteA700 : appTheme.black,
|
||||
),
|
||||
|
||||
@@ -1,25 +1,47 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/cubit/create_plan_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class SelectExactOptionWidget extends StatelessWidget {
|
||||
class SelectExactOptionWidget extends StatefulWidget {
|
||||
const SelectExactOptionWidget({super.key});
|
||||
|
||||
@override
|
||||
State<SelectExactOptionWidget> createState() => _SelectExactOptionWidgetState();
|
||||
}
|
||||
|
||||
class _SelectExactOptionWidgetState extends State<SelectExactOptionWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 140,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.black,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
_OptionButton(isSelected: true, text: '1'),
|
||||
_OptionButton(isSelected: true, text: '2'),
|
||||
_OptionButton(isSelected: true, text: '3'),
|
||||
],
|
||||
),
|
||||
return BlocBuilder<CreatePlanCubit, CreatePlanState>(
|
||||
builder: (context, state) {
|
||||
final selectedIndex = state.selectedOptionIndex;
|
||||
return Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
width: 140,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.black,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
...List.generate(
|
||||
3,
|
||||
(index) => Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CreatePlanCubit>().setSelectedOptionIndex(index);
|
||||
},
|
||||
child: _OptionButton(isSelected: selectedIndex == index, text: '${index + 1}'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -30,13 +52,21 @@ class _OptionButton extends StatelessWidget {
|
||||
final String text;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.whiteA700,
|
||||
color: isSelected ? appTheme.whiteA700 : Colors.transparent,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Text(text),
|
||||
child: Center(
|
||||
child: AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
style: TextStyle(color: isSelected ? appTheme.black : appTheme.whiteA700),
|
||||
child: Text(
|
||||
text,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_state.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_state.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
@@ -8,8 +8,8 @@ import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/core/widgets/diet_info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_state.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_state.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
||||
import 'package:eatvio_app/core/widgets/cpfc_container.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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/diets/presentation/bloc/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/calendar_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
|
||||
@@ -34,7 +34,7 @@ class PlanModel with _$PlanModel {
|
||||
@JsonKey(name: "author") required Author author,
|
||||
@JsonKey(name: "total_likes") required int totalLikes,
|
||||
@JsonKey(name: "total_views") required int totalViews,
|
||||
@JsonKey(name: "total_comments") required int totalComments,
|
||||
@JsonKey(name: "total_comments") required int totalComments,
|
||||
}) = _PlanModel;
|
||||
|
||||
factory PlanModel.fromJson(Map<String, dynamic> json) => _$PlanModelFromJson(json);
|
||||
@@ -51,7 +51,7 @@ class PacketOptions with _$PacketOptions {
|
||||
|
||||
factory PacketOptions.fromJson(Map<String, dynamic> json) => _$PacketOptionsFromJson(json);
|
||||
|
||||
factory PacketOptions.empty() => PacketOptions(items: [], price: -1, short: '', description: '');
|
||||
factory PacketOptions.empty() => PacketOptions(items: [], price: 1200, short: '', description: '');
|
||||
}
|
||||
|
||||
@freezed
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_state.dart';
|
||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class PlansCubit extends Cubit<PlansState> {
|
||||
final FeedRepository feedRepository;
|
||||
int currentPage = 1;
|
||||
late int lastPage;
|
||||
bool isLoading = false;
|
||||
String? _query;
|
||||
|
||||
PlansCubit({
|
||||
required this.feedRepository,
|
||||
}) : super(PlansState.initial());
|
||||
|
||||
loadPlans({
|
||||
String? query,
|
||||
}) async {
|
||||
try {
|
||||
_query = query;
|
||||
final plansPagination = await feedRepository.getPlans(
|
||||
query: query,
|
||||
);
|
||||
lastPage = plansPagination.meta.lastPage;
|
||||
emit(
|
||||
state.copyWith(
|
||||
plans: plansPagination.data,
|
||||
errorMessage: null,
|
||||
isLoading: false,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(state.copyWith(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
loadNextPage() async {
|
||||
if (currentPage < lastPage && !isLoading) {
|
||||
isLoading = true;
|
||||
|
||||
emit((state.copyWith(isLoading: isLoading, errorMessage: null)));
|
||||
|
||||
try {
|
||||
if (currentPage < lastPage) {
|
||||
currentPage++;
|
||||
final plansPagination = await feedRepository.getPlans(
|
||||
page: currentPage,
|
||||
query: _query,
|
||||
);
|
||||
isLoading = false;
|
||||
emit(
|
||||
state.copyWith(
|
||||
plans: [
|
||||
...state.plans,
|
||||
...plansPagination.data,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'plans_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class PlansState with _$PlansState {
|
||||
const factory PlansState({
|
||||
required bool isLoading,
|
||||
required List<PlanModel> plans,
|
||||
required String? errorMessage,
|
||||
}) = _PlansState;
|
||||
|
||||
factory PlansState.initial() => const _PlansState(
|
||||
isLoading: true,
|
||||
plans: [],
|
||||
errorMessage: null,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'plans_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$PlansState {
|
||||
bool get isLoading => throw _privateConstructorUsedError;
|
||||
List<PlanModel> get plans => throw _privateConstructorUsedError;
|
||||
String? get errorMessage => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$PlansStateCopyWith<PlansState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $PlansStateCopyWith<$Res> {
|
||||
factory $PlansStateCopyWith(
|
||||
PlansState value, $Res Function(PlansState) then) =
|
||||
_$PlansStateCopyWithImpl<$Res, PlansState>;
|
||||
@useResult
|
||||
$Res call({bool isLoading, List<PlanModel> plans, String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$PlansStateCopyWithImpl<$Res, $Val extends PlansState>
|
||||
implements $PlansStateCopyWith<$Res> {
|
||||
_$PlansStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? plans = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
plans: null == plans
|
||||
? _value.plans
|
||||
: plans // ignore: cast_nullable_to_non_nullable
|
||||
as List<PlanModel>,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PlansStateImplCopyWith<$Res>
|
||||
implements $PlansStateCopyWith<$Res> {
|
||||
factory _$$PlansStateImplCopyWith(
|
||||
_$PlansStateImpl value, $Res Function(_$PlansStateImpl) then) =
|
||||
__$$PlansStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({bool isLoading, List<PlanModel> plans, String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PlansStateImplCopyWithImpl<$Res>
|
||||
extends _$PlansStateCopyWithImpl<$Res, _$PlansStateImpl>
|
||||
implements _$$PlansStateImplCopyWith<$Res> {
|
||||
__$$PlansStateImplCopyWithImpl(
|
||||
_$PlansStateImpl _value, $Res Function(_$PlansStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? plans = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_$PlansStateImpl(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
plans: null == plans
|
||||
? _value._plans
|
||||
: plans // ignore: cast_nullable_to_non_nullable
|
||||
as List<PlanModel>,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PlansStateImpl implements _PlansState {
|
||||
const _$PlansStateImpl(
|
||||
{required this.isLoading,
|
||||
required final List<PlanModel> plans,
|
||||
required this.errorMessage})
|
||||
: _plans = plans;
|
||||
|
||||
@override
|
||||
final bool isLoading;
|
||||
final List<PlanModel> _plans;
|
||||
@override
|
||||
List<PlanModel> get plans {
|
||||
if (_plans is EqualUnmodifiableListView) return _plans;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_plans);
|
||||
}
|
||||
|
||||
@override
|
||||
final String? errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlansState(isLoading: $isLoading, plans: $plans, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PlansStateImpl &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading) &&
|
||||
const DeepCollectionEquality().equals(other._plans, _plans) &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, isLoading,
|
||||
const DeepCollectionEquality().hash(_plans), errorMessage);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$PlansStateImplCopyWith<_$PlansStateImpl> get copyWith =>
|
||||
__$$PlansStateImplCopyWithImpl<_$PlansStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _PlansState implements PlansState {
|
||||
const factory _PlansState(
|
||||
{required final bool isLoading,
|
||||
required final List<PlanModel> plans,
|
||||
required final String? errorMessage}) = _$PlansStateImpl;
|
||||
|
||||
@override
|
||||
bool get isLoading;
|
||||
@override
|
||||
List<PlanModel> get plans;
|
||||
@override
|
||||
String? get errorMessage;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$PlansStateImplCopyWith<_$PlansStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -16,8 +16,8 @@ import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart'
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/plan_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/recipes_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/tags_modal_widget.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/bloc/plans_cubit/plans_cubit.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/bloc/plans_cubit/plans_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_state.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -76,7 +76,7 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
|
||||
_onScrollPlans() {
|
||||
if (plansScrollController.offset >= plansScrollController.position.maxScrollExtent && !plansScrollController.position.outOfRange) {
|
||||
// plansCubit.loadNextPage();
|
||||
plansCubit.loadNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,11 +119,13 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
),
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: NestedScrollView(
|
||||
controller: _selectedChipIndex == 0
|
||||
? blogPostsScrollController
|
||||
: _selectedChipIndex == 1
|
||||
? recipesScrollController
|
||||
: dietsScrollController,
|
||||
controller: switch (_selectedChipIndex) {
|
||||
0 => blogPostsScrollController,
|
||||
1 => recipesScrollController,
|
||||
2 => dietsScrollController,
|
||||
3 => plansScrollController,
|
||||
_ => blogPostsScrollController
|
||||
},
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverAppBar(
|
||||
@@ -317,35 +319,34 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
onRefresh: () => plansCubit.loadPlans(),
|
||||
child: BlocBuilder<PlansCubit, PlansState>(
|
||||
builder: (BuildContext context, PlansState state) {
|
||||
if (state is PlansStateLoaded) {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return PlanWidget(planModel: state.plansModel.data[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.plansModel.data.length,
|
||||
if (state.isLoading) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: const Loader(),
|
||||
);
|
||||
} else if (state is PlansStateError) {
|
||||
} else if (state.errorMessage != null) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage),
|
||||
child: Text(state.errorMessage ?? ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: const Loader(),
|
||||
);
|
||||
}
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return PlanWidget(planModel: state.plans[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.plans.length,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:eatvio_app/features/feed/models/comment_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_settings_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/feed/services/feed_service.dart';
|
||||
|
||||
@@ -62,6 +63,22 @@ class FeedRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<PlanPaginationModel> getPlans({
|
||||
int page = 1,
|
||||
String? query,
|
||||
String? types,
|
||||
int? duration,
|
||||
String? sorting,
|
||||
}) async {
|
||||
try {
|
||||
return (await feedService.getPlans(
|
||||
page: page,
|
||||
));
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<CommentModel> getBlogPostComments({
|
||||
required String id,
|
||||
}) async {
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/comment_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_settings_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_pagination_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
@@ -27,10 +28,15 @@ abstract class FeedService {
|
||||
@GET('/api/diets/index')
|
||||
Future<DietsPagination> getDiets({
|
||||
@Query('page') required int page,
|
||||
@Query('filters[name][\$startsWith]') String? query,
|
||||
@Query('filters[type][\$contains]') String? types,
|
||||
@Query('filters[duration][\$eq]') int? duration,
|
||||
@Query('sort') String? sorting,
|
||||
@Query('filters[name][\$startsWith]') String? query,
|
||||
@Query('filters[type][\$contains]') String? types,
|
||||
@Query('filters[duration][\$eq]') int? duration,
|
||||
@Query('sort') String? sorting,
|
||||
});
|
||||
|
||||
@GET('/api/plans/index')
|
||||
Future<PlanPaginationModel> getPlans({
|
||||
@Query('page') required int page,
|
||||
});
|
||||
|
||||
@GET('/api/blogPosts/{id}/comments/show')
|
||||
@@ -77,6 +83,5 @@ abstract class FeedService {
|
||||
@POST('/api/blogPosts/{id}/unliked')
|
||||
Future<void> unlikedBlogPost({
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -149,6 +149,39 @@ class _FeedService implements FeedService {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PlanPaginationModel> getPlans({required int page}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{r'page': page};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<PlanPaginationModel>(Options(
|
||||
method: 'GET',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/plans/index',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||
late PlanPaginationModel _value;
|
||||
try {
|
||||
_value = PlanPaginationModel.fromJson(_result.data!);
|
||||
} on Object catch (e, s) {
|
||||
errorLogger?.logError(e, s, _options);
|
||||
rethrow;
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CommentModel> getBlogPostComments({required String id}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:eatvio_app/features/plans/presentation/bloc/plans_cubit/plans_state.dart';
|
||||
import 'package:eatvio_app/features/plans/repositories/plans_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class PlansCubit extends Cubit<PlansState> {
|
||||
final PlansRepository plansRepository;
|
||||
|
||||
PlansCubit({
|
||||
required this.plansRepository,
|
||||
}) : super(PlansState.loading());
|
||||
|
||||
loadPlans() async {
|
||||
try {
|
||||
emit(PlansState.loaded(plansModel: await plansRepository.getPlans()));
|
||||
} catch (e) {
|
||||
emit(PlansState.error(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'plans_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class PlansState with _$PlansState {
|
||||
const factory PlansState() = _PlansState;
|
||||
|
||||
const factory PlansState.loading() = PlansStateLoading;
|
||||
|
||||
const factory PlansState.loaded({
|
||||
required PlanPaginationModel plansModel,
|
||||
}) = PlansStateLoaded;
|
||||
|
||||
const factory PlansState.error({
|
||||
required String errorMessage,
|
||||
}) = PlansStateError;
|
||||
}
|
||||
@@ -1,646 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'plans_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$PlansState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(PlanPaginationModel plansModel) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_PlansState value) $default, {
|
||||
required TResult Function(PlansStateLoading value) loading,
|
||||
required TResult Function(PlansStateLoaded value) loaded,
|
||||
required TResult Function(PlansStateError value) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_PlansState value)? $default, {
|
||||
TResult? Function(PlansStateLoading value)? loading,
|
||||
TResult? Function(PlansStateLoaded value)? loaded,
|
||||
TResult? Function(PlansStateError value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_PlansState value)? $default, {
|
||||
TResult Function(PlansStateLoading value)? loading,
|
||||
TResult Function(PlansStateLoaded value)? loaded,
|
||||
TResult Function(PlansStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $PlansStateCopyWith<$Res> {
|
||||
factory $PlansStateCopyWith(
|
||||
PlansState value, $Res Function(PlansState) then) =
|
||||
_$PlansStateCopyWithImpl<$Res, PlansState>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$PlansStateCopyWithImpl<$Res, $Val extends PlansState>
|
||||
implements $PlansStateCopyWith<$Res> {
|
||||
_$PlansStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PlansStateImplCopyWith<$Res> {
|
||||
factory _$$PlansStateImplCopyWith(
|
||||
_$PlansStateImpl value, $Res Function(_$PlansStateImpl) then) =
|
||||
__$$PlansStateImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PlansStateImplCopyWithImpl<$Res>
|
||||
extends _$PlansStateCopyWithImpl<$Res, _$PlansStateImpl>
|
||||
implements _$$PlansStateImplCopyWith<$Res> {
|
||||
__$$PlansStateImplCopyWithImpl(
|
||||
_$PlansStateImpl _value, $Res Function(_$PlansStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PlansStateImpl implements _PlansState {
|
||||
const _$PlansStateImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlansState()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$PlansStateImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(PlanPaginationModel plansModel) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return $default();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return $default?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(PlanPaginationModel plansModel)? 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(_PlansState value) $default, {
|
||||
required TResult Function(PlansStateLoading value) loading,
|
||||
required TResult Function(PlansStateLoaded value) loaded,
|
||||
required TResult Function(PlansStateError value) error,
|
||||
}) {
|
||||
return $default(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_PlansState value)? $default, {
|
||||
TResult? Function(PlansStateLoading value)? loading,
|
||||
TResult? Function(PlansStateLoaded value)? loaded,
|
||||
TResult? Function(PlansStateError value)? error,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_PlansState value)? $default, {
|
||||
TResult Function(PlansStateLoading value)? loading,
|
||||
TResult Function(PlansStateLoaded value)? loaded,
|
||||
TResult Function(PlansStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _PlansState implements PlansState {
|
||||
const factory _PlansState() = _$PlansStateImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PlansStateLoadingImplCopyWith<$Res> {
|
||||
factory _$$PlansStateLoadingImplCopyWith(_$PlansStateLoadingImpl value,
|
||||
$Res Function(_$PlansStateLoadingImpl) then) =
|
||||
__$$PlansStateLoadingImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PlansStateLoadingImplCopyWithImpl<$Res>
|
||||
extends _$PlansStateCopyWithImpl<$Res, _$PlansStateLoadingImpl>
|
||||
implements _$$PlansStateLoadingImplCopyWith<$Res> {
|
||||
__$$PlansStateLoadingImplCopyWithImpl(_$PlansStateLoadingImpl _value,
|
||||
$Res Function(_$PlansStateLoadingImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PlansStateLoadingImpl implements PlansStateLoading {
|
||||
const _$PlansStateLoadingImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlansState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$PlansStateLoadingImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(PlanPaginationModel plansModel) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(PlanPaginationModel plansModel)? 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(_PlansState value) $default, {
|
||||
required TResult Function(PlansStateLoading value) loading,
|
||||
required TResult Function(PlansStateLoaded value) loaded,
|
||||
required TResult Function(PlansStateError value) error,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_PlansState value)? $default, {
|
||||
TResult? Function(PlansStateLoading value)? loading,
|
||||
TResult? Function(PlansStateLoaded value)? loaded,
|
||||
TResult? Function(PlansStateError value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_PlansState value)? $default, {
|
||||
TResult Function(PlansStateLoading value)? loading,
|
||||
TResult Function(PlansStateLoaded value)? loaded,
|
||||
TResult Function(PlansStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PlansStateLoading implements PlansState {
|
||||
const factory PlansStateLoading() = _$PlansStateLoadingImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PlansStateLoadedImplCopyWith<$Res> {
|
||||
factory _$$PlansStateLoadedImplCopyWith(_$PlansStateLoadedImpl value,
|
||||
$Res Function(_$PlansStateLoadedImpl) then) =
|
||||
__$$PlansStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({PlanPaginationModel plansModel});
|
||||
|
||||
$PlanPaginationModelCopyWith<$Res> get plansModel;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PlansStateLoadedImplCopyWithImpl<$Res>
|
||||
extends _$PlansStateCopyWithImpl<$Res, _$PlansStateLoadedImpl>
|
||||
implements _$$PlansStateLoadedImplCopyWith<$Res> {
|
||||
__$$PlansStateLoadedImplCopyWithImpl(_$PlansStateLoadedImpl _value,
|
||||
$Res Function(_$PlansStateLoadedImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? plansModel = null,
|
||||
}) {
|
||||
return _then(_$PlansStateLoadedImpl(
|
||||
plansModel: null == plansModel
|
||||
? _value.plansModel
|
||||
: plansModel // ignore: cast_nullable_to_non_nullable
|
||||
as PlanPaginationModel,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$PlanPaginationModelCopyWith<$Res> get plansModel {
|
||||
return $PlanPaginationModelCopyWith<$Res>(_value.plansModel, (value) {
|
||||
return _then(_value.copyWith(plansModel: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PlansStateLoadedImpl implements PlansStateLoaded {
|
||||
const _$PlansStateLoadedImpl({required this.plansModel});
|
||||
|
||||
@override
|
||||
final PlanPaginationModel plansModel;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlansState.loaded(plansModel: $plansModel)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PlansStateLoadedImpl &&
|
||||
(identical(other.plansModel, plansModel) ||
|
||||
other.plansModel == plansModel));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, plansModel);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$PlansStateLoadedImplCopyWith<_$PlansStateLoadedImpl> get copyWith =>
|
||||
__$$PlansStateLoadedImplCopyWithImpl<_$PlansStateLoadedImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(PlanPaginationModel plansModel) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loaded(plansModel);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loaded?.call(plansModel);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(PlanPaginationModel plansModel)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(plansModel);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_PlansState value) $default, {
|
||||
required TResult Function(PlansStateLoading value) loading,
|
||||
required TResult Function(PlansStateLoaded value) loaded,
|
||||
required TResult Function(PlansStateError value) error,
|
||||
}) {
|
||||
return loaded(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_PlansState value)? $default, {
|
||||
TResult? Function(PlansStateLoading value)? loading,
|
||||
TResult? Function(PlansStateLoaded value)? loaded,
|
||||
TResult? Function(PlansStateError value)? error,
|
||||
}) {
|
||||
return loaded?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_PlansState value)? $default, {
|
||||
TResult Function(PlansStateLoading value)? loading,
|
||||
TResult Function(PlansStateLoaded value)? loaded,
|
||||
TResult Function(PlansStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PlansStateLoaded implements PlansState {
|
||||
const factory PlansStateLoaded(
|
||||
{required final PlanPaginationModel plansModel}) = _$PlansStateLoadedImpl;
|
||||
|
||||
PlanPaginationModel get plansModel;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$PlansStateLoadedImplCopyWith<_$PlansStateLoadedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PlansStateErrorImplCopyWith<$Res> {
|
||||
factory _$$PlansStateErrorImplCopyWith(_$PlansStateErrorImpl value,
|
||||
$Res Function(_$PlansStateErrorImpl) then) =
|
||||
__$$PlansStateErrorImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PlansStateErrorImplCopyWithImpl<$Res>
|
||||
extends _$PlansStateCopyWithImpl<$Res, _$PlansStateErrorImpl>
|
||||
implements _$$PlansStateErrorImplCopyWith<$Res> {
|
||||
__$$PlansStateErrorImplCopyWithImpl(
|
||||
_$PlansStateErrorImpl _value, $Res Function(_$PlansStateErrorImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? errorMessage = null,
|
||||
}) {
|
||||
return _then(_$PlansStateErrorImpl(
|
||||
errorMessage: null == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PlansStateErrorImpl implements PlansStateError {
|
||||
const _$PlansStateErrorImpl({required this.errorMessage});
|
||||
|
||||
@override
|
||||
final String errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PlansState.error(errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PlansStateErrorImpl &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, errorMessage);
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$PlansStateErrorImplCopyWith<_$PlansStateErrorImpl> get copyWith =>
|
||||
__$$PlansStateErrorImplCopyWithImpl<_$PlansStateErrorImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(PlanPaginationModel plansModel) 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(PlanPaginationModel plansModel)? 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(PlanPaginationModel plansModel)? 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(_PlansState value) $default, {
|
||||
required TResult Function(PlansStateLoading value) loading,
|
||||
required TResult Function(PlansStateLoaded value) loaded,
|
||||
required TResult Function(PlansStateError value) error,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_PlansState value)? $default, {
|
||||
TResult? Function(PlansStateLoading value)? loading,
|
||||
TResult? Function(PlansStateLoaded value)? loaded,
|
||||
TResult? Function(PlansStateError value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_PlansState value)? $default, {
|
||||
TResult Function(PlansStateLoading value)? loading,
|
||||
TResult Function(PlansStateLoaded value)? loaded,
|
||||
TResult Function(PlansStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PlansStateError implements PlansState {
|
||||
const factory PlansStateError({required final String errorMessage}) =
|
||||
_$PlansStateErrorImpl;
|
||||
|
||||
String get errorMessage;
|
||||
|
||||
/// Create a copy of PlansState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$PlansStateErrorImplCopyWith<_$PlansStateErrorImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
11
lib/features/plans/presentation/cubit/about_plan_cubit.dart
Normal file
11
lib/features/plans/presentation/cubit/about_plan_cubit.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_state.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AboutPlanCubit extends Cubit<AboutPlanState> {
|
||||
AboutPlanCubit() : super(AboutPlanState.initial());
|
||||
|
||||
|
||||
Future<void> getPlan() async{
|
||||
|
||||
}
|
||||
}
|
||||
18
lib/features/plans/presentation/cubit/about_plan_state.dart
Normal file
18
lib/features/plans/presentation/cubit/about_plan_state.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'about_plan_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class AboutPlanState with _$AboutPlanState {
|
||||
|
||||
const factory AboutPlanState({
|
||||
required bool isLoading,
|
||||
required String? error,
|
||||
required PlanModel? planModel,
|
||||
}) = _AboutPlanState;
|
||||
|
||||
factory AboutPlanState.initial() => const AboutPlanState(isLoading: false, error: null, planModel: null);
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'about_plan_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AboutPlanState {
|
||||
bool get isLoading => throw _privateConstructorUsedError;
|
||||
String? get error => throw _privateConstructorUsedError;
|
||||
PlanModel? get planModel => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$AboutPlanStateCopyWith<AboutPlanState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $AboutPlanStateCopyWith<$Res> {
|
||||
factory $AboutPlanStateCopyWith(
|
||||
AboutPlanState value, $Res Function(AboutPlanState) then) =
|
||||
_$AboutPlanStateCopyWithImpl<$Res, AboutPlanState>;
|
||||
@useResult
|
||||
$Res call({bool isLoading, String? error, PlanModel? planModel});
|
||||
|
||||
$PlanModelCopyWith<$Res>? get planModel;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$AboutPlanStateCopyWithImpl<$Res, $Val extends AboutPlanState>
|
||||
implements $AboutPlanStateCopyWith<$Res> {
|
||||
_$AboutPlanStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? error = freezed,
|
||||
Object? planModel = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
error: freezed == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
planModel: freezed == planModel
|
||||
? _value.planModel
|
||||
: planModel // ignore: cast_nullable_to_non_nullable
|
||||
as PlanModel?,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$PlanModelCopyWith<$Res>? get planModel {
|
||||
if (_value.planModel == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $PlanModelCopyWith<$Res>(_value.planModel!, (value) {
|
||||
return _then(_value.copyWith(planModel: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AboutPlanStateImplCopyWith<$Res>
|
||||
implements $AboutPlanStateCopyWith<$Res> {
|
||||
factory _$$AboutPlanStateImplCopyWith(_$AboutPlanStateImpl value,
|
||||
$Res Function(_$AboutPlanStateImpl) then) =
|
||||
__$$AboutPlanStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({bool isLoading, String? error, PlanModel? planModel});
|
||||
|
||||
@override
|
||||
$PlanModelCopyWith<$Res>? get planModel;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AboutPlanStateImplCopyWithImpl<$Res>
|
||||
extends _$AboutPlanStateCopyWithImpl<$Res, _$AboutPlanStateImpl>
|
||||
implements _$$AboutPlanStateImplCopyWith<$Res> {
|
||||
__$$AboutPlanStateImplCopyWithImpl(
|
||||
_$AboutPlanStateImpl _value, $Res Function(_$AboutPlanStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? error = freezed,
|
||||
Object? planModel = freezed,
|
||||
}) {
|
||||
return _then(_$AboutPlanStateImpl(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
error: freezed == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
planModel: freezed == planModel
|
||||
? _value.planModel
|
||||
: planModel // ignore: cast_nullable_to_non_nullable
|
||||
as PlanModel?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AboutPlanStateImpl implements _AboutPlanState {
|
||||
const _$AboutPlanStateImpl(
|
||||
{required this.isLoading, required this.error, required this.planModel});
|
||||
|
||||
@override
|
||||
final bool isLoading;
|
||||
@override
|
||||
final String? error;
|
||||
@override
|
||||
final PlanModel? planModel;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutPlanState(isLoading: $isLoading, error: $error, planModel: $planModel)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AboutPlanStateImpl &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading) &&
|
||||
(identical(other.error, error) || other.error == error) &&
|
||||
(identical(other.planModel, planModel) ||
|
||||
other.planModel == planModel));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, isLoading, error, planModel);
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AboutPlanStateImplCopyWith<_$AboutPlanStateImpl> get copyWith =>
|
||||
__$$AboutPlanStateImplCopyWithImpl<_$AboutPlanStateImpl>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _AboutPlanState implements AboutPlanState {
|
||||
const factory _AboutPlanState(
|
||||
{required final bool isLoading,
|
||||
required final String? error,
|
||||
required final PlanModel? planModel}) = _$AboutPlanStateImpl;
|
||||
|
||||
@override
|
||||
bool get isLoading;
|
||||
@override
|
||||
String? get error;
|
||||
@override
|
||||
PlanModel? get planModel;
|
||||
|
||||
/// Create a copy of AboutPlanState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$AboutPlanStateImplCopyWith<_$AboutPlanStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AboutPlanScreen extends StatelessWidget {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/services/plans_service.dart';
|
||||
|
||||
class PlansRepository {
|
||||
final PlansService plansService;
|
||||
|
||||
const PlansRepository({required this.plansService});
|
||||
|
||||
Future<PlanPaginationModel> getPlans() async {
|
||||
try {
|
||||
return await plansService.getPlans();
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/plans/models/plan_pagination_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'plans_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class PlansService {
|
||||
factory PlansService(Dio dio, {String baseUrl}) = _PlansService;
|
||||
|
||||
@GET('/api/plans/index')
|
||||
Future<PlanPaginationModel> getPlans();
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'plans_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RetrofitGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _PlansService implements PlansService {
|
||||
_PlansService(
|
||||
this._dio, {
|
||||
this.baseUrl,
|
||||
this.errorLogger,
|
||||
});
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
String? baseUrl;
|
||||
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<PlanPaginationModel> getPlans() async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<PlanPaginationModel>(Options(
|
||||
method: 'GET',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/plans/index',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||
late PlanPaginationModel _value;
|
||||
try {
|
||||
_value = PlanPaginationModel.fromJson(_result.data!);
|
||||
} on Object catch (e, s) {
|
||||
errorLogger?.logError(e, s, _options);
|
||||
rethrow;
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
requestOptions.responseType == ResponseType.stream)) {
|
||||
if (T == String) {
|
||||
requestOptions.responseType = ResponseType.plain;
|
||||
} else {
|
||||
requestOptions.responseType = ResponseType.json;
|
||||
}
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
String _combineBaseUrls(
|
||||
String dioBaseUrl,
|
||||
String? baseUrl,
|
||||
) {
|
||||
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||
return dioBaseUrl;
|
||||
}
|
||||
|
||||
final url = Uri.parse(baseUrl);
|
||||
|
||||
if (url.isAbsolute) {
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
@@ -81,6 +82,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price":
|
||||
MessageLookupByLibrary.simpleMessage("Цена для покупателя"),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
@@ -101,6 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"eating_behavior":
|
||||
MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Элетронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты"),
|
||||
@@ -167,6 +171,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽"),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err":
|
||||
@@ -183,6 +189,17 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"no_account":
|
||||
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content":
|
||||
MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text":
|
||||
MessageLookupByLibrary.simpleMessage("На связи 7 дней в неделю"),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный"),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты"),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation":
|
||||
@@ -215,14 +232,18 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
|
||||
@@ -254,6 +275,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя"),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"),
|
||||
"your_favorite_sports":
|
||||
|
||||
@@ -1779,6 +1779,156 @@ class S {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Опция`
|
||||
String get option {
|
||||
return Intl.message(
|
||||
'Опция',
|
||||
name: 'option',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Оказание услуг`
|
||||
String get services {
|
||||
return Intl.message(
|
||||
'Оказание услуг',
|
||||
name: 'services',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Эконом`
|
||||
String get economy {
|
||||
return Intl.message(
|
||||
'Эконом',
|
||||
name: 'economy',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Стандарт`
|
||||
String get standard {
|
||||
return Intl.message(
|
||||
'Стандарт',
|
||||
name: 'standard',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Комфорт`
|
||||
String get comfort {
|
||||
return Intl.message(
|
||||
'Комфорт',
|
||||
name: 'comfort',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Заголовок опции`
|
||||
String get option_title {
|
||||
return Intl.message(
|
||||
'Заголовок опции',
|
||||
name: 'option_title',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Описание опции`
|
||||
String get option_desc {
|
||||
return Intl.message(
|
||||
'Описание опции',
|
||||
name: 'option_desc',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Этот план питания для похудения на 7 дней сбалансированный и разнообразный`
|
||||
String get option_desc_hint_text {
|
||||
return Intl.message(
|
||||
'Этот план питания для похудения на 7 дней сбалансированный и разнообразный',
|
||||
name: 'option_desc_hint_text',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Вы получите`
|
||||
String get you_will_get {
|
||||
return Intl.message(
|
||||
'Вы получите',
|
||||
name: 'you_will_get',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Цена для покупателя`
|
||||
String get customer_price {
|
||||
return Intl.message(
|
||||
'Цена для покупателя',
|
||||
name: 'customer_price',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Минимальная цена для покупателя: 1200₽`
|
||||
String get minimal_customer_price {
|
||||
return Intl.message(
|
||||
'Минимальная цена для покупателя: 1200₽',
|
||||
name: 'minimal_customer_price',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Разница в ценах, это комиссия Итвио`
|
||||
String get price_explanation {
|
||||
return Intl.message(
|
||||
'Разница в ценах, это комиссия Итвио',
|
||||
name: 'price_explanation',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Содержание опции`
|
||||
String get option_content {
|
||||
return Intl.message(
|
||||
'Содержание опции',
|
||||
name: 'option_content',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `На связи 7 дней в неделю`
|
||||
String get option_content_hint_text {
|
||||
return Intl.message(
|
||||
'На связи 7 дней в неделю',
|
||||
name: 'option_content_hint_text',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Опция подразумевает создание индивидуальной диеты`
|
||||
String get option_personal_diet_desc {
|
||||
return Intl.message(
|
||||
'Опция подразумевает создание индивидуальной диеты',
|
||||
name: 'option_personal_diet_desc',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
||||
@@ -171,6 +171,20 @@
|
||||
"plan_desc": "Описание плана",
|
||||
"plan_desc_example": "Большое подробное, привлекательное описание плана",
|
||||
"one_option": "1 опция",
|
||||
"three_options": "3 опции"
|
||||
|
||||
"three_options": "3 опции",
|
||||
"option": "Опция",
|
||||
"services": "Оказание услуг",
|
||||
"economy": "Эконом",
|
||||
"standard": "Стандарт",
|
||||
"comfort": "Комфорт",
|
||||
"option_title": "Заголовок опции",
|
||||
"option_desc": "Описание опции",
|
||||
"option_desc_hint_text": "Этот план питания для похудения на 7 дней сбалансированный и разнообразный",
|
||||
"you_will_get": "Вы получите",
|
||||
"customer_price": "Цена для покупателя",
|
||||
"minimal_customer_price": "Минимальная цена для покупателя: 1200₽",
|
||||
"price_explanation": "Разница в ценах, это комиссия Итвио",
|
||||
"option_content": "Содержание опции",
|
||||
"option_content_hint_text": "На связи 7 дней в неделю",
|
||||
"option_personal_diet_desc": "Опция подразумевает создание индивидуальной диеты"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user