From dd7a8b26eb4941e43046cca5250955962250c3e2 Mon Sep 17 00:00:00 2001 From: Herwig Birke Date: Tue, 12 Mar 2024 12:43:13 +0100 Subject: [PATCH] providers final --- lib/providers/filters_provider.dart | 37 ++++- lib/screens/filters.dart | 224 +++++++++++----------------- lib/screens/meal_details.dart | 26 ++-- lib/screens/tabs.dart | 19 +-- 4 files changed, 136 insertions(+), 170 deletions(-) diff --git a/lib/providers/filters_provider.dart b/lib/providers/filters_provider.dart index fec8efe..ef0f528 100644 --- a/lib/providers/filters_provider.dart +++ b/lib/providers/filters_provider.dart @@ -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> { 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 chosenFilters) { state = chosenFilters; @@ -29,5 +30,27 @@ class FiltersNotifier extends StateNotifier> { } final filtersProvider = -StateNotifierProvider>( - (ref) => FiltersNotifier()); + StateNotifierProvider>( + (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(); +}); \ No newline at end of file diff --git a/lib/screens/filters.dart b/lib/screens/filters.dart index eda4c00..86d6c83 100644 --- a/lib/screens/filters.dart +++ b/lib/screens/filters.dart @@ -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 createState() { - return _FiltersScreenState(); - } -} + Widget build(BuildContext context, WidgetRef ref) { + final activeFilters = ref.watch(filtersProvider); -class _FiltersScreenState extends ConsumerState { - 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), + ), + ], ), ); } diff --git a/lib/screens/meal_details.dart b/lib/screens/meal_details.dart index 1a4b50b..8a544ed 100644 --- a/lib/screens/meal_details.dart +++ b/lib/screens/meal_details.dart @@ -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, + ), ), ), ], diff --git a/lib/screens/tabs.dart b/lib/screens/tabs.dart index ec22b8d..be88158 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -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 { @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,