providers final
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter_meals/providers/meals_provider.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
enum Filter {
|
||||
@@ -10,11 +11,11 @@ enum Filter {
|
||||
class FiltersNotifier extends StateNotifier<Map<Filter, bool>> {
|
||||
FiltersNotifier()
|
||||
: super({
|
||||
Filter.glutenFree: false,
|
||||
Filter.lactoseFree: false,
|
||||
Filter.vegetarian: false,
|
||||
Filter.vegan: false
|
||||
});
|
||||
Filter.glutenFree: false,
|
||||
Filter.lactoseFree: false,
|
||||
Filter.vegetarian: false,
|
||||
Filter.vegan: false
|
||||
});
|
||||
|
||||
void setFilters(Map<Filter, bool> chosenFilters) {
|
||||
state = chosenFilters;
|
||||
@@ -29,5 +30,27 @@ class FiltersNotifier extends StateNotifier<Map<Filter, bool>> {
|
||||
}
|
||||
|
||||
final filtersProvider =
|
||||
StateNotifierProvider<FiltersNotifier, Map<Filter, bool>>(
|
||||
(ref) => FiltersNotifier());
|
||||
StateNotifierProvider<FiltersNotifier, Map<Filter, bool>>(
|
||||
(ref) => FiltersNotifier(),
|
||||
);
|
||||
|
||||
final filteredMealsProvider = Provider((ref) {
|
||||
final meals = ref.watch(mealsProvider);
|
||||
final activeFilters = ref.watch(filtersProvider);
|
||||
|
||||
return meals.where((meal) {
|
||||
if (activeFilters[Filter.glutenFree]! && !meal.isGlutenFree) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.lactoseFree]! && !meal.isLactoseFree) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.vegetarian]! && !meal.isVegetarian) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.vegan]! && !meal.isVegan) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).toList();
|
||||
});
|
||||
+90
-134
@@ -6,152 +6,108 @@ import 'package:flutter_meals/providers/filters_provider.dart';
|
||||
// import 'package:flutter_meals/screens/tabs.dart';
|
||||
// import 'package:flutter_meals/widgets/main_drawer.dart';
|
||||
|
||||
class FiltersScreen extends ConsumerStatefulWidget {
|
||||
class FiltersScreen extends ConsumerWidget {
|
||||
const FiltersScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<FiltersScreen> createState() {
|
||||
return _FiltersScreenState();
|
||||
}
|
||||
}
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final activeFilters = ref.watch(filtersProvider);
|
||||
|
||||
class _FiltersScreenState extends ConsumerState<FiltersScreen> {
|
||||
var _glutenFreeFilterSet = false;
|
||||
var _lactoseFreeFilterSet = false;
|
||||
var _vegetarianFilterSet = false;
|
||||
var _veganFilterSet = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final activeFilters = ref.read(filtersProvider);
|
||||
|
||||
_glutenFreeFilterSet = activeFilters[Filter.glutenFree]!;
|
||||
_lactoseFreeFilterSet = activeFilters[Filter.lactoseFree]!;
|
||||
_vegetarianFilterSet = activeFilters[Filter.vegetarian]!;
|
||||
_veganFilterSet = activeFilters[Filter.vegan]!;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Your Filters'),
|
||||
),
|
||||
// drawer: MainDrawer(
|
||||
// onSelectScreen: (identifier) {
|
||||
// Navigator.of(context).pop();
|
||||
// if (identifier == 'meals') {
|
||||
// Navigator.of(context).pushReplacement(
|
||||
// MaterialPageRoute(
|
||||
// builder: (ctx) => const TabsScreen(),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
body: WillPopScope(
|
||||
onWillPop: () async {
|
||||
ref.read(filtersProvider.notifier).setFilters({
|
||||
Filter.glutenFree: _glutenFreeFilterSet,
|
||||
Filter.lactoseFree: _lactoseFreeFilterSet,
|
||||
Filter.vegetarian: _vegetarianFilterSet,
|
||||
Filter.vegan: _veganFilterSet,
|
||||
});
|
||||
return true;
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
value: _glutenFreeFilterSet,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
_glutenFreeFilterSet = isChecked;
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
'Gluten-free',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include gluten-free meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
body: Column(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
value: activeFilters[Filter.glutenFree]!,
|
||||
onChanged: (isChecked) {
|
||||
ref
|
||||
.read(filtersProvider.notifier)
|
||||
.setFilter(Filter.glutenFree, isChecked);
|
||||
},
|
||||
title: Text(
|
||||
'Gluten-free',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: _lactoseFreeFilterSet,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
_lactoseFreeFilterSet = isChecked;
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
'Lactose-free',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include lactose-free meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
subtitle: Text(
|
||||
'Only include gluten-free meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: _vegetarianFilterSet,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
_vegetarianFilterSet = isChecked;
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
'Vegetarian',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include vegetarian meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: activeFilters[Filter.lactoseFree]!,
|
||||
onChanged: (isChecked) {
|
||||
ref
|
||||
.read(filtersProvider.notifier)
|
||||
.setFilter(Filter.lactoseFree, isChecked);
|
||||
},
|
||||
title: Text(
|
||||
'Lactose-free',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: _veganFilterSet,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
_veganFilterSet = isChecked;
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
'Vegan',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include vegan meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
subtitle: Text(
|
||||
'Only include lactose-free meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: activeFilters[Filter.vegetarian]!,
|
||||
onChanged: (isChecked) {
|
||||
ref
|
||||
.read(filtersProvider.notifier)
|
||||
.setFilter(Filter.vegetarian, isChecked);
|
||||
},
|
||||
title: Text(
|
||||
'Vegetarian',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include vegetarian meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: activeFilters[Filter.vegan]!,
|
||||
onChanged: (isChecked) {
|
||||
ref
|
||||
.read(filtersProvider.notifier)
|
||||
.setFilter(Filter.vegan, isChecked);
|
||||
},
|
||||
title: Text(
|
||||
'Vegan',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Only include vegan meals.',
|
||||
style: Theme.of(context).textTheme.labelMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
activeColor: Theme.of(context).colorScheme.tertiary,
|
||||
contentPadding: const EdgeInsets.only(left: 34, right: 22),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ class MealDetailsScreen extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final favoriteMeals = ref.watch(favoriteMealsProvider);
|
||||
|
||||
final isFavorite = favoriteMeals.contains(meal);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(meal.title), actions: [
|
||||
IconButton(
|
||||
@@ -29,7 +33,7 @@ class MealDetailsScreen extends ConsumerWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.star),
|
||||
icon: Icon(isFavorite ? Icons.star : Icons.star_border),
|
||||
)
|
||||
]),
|
||||
body: SingleChildScrollView(
|
||||
@@ -45,25 +49,25 @@ class MealDetailsScreen extends ConsumerWidget {
|
||||
Text(
|
||||
'Ingredients',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
for (final ingredient in meal.ingredients)
|
||||
Text(
|
||||
ingredient,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
'Steps',
|
||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
for (final step in meal.steps)
|
||||
@@ -76,8 +80,8 @@ class MealDetailsScreen extends ConsumerWidget {
|
||||
step,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
+1
-18
@@ -5,7 +5,6 @@ import 'package:flutter_meals/screens/categories.dart';
|
||||
import 'package:flutter_meals/screens/filters.dart';
|
||||
import 'package:flutter_meals/screens/meals.dart';
|
||||
import 'package:flutter_meals/widgets/main_drawer.dart';
|
||||
import 'package:flutter_meals/providers/meals_provider.dart';
|
||||
import 'package:flutter_meals/providers/favorites_provider.dart';
|
||||
import 'package:flutter_meals/providers/filters_provider.dart';
|
||||
|
||||
@@ -47,23 +46,7 @@ class _TabsScreenState extends ConsumerState<TabsScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final meals = ref.watch(mealsProvider);
|
||||
final activeFilters = ref.watch(filtersProvider);
|
||||
final availableMeals = meals.where((meal) {
|
||||
if (activeFilters[Filter.glutenFree]! && !meal.isGlutenFree) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.lactoseFree]! && !meal.isLactoseFree) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.vegetarian]! && !meal.isVegetarian) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilters[Filter.vegan]! && !meal.isVegan) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).toList();
|
||||
final availableMeals = ref.watch(filteredMealsProvider);
|
||||
|
||||
Widget activePage = CategoriesScreen(
|
||||
availableMeals: availableMeals,
|
||||
|
||||
Reference in New Issue
Block a user