From bbac96686e93ae8d097fa7f529878bed53f23d3d Mon Sep 17 00:00:00 2001 From: Alysson Date: Wed, 3 May 2023 18:56:10 +0200 Subject: [PATCH] feat(): multiscreen navigation --- lib/screens/CategoriesScreen.dart | 13 ++- lib/screens/filters.dart | 134 ++++++++++++++++++++++++++++++ lib/screens/tabs.dart | 47 +++++++++++ lib/widgets/main_drawer.dart | 80 ++++++++++++++++++ 4 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 lib/screens/filters.dart create mode 100644 lib/widgets/main_drawer.dart diff --git a/lib/screens/CategoriesScreen.dart b/lib/screens/CategoriesScreen.dart index 8340841..0cb25ce 100644 --- a/lib/screens/CategoriesScreen.dart +++ b/lib/screens/CategoriesScreen.dart @@ -6,12 +6,15 @@ import 'package:meals/screens/MealsScreen.dart'; import 'package:meals/widgets/CategoryGridItem.dart'; class CategoriesScreen extends StatelessWidget { + final List availableMeals; final void Function(Meal meal) onToggleFavorite; - const CategoriesScreen({super.key, required this.onToggleFavorite}); + const CategoriesScreen({super.key, + required this.availableMeals, + required this.onToggleFavorite}); void _selectCategory(BuildContext context, Category category) { - final meals = dummyMeals + final meals = availableMeals .where((Meal meal) => meal.categories.contains(category.id)) .toList(); @@ -19,9 +22,11 @@ class CategoriesScreen extends StatelessWidget { context, MaterialPageRoute( builder: (ctx) => - MealsScreen(title: category.title, + MealsScreen( + title: category.title, meals: meals, - onToggleFavorite: onToggleFavorite,))); + onToggleFavorite: onToggleFavorite, + ))); } @override diff --git a/lib/screens/filters.dart b/lib/screens/filters.dart new file mode 100644 index 0000000..83628c1 --- /dev/null +++ b/lib/screens/filters.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:meals/screens/tabs.dart'; +import 'package:meals/widgets/main_drawer.dart'; + +enum Filter { + glutenFree, + lactoseFree, + veggie, + vegan, +} + +class FiltersScreen extends StatefulWidget { + final Map currentFilters; + + const FiltersScreen({Key? key, required this.currentFilters}) + : super(key: key); + + @override + State createState() => _FiltersScreenState(); +} + +class _FiltersScreenState extends State { + bool _glutenFreeFilterSet = false; + bool _lactoseFreeFilterSet = false; + bool _veggieFilterSet = false; + bool _veganFilterSet = false; + + @override + void initState() { + super.initState(); + setState(() { + _glutenFreeFilterSet = widget.currentFilters[Filter.glutenFree]!; + _lactoseFreeFilterSet = widget.currentFilters[Filter.lactoseFree]!; + _veggieFilterSet = widget.currentFilters[Filter.veggie]!; + _veganFilterSet = widget.currentFilters[Filter.vegan]!; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Your filters'), + ), + body: WillPopScope( + onWillPop: () async { + Navigator.of(context).pop({ + Filter.glutenFree: _glutenFreeFilterSet, + Filter.lactoseFree: _lactoseFreeFilterSet, + Filter.veggie: _veggieFilterSet, + Filter.vegan: _veganFilterSet, + }); + + return false; + }, + child: Column( + children: [ + SwitchListTile( + value: _glutenFreeFilterSet, + onChanged: (checked) => setState(() { + _glutenFreeFilterSet = checked; + }), + title: Text( + 'Gluten free', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onBackground), + ), + subtitle: Text( + 'Only includes 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), + ), + SwitchListTile( + value: _lactoseFreeFilterSet, + onChanged: (checked) => setState(() { + _lactoseFreeFilterSet = checked; + }), + title: Text( + 'Lactose free', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onBackground), + ), + subtitle: Text( + 'Only includes 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: _veggieFilterSet, + onChanged: (checked) => setState(() { + _veggieFilterSet = checked; + }), + title: Text( + 'Veggie', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onBackground), + ), + subtitle: Text( + 'Only includes veggie 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: _veganFilterSet, + onChanged: (checked) => setState(() { + _veganFilterSet = checked; + }), + title: Text( + 'Vegan', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onBackground), + ), + subtitle: Text( + 'Only includes 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/tabs.dart b/lib/screens/tabs.dart index bf21a2c..b43008b 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -1,9 +1,19 @@ import 'package:flutter/material.dart'; +import 'package:meals/data/dummy_categories.dart'; import 'package:meals/screens/CategoriesScreen.dart'; import 'package:meals/screens/MealsScreen.dart'; +import 'package:meals/screens/filters.dart'; +import 'package:meals/widgets/main_drawer.dart'; import '../models/Meal.dart'; +const kDefaultFilters = { + Filter.glutenFree: false, + Filter.lactoseFree: false, + Filter.veggie: false, + Filter.vegan: false, +}; + class TabsScreen extends StatefulWidget { const TabsScreen({Key? key}) : super(key: key); @@ -14,6 +24,7 @@ class TabsScreen extends StatefulWidget { class _TabsScreenState extends State { int _selectedPageIndex = 0; final List _favoriteMeals = []; + Map _selectedFilters = kDefaultFilters; void _showInfoMessage(String message) { ScaffoldMessenger.of(context).clearSnackBars(); @@ -41,10 +52,42 @@ class _TabsScreenState extends State { } } + void _setScreen(String identifier) async { + Navigator.of(context).pop(); + + switch (identifier) { + case 'filters': + final results = await Navigator.of(context) + .push>(MaterialPageRoute( + builder: (ctx) => FiltersScreen( + currentFilters: _selectedFilters, + ))); + setState(() { + _selectedFilters = results ?? kDefaultFilters; + }); + break; + } + } + @override Widget build(BuildContext context) { Widget activePage; String? activePageTitle; + final availableMeals = dummyMeals.where((meal) { + if (_selectedFilters[Filter.glutenFree]! && !meal.isGlutenFree) { + return false; + } + if (_selectedFilters[Filter.lactoseFree]! && !meal.isLactoseFree) { + return false; + } + if (_selectedFilters[Filter.veggie]! && !meal.isVegetarian) { + return false; + } + if (_selectedFilters[Filter.vegan]! && !meal.isVegan) { + return false; + } + return true; + }).toList(); switch (_selectedPageIndex) { case 1: @@ -57,12 +100,16 @@ class _TabsScreenState extends State { default: activePageTitle = 'Pick your category'; activePage = CategoriesScreen( + availableMeals: availableMeals, onToggleFavorite: _toggleFavoriteMeal, ); } return Scaffold( appBar: AppBar(title: Text(activePageTitle)), + drawer: MainDrawer( + onSelectScreen: _setScreen, + ), body: activePage, bottomNavigationBar: BottomNavigationBar( onTap: _selectPage, diff --git a/lib/widgets/main_drawer.dart b/lib/widgets/main_drawer.dart new file mode 100644 index 0000000..fb02d57 --- /dev/null +++ b/lib/widgets/main_drawer.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; + +class MainDrawer extends StatelessWidget { + final Function(String identifier) onSelectScreen; + + const MainDrawer({Key? key, required this.onSelectScreen}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Drawer( + child: Column( + children: [ + DrawerHeader( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Theme.of(context).colorScheme.primaryContainer, + Theme.of(context) + .colorScheme + .primaryContainer + .withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + child: Row( + children: [ + Icon( + Icons.fastfood, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox( + width: 18, + ), + Text( + 'Cooking up!', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.primary, + ), + ), + ], + ), + ), + ListTile( + leading: Icon( + Icons.restaurant, + size: 26, + color: Theme.of(context).colorScheme.onBackground, + ), + title: Text('Meals', + style: Theme.of(context).textTheme.titleSmall!.copyWith( + color: Colors.white, + fontSize: 24, + )), + onTap: () { + onSelectScreen('meals'); + }, + ), + ListTile( + leading: Icon( + Icons.settings, + size: 26, + color: Theme.of(context).colorScheme.onBackground, + ), + title: Text('Filters', + style: Theme.of(context).textTheme.titleSmall!.copyWith( + color: Colors.white, + fontSize: 24, + )), + onTap: () { + onSelectScreen('filters'); + }, + ) + ], + ), + ); + } +}