feat(): multiscreen navigation

feat/state-management
Alysson H. 2 years ago
parent ae62d4b7a8
commit bbac96686e

@ -6,12 +6,15 @@ import 'package:meals/screens/MealsScreen.dart';
import 'package:meals/widgets/CategoryGridItem.dart';
class CategoriesScreen extends StatelessWidget {
final List<Meal> 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

@ -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<Filter, bool> currentFilters;
const FiltersScreen({Key? key, required this.currentFilters})
: super(key: key);
@override
State<FiltersScreen> createState() => _FiltersScreenState();
}
class _FiltersScreenState extends State<FiltersScreen> {
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),
)
],
),
));
}
}

@ -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<TabsScreen> {
int _selectedPageIndex = 0;
final List<Meal> _favoriteMeals = [];
Map<Filter, bool> _selectedFilters = kDefaultFilters;
void _showInfoMessage(String message) {
ScaffoldMessenger.of(context).clearSnackBars();
@ -41,10 +52,42 @@ class _TabsScreenState extends State<TabsScreen> {
}
}
void _setScreen(String identifier) async {
Navigator.of(context).pop();
switch (identifier) {
case 'filters':
final results = await Navigator.of(context)
.push<Map<Filter, bool>>(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<TabsScreen> {
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,

@ -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');
},
)
],
),
);
}
}
Loading…
Cancel
Save