From af0be6fe8b1c8353feb6bdde4c1769127626f549 Mon Sep 17 00:00:00 2001 From: broodjeaap89 Date: Sun, 5 Sep 2021 13:35:56 +0200 Subject: [PATCH] moved to a wrapped scaffold, to get some consistency and one place to add the nav drawer --- lib/pages/add_pizza_event_page.dart | 319 +++++++++---------- lib/pages/add_recipe_page.dart | 189 ++++++----- lib/pages/pick_pizza_recipe_page.dart | 56 ++-- lib/pages/pizza_event_notification_page.dart | 177 +++++----- lib/pages/pizza_event_page.dart | 89 +++--- lib/pages/pizza_events_page.dart | 68 ++-- lib/pages/recipe_page.dart | 60 ++-- lib/pages/recipe_step_instruction_page.dart | 64 ++-- lib/pages/recipes_page.dart | 96 +++--- lib/pages/scaffold.dart | 39 +++ 10 files changed, 577 insertions(+), 580 deletions(-) create mode 100644 lib/pages/scaffold.dart diff --git a/lib/pages/add_pizza_event_page.dart b/lib/pages/add_pizza_event_page.dart index bfa1dfa..5e40e0b 100644 --- a/lib/pages/add_pizza_event_page.dart +++ b/lib/pages/add_pizza_event_page.dart @@ -7,6 +7,7 @@ import 'package:fluttericon/font_awesome5_icons.dart'; import 'package:pizzaplanner/entities/pizza_event.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart'; import 'package:pizzaplanner/main.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:pizzaplanner/util.dart'; import 'package:hive/hive.dart'; @@ -31,178 +32,172 @@ class AddPizzaEventPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text("Add Pizza Event"), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Expanded( - flex: 40, - child: Column( - children: [ - Row( - children: [ - const Icon(Icons.title), - Container(width: 25), - Expanded( - child: TextField( - decoration: InputDecoration( - hintText: "Event Name", - errorText: nameValidation ? """Name can't be empty""" : null - ), - onChanged: (String newName) { - setState(() { - name = newName; - }); - }, - ), - ) - ] - ), - Row( - children: [ - const Icon(FontAwesome5.hashtag), - Expanded( - child: Slider( + return PizzaPlannerScaffold( + title: const Text("Add Pizza Event"), + body: Column( + children: [ + Expanded( + flex: 40, + child: Column( + children: [ + Row( + children: [ + const Icon(Icons.title), + Container(width: 25), + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: "Event Name", + errorText: nameValidation ? """Name can't be empty""" : null + ), + onChanged: (String newName) { + setState(() { + name = newName; + }); + }, + ), + ) + ] + ), + Row( + children: [ + const Icon(FontAwesome5.hashtag), + Expanded( + child: Slider( - value: pizzaCount.toDouble(), - min: 1, - max: 20, - divisions: 19, - label: pizzaCount.toString(), - onChanged: (double newPizzaCount) { - setState(() {pizzaCount = newPizzaCount.round();}); - }, - ) - ), - SizedBox( - width: 25, - child: Text(pizzaCount.toString()) + value: pizzaCount.toDouble(), + min: 1, + max: 20, + divisions: 19, + label: pizzaCount.toString(), + onChanged: (double newPizzaCount) { + setState(() {pizzaCount = newPizzaCount.round();}); + }, ) - ] - ), - Row( - children: [ - const Icon(FontAwesome5.weight_hanging), - Expanded( - child: Slider( - value: doughBallSize.toDouble(), - min: 100, - max: 400, - divisions: 30, - label: doughBallSize.toString(), - onChanged: (double newDoughBallSize) { - setState(() {doughBallSize = newDoughBallSize.round();}); - }, - ) - ), - SizedBox( - width: 25, - child: Text(doughBallSize.toString()) + ), + SizedBox( + width: 25, + child: Text(pizzaCount.toString()) + ) + ] + ), + Row( + children: [ + const Icon(FontAwesome5.weight_hanging), + Expanded( + child: Slider( + value: doughBallSize.toDouble(), + min: 100, + max: 400, + divisions: 30, + label: doughBallSize.toString(), + onChanged: (double newDoughBallSize) { + setState(() {doughBallSize = newDoughBallSize.round();}); + }, ) - ] - ), - widget.pizzaRecipe.getIngredientsTable(pizzaCount, doughBallSize), - ] - ) - ), - const Divider(), - Expanded( - flex: 45, - child: ListView( - children: [ - Column( - children: widget.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.isNotEmpty).map((recipeStep) { - return [ - Text(recipeStep.waitDescription), - Row( - children: [ - Expanded( - child: Slider( - value: recipeStep.waitValue!.toDouble(), - min: recipeStep.waitMin.toDouble(), - max: recipeStep.waitMax.toDouble(), - divisions: recipeStep.waitMax - recipeStep.waitMin, - label: recipeStep.waitValue.toString(), - onChanged: (newValue) => setState(() => recipeStep.waitValue = newValue.toInt()), - ) - ), - SizedBox( - width: 25, - child: Text(recipeStep.waitValue.toString()) + ), + SizedBox( + width: 25, + child: Text(doughBallSize.toString()) + ) + ] + ), + widget.pizzaRecipe.getIngredientsTable(pizzaCount, doughBallSize), + ] + ) + ), + const Divider(), + Expanded( + flex: 45, + child: ListView( + children: [ + Column( + children: widget.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.isNotEmpty).map((recipeStep) { + return [ + Text(recipeStep.waitDescription), + Row( + children: [ + Expanded( + child: Slider( + value: recipeStep.waitValue!.toDouble(), + min: recipeStep.waitMin.toDouble(), + max: recipeStep.waitMax.toDouble(), + divisions: recipeStep.waitMax - recipeStep.waitMin, + label: recipeStep.waitValue.toString(), + onChanged: (newValue) => setState(() => recipeStep.waitValue = newValue.toInt()), ) - ] - ) - ]; - }).expand((option) => option).toList() - ) - ] - ) - ), - const Divider(), - const Spacer(), - SizedBox( - width: double.infinity, - height: 70, - child: Container( - color: Colors.blue, - child: TextButton( - onPressed: () async { + ), + SizedBox( + width: 25, + child: Text(recipeStep.waitValue.toString()) + ) + ] + ) + ]; + }).expand((option) => option).toList() + ) + ] + ) + ), + const Divider(), + const Spacer(), + SizedBox( + width: double.infinity, + height: 70, + child: Container( + color: Colors.blue, + child: TextButton( + onPressed: () async { - if (name.isEmpty){ - setState(() { nameValidation = true; }); - return; - } - setState(() { nameValidation = false; }); - FocusScope.of(context).unfocus(); - DateTime? eventTime = await showDialog( - context: context, - builder: (context) { - return ConfirmPizzaEventDialog(name: name, pizzaRecipe: widget.pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize); - } - ); - if (eventTime == null){ - return; - } - - // if the user waited to long on the confirmation dialog that the first step time is now in the past - final durationUntilFirstStep = Duration(seconds: widget.pizzaRecipe.getCurrentDuration().inSeconds); - final firstStepDateTime = eventTime.subtract(durationUntilFirstStep); - if (firstStepDateTime.isBefore(DateTime.now())){ - eventTime = DateTime.now() - .add(durationUntilFirstStep) - .add(const Duration(minutes: 1)); + if (name.isEmpty){ + setState(() { nameValidation = true; }); + return; + } + setState(() { nameValidation = false; }); + FocusScope.of(context).unfocus(); + DateTime? eventTime = await showDialog( + context: context, + builder: (context) { + return ConfirmPizzaEventDialog(name: name, pizzaRecipe: widget.pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize); } + ); + if (eventTime == null){ + return; + } - final pizzaEventsBox = Hive.box("PizzaEvents"); - final PizzaEvent pizzaEvent = PizzaEvent( - name, - widget.pizzaRecipe, - pizzaCount, - doughBallSize, - eventTime - ); - await pizzaEventsBox.add(pizzaEvent); + // if the user waited to long on the confirmation dialog that the first step time is now in the past + final durationUntilFirstStep = Duration(seconds: widget.pizzaRecipe.getCurrentDuration().inSeconds); + final firstStepDateTime = eventTime.subtract(durationUntilFirstStep); + if (firstStepDateTime.isBefore(DateTime.now())){ + eventTime = DateTime.now() + .add(durationUntilFirstStep) + .add(const Duration(minutes: 1)); + } - pizzaEvent.createPizzaEventNotifications(); - - if(!mounted) { - return; //https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html - } - Navigator.of(context).pop(); - Navigator.of(context).pop(); // two times because of the pick recipe page - }, - child: const Text("Review", style: TextStyle(color: Colors.white)), - ) + final pizzaEventsBox = Hive.box("PizzaEvents"); + final PizzaEvent pizzaEvent = PizzaEvent( + name, + widget.pizzaRecipe, + pizzaCount, + doughBallSize, + eventTime + ); + await pizzaEventsBox.add(pizzaEvent); + + pizzaEvent.createPizzaEventNotifications(); + + if(!mounted) { + return; //https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html + } + Navigator.of(context).pop(); + Navigator.of(context).pop(); // two times because of the pick recipe page + }, + child: const Text("Review", style: TextStyle(color: Colors.white)), ) ) - ] - ) - ) + ) + ] + ), ); } } diff --git a/lib/pages/add_recipe_page.dart b/lib/pages/add_recipe_page.dart index c3429b8..c7f393d 100644 --- a/lib/pages/add_recipe_page.dart +++ b/lib/pages/add_recipe_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/ingredient.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:url_launcher/url_launcher.dart'; class AddRecipePage extends StatefulWidget { @@ -34,107 +35,101 @@ class AddRecipePageState extends State { @override Widget build(BuildContext context){ - return Scaffold( - appBar: AppBar( - title: const Text("Add Pizza Recipe"), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: ListView( - children: [ - TextField( - decoration: InputDecoration( - hintText: "Recipe Name", - errorText: nameValidation ? """Name can't be empty""" : null - ), - onChanged: (String newName) { - setState(() { - pizzaRecipe.name = newName; - }); - }, + return PizzaPlannerScaffold( + title: const Text("Add Recipe"), + body: ListView( + children: [ + TextField( + decoration: InputDecoration( + hintText: "Recipe Name", + errorText: nameValidation ? """Name can't be empty""" : null ), - const Divider(), - TextField( - decoration: InputDecoration( - hintText: "Recipe Description", - errorText: nameValidation ? """Description can't be empty""" : null - ), - maxLines: 8, - onChanged: (String newDescription) { - setState(() { - pizzaRecipe.description = newDescription; - }); - }, + onChanged: (String newName) { + setState(() { + pizzaRecipe.name = newName; + }); + }, + ), + const Divider(), + TextField( + decoration: InputDecoration( + hintText: "Recipe Description", + errorText: nameValidation ? """Description can't be empty""" : null ), - const Divider(), - Row( - children: [ - Expanded( - flex: 2, - child: Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return PreviewMarkdownDescription(pizzaRecipe.description); - } - ); - }, - child: const Text("Preview", style: TextStyle(color: Colors.white)), - ) - ) - ), - const Expanded( + maxLines: 8, + onChanged: (String newDescription) { + setState(() { + pizzaRecipe.description = newDescription; + }); + }, + ), + const Divider(), + Row( + children: [ + Expanded( + flex: 2, + child: Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return PreviewMarkdownDescription(pizzaRecipe.description); + } + ); + }, + child: const Text("Preview", style: TextStyle(color: Colors.white)), + ) + ) + ), + const Expanded( child: SizedBox() - ), - Expanded( - flex: 2, - child: Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () { - launch("https://guides.github.com/features/mastering-markdown/"); - }, - child: const Text("Markdown?", style: TextStyle(color: Colors.white)), - ) - ) - ) - ], - ), - const Divider(), - const Center( + ), + Expanded( + flex: 2, + child: Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () { + launch("https://guides.github.com/features/mastering-markdown/"); + }, + child: const Text("Markdown?", style: TextStyle(color: Colors.white)), + ) + ) + ) + ], + ), + const Divider(), + const Center( child: Text("Ingredients") - - ), - const Divider(), - Container( - color: Colors.blue, - child: TextButton( - onPressed: () { - setState(() { - pizzaRecipe.ingredients.add( - Ingredient( - "", - "", - 0.0 - ) - ); - }); - }, - child: const Text("Add Ingredient", style: TextStyle(color: Colors.white)), - ) - ), - const Divider(), - ] + pizzaRecipe.ingredients.map((ingredient) => buildIngredientRow(ingredient)).toList() + [ - - ], - ) - ) + + ), + const Divider(), + Container( + color: Colors.blue, + child: TextButton( + onPressed: () { + setState(() { + pizzaRecipe.ingredients.add( + Ingredient( + "", + "", + 0.0 + ) + ); + }); + }, + child: const Text("Add Ingredient", style: TextStyle(color: Colors.white)), + ) + ), + const Divider(), + ] + pizzaRecipe.ingredients.map((ingredient) => buildIngredientRow(ingredient)).toList() + [ + + ], + ), ); } diff --git a/lib/pages/pick_pizza_recipe_page.dart b/lib/pages/pick_pizza_recipe_page.dart index 7db7f73..2b717ce 100644 --- a/lib/pages/pick_pizza_recipe_page.dart +++ b/lib/pages/pick_pizza_recipe_page.dart @@ -2,42 +2,36 @@ import 'package:flutter/material.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart'; import 'package:pizzaplanner/pages/nav_drawer.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart'; class PickPizzaRecipePage extends StatelessWidget { @override Widget build(BuildContext context){ - return Scaffold( - drawer: NavDrawer(), - appBar: AppBar( - title: const Text("Pick Pizza Recipe"), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: ValueListenableBuilder( - valueListenable: Hive.box("PizzaRecipes").listenable(), - builder: (context, Box pizzaRecipesBox, widget) { - return ListView.separated( - padding: const EdgeInsets.all(8), - itemCount: pizzaRecipesBox.length, - itemBuilder: (context, i) { - final pizzaRecipe = pizzaRecipesBox.get(i); - if (pizzaRecipe == null){ - return const SizedBox(); - } - return InkWell( - onTap: () { - Navigator.pushNamed(context, "/event/add", arguments: pizzaRecipe); - }, - child: PizzaRecipeWidget(pizzaRecipe), - ); - }, - separatorBuilder: (BuildContext context, int i) => const Divider(), - ); - } - ) - ) + return PizzaPlannerScaffold( + title: const Text("Pick Recipe"), + body: ValueListenableBuilder( + valueListenable: Hive.box("PizzaRecipes").listenable(), + builder: (context, Box pizzaRecipesBox, widget) { + return ListView.separated( + padding: const EdgeInsets.all(8), + itemCount: pizzaRecipesBox.length, + itemBuilder: (context, i) { + final pizzaRecipe = pizzaRecipesBox.get(i); + if (pizzaRecipe == null){ + return const SizedBox(); + } + return InkWell( + onTap: () { + Navigator.pushNamed(context, "/event/add", arguments: pizzaRecipe); + }, + child: PizzaRecipeWidget(pizzaRecipe), + ); + }, + separatorBuilder: (BuildContext context, int i) => const Divider(), + ); + } + ), ); } } \ No newline at end of file diff --git a/lib/pages/pizza_event_notification_page.dart b/lib/pages/pizza_event_notification_page.dart index f42fcf9..6358f91 100644 --- a/lib/pages/pizza_event_notification_page.dart +++ b/lib/pages/pizza_event_notification_page.dart @@ -9,6 +9,7 @@ import 'package:pizzaplanner/entities/pizza_event.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart'; import 'package:pizzaplanner/main.dart'; import 'package:pizzaplanner/pages/recipe_step_instruction_page.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:vibration/vibration.dart'; @@ -56,98 +57,92 @@ class PizzaEventNotificationState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text("From notification"), + return PizzaPlannerScaffold( + title: Text(recipeStep.name), + body: Column( + children: [ + Expanded( + flex: 10, + child: Center( + child: Text(pizzaEvent.name), + ), + ), + Expanded( + flex: 10, + child: Center( + child: Text(recipeStep.name) + ), + ), + const Divider(), + Expanded( + flex: 10, + child: Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () async { + showDialog(context: context, builder: (BuildContext context) { + return buildIgnoreDialog(); + }); + }, + child: const Text("Ignore", style: TextStyle(color: Colors.white)), + ) + ) + ), + const Divider(), + Expanded( + flex: 30, + child: Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () async { + setRecipeStepNotification(DateTime.now().add(const Duration(minutes: 15))); + Navigator.pop(context); + }, + onLongPress: () async { + final future5Min = DateTime.now().add(const Duration(minutes: 5)); + DatePicker.showDateTimePicker(context, + minTime: future5Min, + currentTime: future5Min, + maxTime: DateTime.now().add(const Duration(days: 365*10)), + onConfirm: (newEventTime) { + setState((){ + setRecipeStepNotification(newEventTime); + Navigator.pop(context); + }); + } + ); + + }, + child: const Text("Snooze 15 minutes", style: TextStyle(color: Colors.white)), + ) + ) + ), + const Divider(), + Expanded( + flex: 40, + child: Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () async { + Navigator.pop(context); + Navigator.pushNamed( + context, + "/event/recipe_step", + arguments: RecipeStepInstructionPageArguments( + pizzaEvent, + recipeStep + ) + ); + }, + child: const Text("Start!", style: TextStyle(color: Colors.white)), + ) + ) + ), + ] ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Expanded( - flex: 10, - child: Center( - child: Text(pizzaEvent.name), - ), - ), - Expanded( - flex: 10, - child: Center( - child: Text(recipeStep.name) - ), - ), - const Divider(), - Expanded( - flex: 10, - child: Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () async { - showDialog(context: context, builder: (BuildContext context) { - return buildIgnoreDialog(); - }); - }, - child: const Text("Ignore", style: TextStyle(color: Colors.white)), - ) - ) - ), - const Divider(), - Expanded( - flex: 30, - child: Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () async { - setRecipeStepNotification(DateTime.now().add(const Duration(minutes: 15))); - Navigator.pop(context); - }, - onLongPress: () async { - final future5Min = DateTime.now().add(const Duration(minutes: 5)); - DatePicker.showDateTimePicker(context, - minTime: future5Min, - currentTime: future5Min, - maxTime: DateTime.now().add(const Duration(days: 365*10)), - onConfirm: (newEventTime) { - setState((){ - setRecipeStepNotification(newEventTime); - Navigator.pop(context); - }); - } - ); - - }, - child: const Text("Snooze 15 minutes", style: TextStyle(color: Colors.white)), - ) - ) - ), - const Divider(), - Expanded( - flex: 40, - child: Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () async { - Navigator.pop(context); - Navigator.pushNamed( - context, - "/event/recipe_step", - arguments: RecipeStepInstructionPageArguments( - pizzaEvent, - recipeStep - ) - ); - }, - child: const Text("Start!", style: TextStyle(color: Colors.white)), - ) - ) - ), - ] - ) - ) ); } diff --git a/lib/pages/pizza_event_page.dart b/lib/pages/pizza_event_page.dart index 0f06258..c7c66df 100644 --- a/lib/pages/pizza_event_page.dart +++ b/lib/pages/pizza_event_page.dart @@ -7,6 +7,7 @@ import 'package:pizzaplanner/entities/PizzaRecipe/ingredient.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart'; import 'package:pizzaplanner/main.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:pizzaplanner/util.dart'; import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -26,35 +27,30 @@ class PizzaEventPageState extends State { Widget build(BuildContext context) { final recipeStepCount = widget.pizzaEvent.recipe.recipeSteps.length; final completedRecipeStepCount = widget.pizzaEvent.recipe.recipeSteps.where((recipeStep) => recipeStep.completed).length; - return Scaffold( - appBar: AppBar( - title: Text(widget.pizzaEvent.name), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Expanded( - flex: 15, - child: Column( - children: [ - Text(widget.pizzaEvent.name), - Text(getTimeRemainingString(widget.pizzaEvent.dateTime)), - Container( - color: Colors.blue, - child: TextButton( - onPressed: () { - Navigator.pushNamed(context, "/recipe/view", arguments: widget.pizzaEvent.recipe); - }, - child: Text(widget.pizzaEvent.recipe.name, style: const TextStyle(color: Colors.white)), - ) - ) - ], - ), + return PizzaPlannerScaffold( + title: Text(widget.pizzaEvent.name), + body: Column( + children: [ + Expanded( + flex: 15, + child: Column( + children: [ + Text(widget.pizzaEvent.name), + Text(getTimeRemainingString(widget.pizzaEvent.dateTime)), + Container( + color: Colors.blue, + child: TextButton( + onPressed: () { + Navigator.pushNamed(context, "/recipe/view", arguments: widget.pizzaEvent.recipe); + }, + child: Text(widget.pizzaEvent.recipe.name, style: const TextStyle(color: Colors.white)), + ) + ) + ], ), - const Divider(), - Expanded( + ), + const Divider(), + Expanded( flex: 80, child: ListView( children: [ @@ -78,28 +74,27 @@ class PizzaEventPageState extends State { ] + widget.pizzaEvent.recipe.ingredients.map((ingredient) => buildIngredientWidget(ingredient)).toList(), ), Table( - columnWidths: const { - 0: FlexColumnWidth(4), - 1: FlexColumnWidth(3), - 2: FlexColumnWidth(), - }, - children: [ - TableRow( - children: [ - const TableCell(child: Text("Recipe Step")), - const TableCell(child: Text("When")), - TableCell(child: Text("$completedRecipeStepCount/$recipeStepCount")), - ] - ) - ] + widget.pizzaEvent.recipe.recipeSteps.map((recipeStep) => buildRecipeStepWhenWidget(recipeStep)).toList() + columnWidths: const { + 0: FlexColumnWidth(4), + 1: FlexColumnWidth(3), + 2: FlexColumnWidth(), + }, + children: [ + TableRow( + children: [ + const TableCell(child: Text("Recipe Step")), + const TableCell(child: Text("When")), + TableCell(child: Text("$completedRecipeStepCount/$recipeStepCount")), + ] + ) + ] + widget.pizzaEvent.recipe.recipeSteps.map((recipeStep) => buildRecipeStepWhenWidget(recipeStep)).toList() ), const Divider(), - ] + ] ) - ), - ], - ) - ) + ), + ], + ), ); } diff --git a/lib/pages/pizza_events_page.dart b/lib/pages/pizza_events_page.dart index 7252c20..62bf5b6 100644 --- a/lib/pages/pizza_events_page.dart +++ b/lib/pages/pizza_events_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:pizzaplanner/entities/pizza_event.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:pizzaplanner/widgets/pizza_event_widget.dart'; import 'package:hive/hive.dart'; @@ -17,47 +18,42 @@ class PizzaEventsState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text("Pizza Events"), - ), - body: Container( - padding: const EdgeInsets.all(16), - child: ValueListenableBuilder( - valueListenable: Hive.box("PizzaEvents").listenable(), - builder: (context, Box box, widget) { - if (box.isEmpty){ - return Container(); - } - return ListView.separated( - padding: const EdgeInsets.all(8), - itemCount: box.length, - itemBuilder: (BuildContext context, int i) => PizzaEventWidget(box.getAt(i)!), - separatorBuilder: (BuildContext context, int i) => const Divider(), - ); + return PizzaPlannerScaffold( + title: const Text("Pizza Events"), + body: ValueListenableBuilder( + valueListenable: Hive.box("PizzaEvents").listenable(), + builder: (context, Box box, widget) { + if (box.isEmpty){ + return Container(); } - ), + return ListView.separated( + padding: const EdgeInsets.all(8), + itemCount: box.length, + itemBuilder: (BuildContext context, int i) => PizzaEventWidget(box.getAt(i)!), + separatorBuilder: (BuildContext context, int i) => const Divider(), + ); + } ), floatingActionButton: FloatingActionButton( - onPressed: () async { - final dynamic newPizzaEvent = await Navigator.pushNamed( - context, - "/event/pick_recipe", - ); + onPressed: () async { + final dynamic newPizzaEvent = await Navigator.pushNamed( + context, + "/event/pick_recipe", + ); - if (newPizzaEvent != null){ - addPizzaEvent(newPizzaEvent as PizzaEvent); - } - }, - tooltip: "Add Pizza Plans", - child: Center( - child: Row( - children: const [ - Icon(Icons.add), - Icon(Icons.local_pizza_rounded), - ] + if (newPizzaEvent != null){ + addPizzaEvent(newPizzaEvent as PizzaEvent); + } + }, + tooltip: "Add Pizza Plans", + child: Center( + child: Row( + children: const [ + Icon(Icons.add), + Icon(Icons.local_pizza_rounded), + ] + ) ) - ) ), ); } diff --git a/lib/pages/recipe_page.dart b/lib/pages/recipe_page.dart index 7d06dd3..b4c6995 100644 --- a/lib/pages/recipe_page.dart +++ b/lib/pages/recipe_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart'; import 'package:pizzaplanner/entities/pizza_event.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:url_launcher/url_launcher.dart'; class RecipePage extends StatefulWidget { @@ -41,38 +42,35 @@ class RecipePageState extends State { ); } } - - return Scaffold( - appBar: AppBar( + + return PizzaPlannerScaffold( title: Text(widget.pizzaRecipe.name), - ), - resizeToAvoidBottomInset: false, - body: Column( - children: [ - Expanded( - flex: 95, - child: PageView( - onPageChanged: (newPage) => setState(() {page = newPage;}), - controller: controller, - children: [ - Markdown( - data: widget.pizzaRecipe.description, - onTapLink: (text, url, title) { - launch(url!); - }, - ), - ] + widget.pizzaRecipe.recipeSteps.map((recipeStep) => buildRecipeStep(recipeStep)).toList() - ) - ), - Expanded( - flex: 5, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: pageIndex - ) - ) - ], - ) + body: Column( + children: [ + Expanded( + flex: 95, + child: PageView( + onPageChanged: (newPage) => setState(() {page = newPage;}), + controller: controller, + children: [ + Markdown( + data: widget.pizzaRecipe.description, + onTapLink: (text, url, title) { + launch(url!); + }, + ), + ] + widget.pizzaRecipe.recipeSteps.map((recipeStep) => buildRecipeStep(recipeStep)).toList() + ) + ), + Expanded( + flex: 5, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: pageIndex + ) + ) + ], + ), ); } diff --git a/lib/pages/recipe_step_instruction_page.dart b/lib/pages/recipe_step_instruction_page.dart index 3268850..d0d51a8 100644 --- a/lib/pages/recipe_step_instruction_page.dart +++ b/lib/pages/recipe_step_instruction_page.dart @@ -4,6 +4,7 @@ import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:url_launcher/url_launcher.dart'; class RecipeStepInstructionPageArguments { @@ -49,41 +50,37 @@ class RecipeStepInstructionState extends State { } else if (page > 0){ nextButtonText = "Next step"; } - return Scaffold( - appBar: AppBar( + + return PizzaPlannerScaffold( title: Text(widget.recipeStep.name), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: Column( + body: Column( children: [ Expanded( - flex: 90, - child: PageView( - controller: controller, - onPageChanged: (newPage) => setState(() { - page = newPage; - if (widget.recipeStep.subSteps.isNotEmpty && page != 0) { - currentSubStep = widget.recipeStep.subSteps.elementAt(newPage-1); - } - }), - children: [ - Markdown( - data: widget.recipeStep.description, - onTapLink: (text, url, title) { - launch(url!); - }, - ) - ] + widget.recipeStep.subSteps.map((subStep) { - return Markdown( - data: subStep.description, - onTapLink: (text, url, title) { - launch(url!); - }, - ); - }).toList() - ) + flex: 90, + child: PageView( + controller: controller, + onPageChanged: (newPage) => setState(() { + page = newPage; + if (widget.recipeStep.subSteps.isNotEmpty && page != 0) { + currentSubStep = widget.recipeStep.subSteps.elementAt(newPage-1); + } + }), + children: [ + Markdown( + data: widget.recipeStep.description, + onTapLink: (text, url, title) { + launch(url!); + }, + ) + ] + widget.recipeStep.subSteps.map((subStep) { + return Markdown( + data: subStep.description, + onTapLink: (text, url, title) { + launch(url!); + }, + ); + }).toList() + ) ), Expanded( flex: 10, @@ -139,8 +136,7 @@ class RecipeStepInstructionState extends State { ), ) ] - ) - ) + ), ); } } \ No newline at end of file diff --git a/lib/pages/recipes_page.dart b/lib/pages/recipes_page.dart index fe999ec..80fb1c3 100644 --- a/lib/pages/recipes_page.dart +++ b/lib/pages/recipes_page.dart @@ -2,63 +2,57 @@ import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart'; import 'package:pizzaplanner/pages/nav_drawer.dart'; +import 'package:pizzaplanner/pages/scaffold.dart'; import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart'; class RecipesPage extends StatelessWidget { @override Widget build(BuildContext context){ - return Scaffold( - drawer: NavDrawer(), - appBar: AppBar( - title: const Text("Recipes"), - ), - resizeToAvoidBottomInset: false, - body: Container( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - const Expanded( - flex: 5, - child: Text("Search here maybe") - ), - Container( - color: Colors.blue, - width: double.infinity, - child: TextButton( - onPressed: () async { - Navigator.pushNamed(context, "/recipes/add"); - }, - child: const Text("New Recipe", style: TextStyle(color: Colors.white)), - ) - ), - const Divider(), - Expanded( - flex: 50, - child: ValueListenableBuilder( - valueListenable: Hive.box("PizzaRecipes").listenable(), - builder: (context, Box pizzaRecipesBox, widget) { - return ListView.separated( - itemCount: pizzaRecipesBox.length, - itemBuilder: (context, i) { - final pizzaRecipe = pizzaRecipesBox.get(i); - if (pizzaRecipe == null){ - return const SizedBox(); - } - return InkWell( - onTap: () { - Navigator.pushNamed(context, "/recipe/view", arguments: pizzaRecipe); - }, - child: PizzaRecipeWidget(pizzaRecipe), - ); - }, - separatorBuilder: (BuildContext context, int i) => const Divider(), - ); - } - ), + return PizzaPlannerScaffold( + title: const Text("Pizza Recipes"), + body: Column( + children: [ + const Expanded( + flex: 5, + child: Text("Search here maybe") + ), + Container( + color: Colors.blue, + width: double.infinity, + child: TextButton( + onPressed: () async { + Navigator.pushNamed(context, "/recipes/add"); + }, + child: const Text("New Recipe", style: TextStyle(color: Colors.white)), ) - ] - ) - ) + ), + const Divider(), + Expanded( + flex: 50, + child: ValueListenableBuilder( + valueListenable: Hive.box("PizzaRecipes").listenable(), + builder: (context, Box pizzaRecipesBox, widget) { + return ListView.separated( + itemCount: pizzaRecipesBox.length, + itemBuilder: (context, i) { + final pizzaRecipe = pizzaRecipesBox.get(i); + if (pizzaRecipe == null){ + return const SizedBox(); + } + return InkWell( + onTap: () { + Navigator.pushNamed(context, "/recipe/view", arguments: pizzaRecipe); + }, + child: PizzaRecipeWidget(pizzaRecipe), + ); + }, + separatorBuilder: (BuildContext context, int i) => const Divider(), + ); + } + ), + ) + ] + ), ); } } \ No newline at end of file diff --git a/lib/pages/scaffold.dart b/lib/pages/scaffold.dart new file mode 100644 index 0000000..386cd4e --- /dev/null +++ b/lib/pages/scaffold.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:pizzaplanner/pages/nav_drawer.dart'; + +class PizzaPlannerScaffold extends StatelessWidget { + late final Widget _body; + late final Widget _appBarTitle; + late final bool _resizeToAvoidBottomInset; + late final EdgeInsets _edgeInsets; + late final FloatingActionButton? _floatingActionButton; + PizzaPlannerScaffold({ + required Widget body, + required Widget title, + bool resizeToAvoidBottomInset = false, + EdgeInsets edgeInsets = const EdgeInsets.all(16), + FloatingActionButton? floatingActionButton + }){ + _body = body; + _appBarTitle = title; + _resizeToAvoidBottomInset = resizeToAvoidBottomInset; + _edgeInsets = edgeInsets; + _floatingActionButton = floatingActionButton; + } + + @override + Widget build(BuildContext context){ + return Scaffold( + body: Container( + padding: _edgeInsets, + child: _body + ), + appBar: AppBar( + title: _appBarTitle, + ), + resizeToAvoidBottomInset: _resizeToAvoidBottomInset, + drawer: NavDrawer(), + floatingActionButton: _floatingActionButton, + ); + } +} \ No newline at end of file