my plans and my diets

This commit is contained in:
Username1548
2024-12-23 15:36:00 +07:00
parent 15a6ff44ef
commit 5ef1f3a660
52 changed files with 3857 additions and 573 deletions

View File

@@ -9,7 +9,7 @@ import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_sta
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class DietsCubit extends Cubit<DietsState> {
class DietsCubit extends Cubit<DietsState>{
final FeedRepository feedRepository;
final DietRepository dietsRepository;
int currentPage = 1;
@@ -52,6 +52,7 @@ class DietsCubit extends Cubit<DietsState> {
super.close();
}
void changeTypeFilter(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(typeIndex: index), errorMessage: null));
EasyDebounce.debounce(
@@ -63,6 +64,7 @@ class DietsCubit extends Cubit<DietsState> {
);
}
void changeSortingType(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(sortingIndex: index), errorMessage: null));
EasyDebounce.debounce(
@@ -74,6 +76,7 @@ class DietsCubit extends Cubit<DietsState> {
);
}
void changeDurationFilter(int index) {
emit(state.copyWith(filterState: state.filterState.copyWith(durationIndex: index), errorMessage: null));
EasyDebounce.debounce(
@@ -101,7 +104,11 @@ class DietsCubit extends Cubit<DietsState> {
);
lastPage = dietsPagination.meta.lastPage;
emit(
state.copyWith(dietsList: dietsPagination.data, isLoading: isLoading, errorMessage: null,),
state.copyWith(
dietsList: dietsPagination.data,
isLoading: isLoading,
errorMessage: null,
),
);
} catch (e) {
emit(

View File

@@ -1,4 +1,6 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:eatvio_app/core/widgets/add_item_button.dart';
import 'package:eatvio_app/core/widgets/custom_search_bar.dart';
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
import 'package:eatvio_app/features/create_plan/presentation/create_plan_screen.dart';
@@ -163,16 +165,63 @@ class _FeedScreenState extends State<FeedScreen> {
bottom: _chipGroup(),
title: Row(
children: [
_searchBar(),
CustomSearchBar(
searchController: searchController,
onChanged: (query) {
if (query.length > 2) {
EasyDebounce.debounce(
'searchFeed',
Duration(milliseconds: 500),
() {
switch (_selectedChipIndex) {
case 0:
feedCubit.loadFeedBlogPostList(query: query);
break;
case 1:
recipesCubit.loadRecipesList(query: query);
break;
case 2:
dietsCubit.loadDiets(query: query);
break;
case 3:
plansCubit.loadPlans(query: query);
break;
}
},
);
} else {
EasyDebounce.debounce(
'searchFeed',
Duration(milliseconds: 500),
() {
switch (_selectedChipIndex) {
case 0:
feedCubit.loadFeedBlogPostList();
break;
case 1:
recipesCubit.loadRecipesList();
break;
case 2:
dietsCubit.loadDiets();
break;
case 3:
plansCubit.loadPlans();
break;
}
},
);
}
},
),
SizedBox(width: 12),
switch (_selectedChipIndex) {
2 => _addItemButton(
2 => AddItemButton(
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null,
),
3 => _addItemButton(
3 => AddItemButton(
onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null,
),
_ => _addItemButton()
_ => AddItemButton()
},
],
),
@@ -181,21 +230,13 @@ class _FeedScreenState extends State<FeedScreen> {
),
];
},
body: Builder(
builder: (BuildContext context) {
if (_selectedChipIndex == 0) {
return _buildAllBlogPosts();
} else if (_selectedChipIndex == 1) {
return _buildAllRecipes();
} else if (_selectedChipIndex == 2) {
return _buildDiets();
} else if (_selectedChipIndex == 3) {
return _buildPlans();
} else {
return Center(child: Text(chipsLabelList[_selectedChipIndex]));
}
},
),
body: switch (_selectedChipIndex) {
0 => _buildAllBlogPosts(),
1 => _buildAllRecipes(),
2 => _buildDiets(),
3 => _buildPlans(),
_ => Center(child: Text(chipsLabelList[_selectedChipIndex])),
},
),
),
);
@@ -473,111 +514,4 @@ class _FeedScreenState extends State<FeedScreen> {
),
);
}
_addItemButton({void Function()? onTap}) {
return InkWell(
onTap: onTap ??
() {
GoRouter.of(context).pushNamed('blogPostCreateScreen');
},
borderRadius: BorderRadius.circular(64),
child: Ink(
decoration: BoxDecoration(
color: appTheme.blueA400,
shape: BoxShape.circle,
),
child: Icon(
Icons.add_rounded,
color: appTheme.gray100,
),
width: 40,
height: 40,
),
);
}
_searchBar() {
return SizedBox(
height: 40,
width: MediaQuery.of(context).size.width - 84,
child: TextFormField(
controller: searchController,
autofocus: false,
style: TextStyle(
fontSize: 12,
),
onChanged: (query) {
if (query.length > 2) {
EasyDebounce.debounce(
'searchFeed',
Duration(milliseconds: 500),
() {
switch (_selectedChipIndex) {
case 0:
feedCubit.loadFeedBlogPostList(query: query);
break;
case 1:
recipesCubit.loadRecipesList(query: query);
break;
case 2:
dietsCubit.loadDiets(query: query);
break;
case 3:
plansCubit.loadPlans(query: query);
break;
}
},
);
} else {
EasyDebounce.debounce(
'searchFeed',
Duration(milliseconds: 500),
() {
switch (_selectedChipIndex) {
case 0:
feedCubit.loadFeedBlogPostList();
break;
case 1:
recipesCubit.loadRecipesList();
break;
case 2:
dietsCubit.loadDiets(query: query == '' ? null : query);
break;
}
},
);
}
},
decoration: InputDecoration(
hintText: 'Поиск',
hintStyle: TextStyle(
fontSize: 12,
color: appTheme.gray600,
fontWeight: FontWeight.w400,
),
prefixIcon: Icon(
Icons.search,
color: appTheme.gray600,
size: 16,
),
isDense: false,
contentPadding: EdgeInsets.all(8),
fillColor: appTheme.gray100,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
),
),
);
}
}

