added plan pagination and updated plans creation screen

This commit is contained in:
Username1548
2024-12-04 22:03:31 +07:00
parent 4a57c72297
commit bc0b3829c9
50 changed files with 1504 additions and 959 deletions

View File

@@ -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(),
};
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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),
),
);
}

View File

@@ -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,

View File

@@ -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,
);
}

View File

@@ -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')

View File

@@ -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,

View File

@@ -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,

View File

@@ -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(),
),
);
},
),
],
),

View File

@@ -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(

View File

@@ -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()],
),
),
);
}

View File

@@ -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),
),
),
],
],
);
}
}

View File

@@ -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),
),
);
}
}

View File

@@ -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,
),

View File

@@ -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,
),
),
),
);
}
}

View File

@@ -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> {

View File

@@ -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';

View File

@@ -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';

View File

@@ -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

View File

@@ -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()));
}
}
}
}

View File

@@ -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,
);
}

View File

@@ -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;
}

View File

@@ -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,
);
},
),
),

View File

@@ -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';

View File

@@ -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 {

View File

@@ -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,
});
});
}

View File

@@ -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>{};

View File

@@ -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()));
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View 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{
}
}

View 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);
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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;
}
}
}

View File

@@ -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();
}

View File

@@ -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();
}
}