View File

@@ -4,14 +4,16 @@ import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cub
import 'package:eatvio_app/features/feed/presentation/widgets/duration_choice_filter_widget.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/sorting_drop_down_filter.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/type_choice_filter_widget.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class DietFilterBottomSheet extends StatelessWidget {
const DietFilterBottomSheet({super.key, required this.dietsCubit});
final DietsCubit dietsCubit;
const DietFilterBottomSheet({super.key, this.dietsCubit, this.myDietsCubit});
final DietsCubit? dietsCubit;
final MyDietsCubit? myDietsCubit;
@override
Widget build(BuildContext context) {
final s = S.of(context);
@@ -32,7 +34,8 @@ class DietFilterBottomSheet extends StatelessWidget {
),
SizedBox(height: 12),
SortingDropDownFilter(
cubit: dietsCubit,
dietsCubit: dietsCubit,
myDietsCubit: myDietsCubit,
),
SizedBox(
height: 16,
@@ -50,6 +53,7 @@ class DietFilterBottomSheet extends StatelessWidget {
),
TypeChoiceFilterWidget(
dietsCubit: dietsCubit,
myDietsCubit: myDietsCubit,
),
SizedBox(
height: 16,
@@ -67,6 +71,7 @@ class DietFilterBottomSheet extends StatelessWidget {
),
DurationChoiceFilterWidget(
dietCubit: dietsCubit,
myDietsCubit: myDietsCubit,
),
SizedBox(
height: 24,

View File

@@ -1,7 +1,7 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
import 'package:eatvio_app/core/widgets/diet_info_row.dart';
import 'package:eatvio_app/core/widgets/info_row.dart';
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';

View File

@@ -5,14 +5,20 @@ import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_sta
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/features/feed/presentation/widgets/choice_chip_widget.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class DurationChoiceFilterWidget extends StatefulWidget {
const DurationChoiceFilterWidget({super.key, this.dietCubit, this.plansCubit});
const DurationChoiceFilterWidget({super.key, this.dietCubit, this.plansCubit, this.myDietsCubit, this.myPlansCubit});
final DietsCubit? dietCubit;
final PlansCubit? plansCubit;
final MyDietsCubit? myDietsCubit;
final MyPlansCubit? myPlansCubit;
@override
State<DurationChoiceFilterWidget> createState() => _DurationChoiceFilterWidgetState();
}
@@ -39,102 +45,102 @@ class _DurationChoiceFilterWidgetState extends State<DurationChoiceFilterWidget>
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.dietCubit?.changeDurationFilter(0);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.dietCubit?.changeDurationFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.dietCubit?.changeDurationFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.dietCubit?.changeDurationFilter(3);
},
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.dietCubit?.changeDurationFilter(index);
},
),
),
),
],
);
},
);
} else {
} else if (widget.plansCubit != null) {
return BlocBuilder<PlansCubit, PlansState>(
bloc: widget.plansCubit!,
bloc: widget.plansCubit,
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeDurationFilter(0);
},
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeDurationFilter(index);
},
),
),
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeDurationFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeDurationFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.durationIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeDurationFilter(3);
},
],
);
},
);
} else if (widget.myPlansCubit != null) {
return BlocBuilder<MyPlansCubit, MyPlansState>(
bloc: widget.myPlansCubit,
builder: (context, state) {
return Wrap(
children: [
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: switch (state.selectedStateIndex) {
1 => state.draftFilterState.durationIndex,
_ => state.activeFilterState.durationIndex
},
onSelected: (selectedValue) {
widget.myPlansCubit?.changeDurationFilter(index);
},
),
),
),
],
);
},
);
}
return BlocBuilder<MyDietsCubit, MyDietsState>(
bloc: widget.myDietsCubit,
builder: (context, state) {
return Wrap(
children: [
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: switch (state.selectedStateIndex) {
1 => state.draftFilterState.durationIndex,
2 => state.personalFilterState.durationIndex,
_ => state.activeFilterState.durationIndex
},
onSelected: (selectedValue) {
widget.myDietsCubit?.changeDurationFilter(index);
},
),
),
),
],
);
},
);
}
}

View File

@@ -1,13 +1,15 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
import 'package:eatvio_app/core/widgets/diet_info_row.dart';
import 'package:eatvio_app/core/widgets/info_row.dart';
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.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/feed/presentation/bloc/plans_cubit/plans_cubit.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_html/flutter_html.dart';
@@ -31,6 +33,7 @@ class PlanWidget extends StatefulWidget {
class _PlanWidgetState extends State<PlanWidget> {
@override
Widget build(BuildContext context) {
final s = S.of(context);
return DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
@@ -117,8 +120,61 @@ class _PlanWidgetState extends State<PlanWidget> {
],
],
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.only(left: 16, top: 12),
padding: const EdgeInsets.only(left: 16.0),
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: Container(
width: 46,
height: 46,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(widget.plan.author.authorProfileIcon),
fit: BoxFit.cover,
),
),
),
subtitle: Row(
children: [
InfoBouble(
radius: 12,
backgroundColor: appTheme.gray50,
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 10),
children: [
Text(
'${widget.plan.author.authorPlaceInRating}-й в рейтинге',
style: TextStyles.textXSSemibold.copyWith(
color: appTheme.blueA400,
),
),
],
),
Spacer(),
Text(
'${widget.plan.packetsCount == 1 ? widget.plan.packet1Options?.price : '${s.from} ${widget.plan.minPriceOfOptions.toStringAsFixed(0)}'}₽',
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.greenA700),
),
SizedBox(width: 16),
],
),
title: Padding(
padding: const EdgeInsets.only(bottom: 4.0),
child: Text(
widget.plan.author.authorName,
style: TextStyles.textSSemibold.copyWith(
color: appTheme.black,
),
),
),
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.only(
left: 16,
),
child: Row(
children: [
FeedIconButton(

View File

@@ -4,14 +4,16 @@ import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cub
import 'package:eatvio_app/features/feed/presentation/widgets/duration_choice_filter_widget.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/price_choice_filter_widget.dart';
import 'package:eatvio_app/features/feed/presentation/widgets/type_choice_filter_widget.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
class PlansFilterBottomSheet extends StatelessWidget {
const PlansFilterBottomSheet({super.key, required this.plansCubit});
final PlansCubit plansCubit;
const PlansFilterBottomSheet({super.key, this.plansCubit, this.myPlansCubit});
final PlansCubit? plansCubit;
final MyPlansCubit? myPlansCubit;
@override
Widget build(BuildContext context) {
final s = S.of(context);
@@ -30,7 +32,7 @@ class PlansFilterBottomSheet extends StatelessWidget {
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
),
SizedBox(height: 12),
PriceChoiceFilterWidget(plansCubit: plansCubit),
PriceChoiceFilterWidget(plansCubit: plansCubit, myPlansCubit: myPlansCubit,),
SizedBox(height: 16),
CustomDivider(),
SizedBox(
@@ -45,6 +47,7 @@ class PlansFilterBottomSheet extends StatelessWidget {
),
DurationChoiceFilterWidget(
plansCubit: plansCubit,
myPlansCubit: myPlansCubit,
),
SizedBox(
height: 16,
@@ -62,6 +65,7 @@ class PlansFilterBottomSheet extends StatelessWidget {
),
TypeChoiceFilterWidget(
plansCubit: plansCubit,
myPlansCubit: myPlansCubit,
),
SizedBox(
height: 24,

View File

@@ -3,12 +3,19 @@ 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/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/features/my_plans/presentation/cubit/my_plans_cubit.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class PriceChoiceFilterWidget extends StatefulWidget {
PriceChoiceFilterWidget({super.key, required this.plansCubit});
final PlansCubit plansCubit;
PriceChoiceFilterWidget({
super.key,
required this.plansCubit,
this.myPlansCubit,
});
final PlansCubit? plansCubit;
final MyPlansCubit? myPlansCubit;
@override
State<PriceChoiceFilterWidget> createState() => _PriceChoiceFilterWidgetState();
@@ -44,6 +51,164 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
@override
Widget build(BuildContext context) {
if (widget.myPlansCubit != null) {
return BlocBuilder<MyPlansCubit, MyPlansState>(
bloc: widget.myPlansCubit,
builder: (context, state) {
final minPlanPrice = switch (state.selectedStateIndex) {
1 => state.minDraftPlanPrice,
_ => state.minActivePlanPrice,
};
final maxPlanPrice = switch (state.selectedStateIndex) {
1 => state.maxDraftPlanPrice,
_ => state.maxActivePlanPrice,
};
final minPriceFilter = switch (state.selectedStateIndex) {
1 => state.draftFilterState.priceFilter.$1,
_ => state.activeFilterState.priceFilter.$1,
};
final maxPriceFilter = switch (state.selectedStateIndex) {
1 => state.draftFilterState.priceFilter.$2,
_ => state.activeFilterState.priceFilter.$2,
};
prevMinPrice ??= minPlanPrice;
prevMaxPrice ??= maxPlanPrice;
minPriceController.text = minPriceFilter?.toStringAsFixed(0) ?? '₽';
maxPriceController.text = maxPriceFilter?.toStringAsFixed(0) ?? '₽';
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Expanded(
child: CustomTextFormField(
keyboardType: TextInputType.number,
controller: minPriceController,
onChanged: (value) {
final price = int.tryParse(value.replaceAll('₽', ''));
if (price == null) {
EasyDebounce.cancel('changeMinPriceFilter');
minPriceController.value = TextEditingValue(
text: '₽',
selection: TextSelection.collapsed(offset: 0),
);
return;
}
if (price < minPlanPrice) {
minPriceController.value = TextEditingValue(
text: '${prevMinPrice ?? ''}₽',
selection: TextSelection.collapsed(offset: prevMinPrice.toString().length),
);
return;
}
if (price > (maxPriceFilter ?? maxPlanPrice)) {
minPriceController.value = TextEditingValue(
text: '${prevMinPrice ?? ''}₽',
selection: TextSelection.collapsed(offset: prevMinPrice.toString().length),
);
EasyDebounce.cancel('changeMinPriceFilter');
widget.myPlansCubit?.changePriceFilter(
prevMinPrice ?? minPlanPrice,
maxPriceFilter ?? maxPlanPrice,
);
return;
}
prevMinPrice = price;
EasyDebounce.debounce(
'changeMinPriceFilter',
Duration(seconds: 2),
() => widget.myPlansCubit?.changePriceFilter(
price,
maxPriceFilter ?? maxPlanPrice,
disableDebounce: true,
),
);
},
),
),
SizedBox(width: 8),
Expanded(
child: CustomTextFormField(
onChanged: (value) {
final price = int.tryParse(value.replaceAll('₽', ''));
if (price == null) {
EasyDebounce.cancel('changeMaxPriceFilter');
maxPriceController.value = TextEditingValue(
text: '₽',
selection: TextSelection.collapsed(offset: 0),
);
return;
}
if (price > maxPlanPrice) {
maxPriceController.value = TextEditingValue(
text: '${prevMaxPrice ?? ''}₽',
selection: TextSelection.collapsed(offset: prevMaxPrice.toString().length),
);
return;
}
if (price < (minPriceFilter ?? minPlanPrice)) {
maxPriceController.value = TextEditingValue(
text: '${prevMaxPrice ?? ''}₽',
selection: TextSelection.collapsed(offset: prevMaxPrice.toString().length),
);
EasyDebounce.cancel('changeMaxPriceFilter');
widget.myPlansCubit?.changePriceFilter(
minPriceFilter ?? minPlanPrice,
prevMaxPrice ?? maxPlanPrice,
);
return;
}
prevMaxPrice = price;
EasyDebounce.debounce(
'changeMaxPriceFilter',
Duration(seconds: 2),
() => widget.myPlansCubit?.changePriceFilter(
minPriceFilter ?? minPlanPrice,
price,
disableDebounce: true,
),
);
},
keyboardType: TextInputType.number,
controller: maxPriceController,
),
),
],
),
SizedBox(height: 12),
Theme(
data: Theme.of(context).copyWith(
sliderTheme: SliderThemeData(
overlayShape: SliderComponentShape.noOverlay,
),
),
child: RangeSlider(
activeColor: appTheme.blueA400,
inactiveColor: appTheme.blueA400,
min: minPlanPrice.toDouble(),
max: maxPlanPrice.toDouble(),
onChanged: (values) {
if (values.start <= values.end) {
widget.myPlansCubit?.changePriceFilter(values.start.toInt(), values.end.toInt());
}
},
values: RangeValues(
minPriceFilter?.toDouble() ?? minPlanPrice.toDouble(),
maxPriceFilter?.toDouble() ?? maxPlanPrice.toDouble(),
),
),
),
],
);
},
);
}
return BlocBuilder<PlansCubit, PlansState>(
bloc: widget.plansCubit,
builder: (context, state) {
@@ -84,7 +249,7 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
selection: TextSelection.collapsed(offset: prevMinPrice.toString().length),
);
EasyDebounce.cancel('changeMinPriceFilter');
widget.plansCubit.changePriceFilter(
widget.plansCubit?.changePriceFilter(
prevMinPrice ?? state.minPlanPrice,
state.filterState.priceFilter.$2 ?? state.maxPlanPrice,
);
@@ -94,7 +259,7 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
EasyDebounce.debounce(
'changeMinPriceFilter',
Duration(seconds: 2),
() => widget.plansCubit.changePriceFilter(
() => widget.plansCubit?.changePriceFilter(
price,
state.filterState.priceFilter.$2 ?? state.maxPlanPrice,
disableDebounce: true,
@@ -129,7 +294,7 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
selection: TextSelection.collapsed(offset: prevMaxPrice.toString().length),
);
EasyDebounce.cancel('changeMaxPriceFilter');
widget.plansCubit.changePriceFilter(
widget.plansCubit?.changePriceFilter(
state.filterState.priceFilter.$1 ?? state.minPlanPrice,
prevMaxPrice ?? state.maxPlanPrice,
);
@@ -139,7 +304,7 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
EasyDebounce.debounce(
'changeMaxPriceFilter',
Duration(seconds: 2),
() => widget.plansCubit.changePriceFilter(
() => widget.plansCubit?.changePriceFilter(
state.filterState.priceFilter.$1 ?? state.minPlanPrice,
price,
disableDebounce: true,
@@ -166,7 +331,7 @@ class _PriceChoiceFilterWidgetState extends State<PriceChoiceFilterWidget> {
max: state.maxPlanPrice.toDouble(),
onChanged: (values) {
if (values.start <= values.end) {
widget.plansCubit.changePriceFilter(values.start.toInt(), values.end.toInt());
widget.plansCubit?.changePriceFilter(values.start.toInt(), values.end.toInt());
}
},
values: RangeValues(

View File

@@ -2,6 +2,8 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:flutter/material.dart';
@@ -9,8 +11,9 @@ import 'package:collection/collection.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SortingDropDownFilter extends StatefulWidget {
const SortingDropDownFilter({super.key, required this.cubit});
final DietsCubit cubit;
const SortingDropDownFilter({super.key, this.dietsCubit, this.myDietsCubit});
final DietsCubit? dietsCubit;
final MyDietsCubit? myDietsCubit;
@override
State<SortingDropDownFilter> createState() => _SortingDropDownFilterState();
}
@@ -33,9 +36,40 @@ class _SortingDropDownFilterState extends State<SortingDropDownFilter> {
@override
Widget build(BuildContext context) {
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.cubit,
if (widget.dietsCubit != null) {
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.dietsCubit!,
builder: (context, state) {
return CustomDropDownButton(
items: sortingTypes
.mapIndexed(
(index, value) => DropdownMenuItem(
child: Text(
sortingTypes[index],
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
),
value: sortingTypes[index],
),
)
.toList(),
value: sortingTypes[state.filterState.sortingIndex],
onChanged: (value) {
if (value != null) {
widget.dietsCubit!.changeSortingType(sortingTypes.indexOf(value));
}
},
);
},
);
}
return BlocBuilder<MyDietsCubit, MyDietsState>(
bloc: widget.myDietsCubit!,
builder: (context, state) {
final sortingIndex = switch (state.selectedStateIndex) {
1 => state.draftFilterState.sortingIndex,
2 => state.personalFilterState.sortingIndex,
_ => state.activeFilterState.sortingIndex
};
return CustomDropDownButton(
items: sortingTypes
.mapIndexed(
@@ -48,10 +82,10 @@ class _SortingDropDownFilterState extends State<SortingDropDownFilter> {
),
)
.toList(),
value: sortingTypes[state.filterState.sortingIndex],
value: sortingTypes[sortingIndex],
onChanged: (value) {
if (value != null) {
widget.cubit.changeSortingType(sortingTypes.indexOf(value));
widget.myDietsCubit!.changeSortingType(sortingTypes.indexOf(value));
}
},
);

View File

@@ -3,6 +3,10 @@ import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_sta
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/features/feed/presentation/widgets/choice_chip_widget.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_state.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -12,9 +16,13 @@ class TypeChoiceFilterWidget extends StatefulWidget {
super.key,
this.dietsCubit,
this.plansCubit,
this.myDietsCubit,
this.myPlansCubit,
});
final DietsCubit? dietsCubit;
final PlansCubit? plansCubit;
final MyDietsCubit? myDietsCubit;
final MyPlansCubit? myPlansCubit;
@override
State<TypeChoiceFilterWidget> createState() => _TypeChoiceFilterWidgetState();
}
@@ -25,7 +33,7 @@ class _TypeChoiceFilterWidgetState extends State<TypeChoiceFilterWidget> {
void didChangeDependencies() {
final s = S.of(context);
super.didChangeDependencies();
if (widget.dietsCubit != null) {
if (widget.dietsCubit != null || widget.myDietsCubit != null) {
if (chipsLabelList.isEmpty) {
chipsLabelList.add(s.all);
chipsLabelList.add(s.vegan_type);
@@ -52,124 +60,102 @@ class _TypeChoiceFilterWidgetState extends State<TypeChoiceFilterWidget> {
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(0);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(3);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 4,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(4);
},
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8.0 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.plansCubit?.changeTypeFilter(index);
},
),
),
),
],
);
},
);
} else {
} else if (widget.dietsCubit != null) {
return BlocBuilder<DietsCubit, DietsState>(
bloc: widget.dietsCubit,
builder: (context, state) {
return Wrap(
children: [
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 0,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(0);
},
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8.0 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(index);
},
),
),
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 1,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(1);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 2,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(2);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 3,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(3);
},
),
SizedBox(
width: 8,
),
ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: 4,
selectedChipIndex: state.filterState.typeIndex,
onSelected: (selectedValue) {
widget.dietsCubit?.changeTypeFilter(4);
},
],
);
},
);
} else if (widget.myPlansCubit != null) {
return BlocBuilder<MyPlansCubit, MyPlansState>(
bloc: widget.myPlansCubit,
builder: (context, state) {
return Wrap(
children: [
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8.0 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: switch (state.selectedStateIndex) {
1 => state.draftFilterState.typeIndex,
_ => state.activeFilterState.typeIndex
},
onSelected: (selectedValue) {
widget.myPlansCubit?.changeTypeFilter(index);
},
),
),
),
],
);
},
);
}
return BlocBuilder<MyDietsCubit, MyDietsState>(
bloc: widget.myDietsCubit,
builder: (context, state) {
return Wrap(
children: [
...List.generate(
chipsLabelList.length,
(index) => Padding(
padding: EdgeInsets.only(right: index != chipsLabelList.length - 1 ? 8.0 : 0),
child: ChoiceChipWidget(
chipsLabelList: chipsLabelList,
index: index,
selectedChipIndex: switch (state.selectedStateIndex) {
1 => state.draftFilterState.typeIndex,
2 => state.personalFilterState.typeIndex,
_ => state.activeFilterState.typeIndex
},
onSelected: (selectedValue) {
widget.myDietsCubit?.changeTypeFilter(index);
},
),
),
),
],
);
},
);
}
}