diff --git a/lib/entities/PizzaRecipe/PizzaRecipe.dart b/lib/entities/PizzaRecipe/PizzaRecipe.dart index e1136f4..d053671 100644 --- a/lib/entities/PizzaRecipe/PizzaRecipe.dart +++ b/lib/entities/PizzaRecipe/PizzaRecipe.dart @@ -109,6 +109,10 @@ class PizzaRecipe extends HiveObject { return Duration(seconds: recipeSteps.map((recipeStep) => recipeStep.getWaitMinInSeconds()).reduce((a, b) => a+b)); } + Duration getMaxDuration(){ + return Duration(seconds: recipeSteps.map((recipeStep) => recipeStep.getWaitMaxInSeconds()).reduce((a, b) => a+b)); + } + Duration getCurrentDuration(){ return Duration(seconds: recipeSteps.map((recipeStep) => recipeStep.getCurrentWaitInSeconds()).reduce((a, b) => a+b)); } diff --git a/lib/main.dart b/lib/main.dart index c06105c..95a3bfd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart'; import 'package:pizzaplanner/entities/PizzaRecipe/RecipeSubStep.dart'; import 'package:pizzaplanner/pages/AddPizzaEventPage.dart'; +import 'package:pizzaplanner/pages/PickPizzaRecipePage.dart'; import 'package:pizzaplanner/pages/PizzaEventsPage.dart'; import 'package:hive/hive.dart'; @@ -50,8 +51,11 @@ class RouteGenerator { case "/": { return MaterialPageRoute(builder: (context) => PizzaEventsPage()); } - case "/add": { - return MaterialPageRoute(builder: (context) => AddPizzaEventPage()); + case "/event/pick_recipe": { + return MaterialPageRoute(builder: (context) => PickPizzaRecipePage()); + } + case "/event/add": { + return MaterialPageRoute(builder: (context) => AddPizzaEventPage(settings.arguments as PizzaRecipe)); } default: { diff --git a/lib/pages/AddPizzaEventPage.dart b/lib/pages/AddPizzaEventPage.dart index 359ac8e..50ddf4e 100644 --- a/lib/pages/AddPizzaEventPage.dart +++ b/lib/pages/AddPizzaEventPage.dart @@ -11,14 +11,16 @@ import 'package:hive/hive.dart'; import 'package:hive_flutter/hive_flutter.dart'; class AddPizzaEventPage extends StatefulWidget { + final PizzaRecipe pizzaRecipe; + + AddPizzaEventPage(this.pizzaRecipe); + @override AddPizzaEventPageState createState() => AddPizzaEventPageState(); } class AddPizzaEventPageState extends State { String name = ""; - bool initialized = false; - late PizzaRecipe pizzaRecipe; int pizzaCount = 1; int doughBallSize = 250; DateTime eventTime = DateTime.now(); @@ -35,179 +37,151 @@ class AddPizzaEventPageState extends State { body: Container( padding: EdgeInsets.fromLTRB(40, 10, 40, 10), child: Column( - children: [ - Expanded( - flex: 35, - child: Column( - children: [ - Row( + children: [ + Expanded( + flex: 20, + child: Column( children: [ - Icon(Icons.title), - Container(width: 25), - Expanded( - child: TextField( - decoration: InputDecoration( - hintText: "Event Name", - errorText: this.nameValidation ? "Name can\'t be empty" : null - ), - onChanged: (String newName) { - setState(() { - name = newName; - }); - }, - ), - ) - ] - ), - Row( - children: [ - Icon(FontAwesome5.pizza_slice), - Container(width: 25), - ValueListenableBuilder( - valueListenable: Hive.box("PizzaRecipes").listenable(), - builder: (context, Box box, widget) { - if (box.isEmpty){ - return Text("Loading Pizza Recipes..."); - } - this.pizzaRecipe = box.values.first; - return Expanded( - child: DropdownButton( - value: this.pizzaRecipe.name, - onChanged: (String? newType) { - setState(() => this.pizzaRecipe = box.values.firstWhere((pizzaRecipe) => pizzaRecipe.name == newType)); - }, - items: box.values.map((pizzaRecipe) { - return DropdownMenuItem( - value: pizzaRecipe.name, - child: Text(pizzaRecipe.name) - ); - }).toList() - ) - ); - } - ), - ] - ), - Row( - children: [ - Icon(FontAwesome5.hashtag), - Expanded( - child: Slider( - value: pizzaCount.toDouble(), - min: 1, - max: 20, - divisions: 19, - label: this.pizzaCount.toString(), - onChanged: (double newPizzaCount) { - setState(() {this.pizzaCount = newPizzaCount.round();}); - }, - ) - ), - Container( - width: 25, - child: Text(this.pizzaCount.toString()) - ) - ] - ), - Row( - children: [ - Icon(FontAwesome5.weight_hanging), - Expanded( - child: Slider( - value: doughBallSize.toDouble(), - min: 100, - max: 400, - divisions: 30, - label: this.doughBallSize.toString(), - onChanged: (double newDoughBallSize) { - setState(() {this.doughBallSize = newDoughBallSize.round();}); - }, - ) - ), - Container( - width: 25, - child: Text(this.doughBallSize.toString()) - ) - ] - ), - ] - ) - ), - Divider(), - Expanded( - flex: 45, - child: ListView( - children: [ - this.initialized ? Column( - children: this.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.length > 0).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) => this.setState(() => recipeStep.waitValue = newValue.toInt()), - ) + Row( + children: [ + Icon(Icons.title), + Container(width: 25), + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: "Event Name", + errorText: this.nameValidation ? "Name can\'t be empty" : null + ), + onChanged: (String newName) { + setState(() { + name = newName; + }); + }, ), - Container( - width: 25, - child: Text(recipeStep.waitValue.toString()) + ) + ] + ), + Row( + children: [ + Icon(FontAwesome5.hashtag), + Expanded( + child: Slider( + value: pizzaCount.toDouble(), + min: 1, + max: 20, + divisions: 19, + label: this.pizzaCount.toString(), + onChanged: (double newPizzaCount) { + setState(() {this.pizzaCount = newPizzaCount.round();}); + }, + ) + ), + Container( + width: 25, + child: Text(this.pizzaCount.toString()) + ) + ] + ), + Row( + children: [ + Icon(FontAwesome5.weight_hanging), + Expanded( + child: Slider( + value: doughBallSize.toDouble(), + min: 100, + max: 400, + divisions: 30, + label: this.doughBallSize.toString(), + onChanged: (double newDoughBallSize) { + setState(() {this.doughBallSize = newDoughBallSize.round();}); + }, + ) + ), + Container( + width: 25, + child: Text(this.doughBallSize.toString()) + ) + ] + ), + ] + ) + ), + Divider(), + Expanded( + flex: 45, + child: ListView( + children: [ + Column( + children: this.widget.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.length > 0).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) => this.setState(() => recipeStep.waitValue = newValue.toInt()), + ) + ), + Container( + width: 25, + child: Text(recipeStep.waitValue.toString()) + ) + ] ) - ] - ) - ]; - }).expand((option) => option).toList() - ) : Container(), - ] - ) - ), - Divider(), - Spacer(), - SizedBox( - width: double.infinity, - height: 70, - child: Container( - color: Colors.blue, - child: TextButton( - child: Text("Review", style: TextStyle(color: Colors.white)), - onPressed: () async { - if (this.name.length == 0){ - setState(() { this.nameValidation = true; }); - return; - } - setState(() { this.nameValidation = false; }); - FocusScope.of(context).unfocus(); - DateTime? eventTime = await showDialog( - context: context, - builder: (context) { - return ConfirmPizzaEventDialog(name: name, pizzaRecipe: pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize); + ]; + }).expand((option) => option).toList() + ) + ] + ) + ), + Divider(), + Spacer(), + SizedBox( + width: double.infinity, + height: 70, + child: Container( + color: Colors.blue, + child: TextButton( + child: Text("Review", style: TextStyle(color: Colors.white)), + onPressed: () async { + if (this.name.length == 0){ + setState(() { this.nameValidation = true; }); + return; } - ); - if (eventTime == null){ - return; - } - var pizzaEventsBox = await Hive.box("PizzaEvents"); - pizzaEventsBox.add( - PizzaEvent( - this.name, - this.pizzaRecipe, - this.pizzaCount, - this.doughBallSize, - eventTime - ) - ); - Navigator.pop(context); - }, - ) - ) - ) - ] - ) + setState(() { this.nameValidation = false; }); + FocusScope.of(context).unfocus(); + DateTime? eventTime = await showDialog( + context: context, + builder: (context) { + return ConfirmPizzaEventDialog(name: name, pizzaRecipe: this.widget.pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize); + } + ); + if (eventTime == null){ + return; + } + var pizzaEventsBox = await Hive.box("PizzaEvents"); + pizzaEventsBox.add( + PizzaEvent( + this.name, + this.widget.pizzaRecipe, + this.pizzaCount, + this.doughBallSize, + eventTime + ) + ); + Navigator.pop(context); + Navigator.pop(context); // two times because of the pick recipe page + }, + ) + ) + ) + ] + ) ) ); } @@ -244,6 +218,7 @@ class ConfirmPizzaEventState extends State { @override Widget build(BuildContext context){ return Dialog( + insetPadding: EdgeInsets.all(10), child: Container( padding: EdgeInsets.all(10), child: Column( diff --git a/lib/pages/PickPizzaRecipePage.dart b/lib/pages/PickPizzaRecipePage.dart new file mode 100644 index 0000000..769f025 --- /dev/null +++ b/lib/pages/PickPizzaRecipePage.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:hive_flutter/adapters.dart'; +import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart'; +import 'package:pizzaplanner/widgets/PizzaRecipeWidget.dart'; + +class PickPizzaRecipePage extends StatelessWidget { + @override + Widget build(BuildContext context){ + return Scaffold( + appBar: AppBar( + title: Text("Pick Pizza Recipe"), + ), + resizeToAvoidBottomInset: false, + body: Container( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + 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) => PizzaRecipeWidget(pizzaRecipesBox.getAt(i)!), + separatorBuilder: (BuildContext context, int i) => const Divider(), + ); + } + ) + ) + ); + } +} \ No newline at end of file diff --git a/lib/pages/PizzaEventsPage.dart b/lib/pages/PizzaEventsPage.dart index 3c744e6..9437f67 100644 --- a/lib/pages/PizzaEventsPage.dart +++ b/lib/pages/PizzaEventsPage.dart @@ -42,7 +42,7 @@ class PizzaEventsState extends State { onPressed: () async { final dynamic newPizzaEvent = await Navigator.pushNamed( context, - "/add", + "/event/pick_recipe", ); if (newPizzaEvent != null){ diff --git a/lib/widgets/PizzaRecipeWidget.dart b/lib/widgets/PizzaRecipeWidget.dart new file mode 100644 index 0000000..69d62eb --- /dev/null +++ b/lib/widgets/PizzaRecipeWidget.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart'; + +class PizzaRecipeWidget extends StatelessWidget { + final PizzaRecipe pizzaRecipe; + + PizzaRecipeWidget(this.pizzaRecipe); + + @override + Widget build(BuildContext context) { + return InkWell( + child: Container( + height: 120, + color: Colors.blueAccent, + child: Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(pizzaRecipe.name), + ] + ), + Text(pizzaRecipe.description), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("${pizzaRecipe.getMinDuration().inHours.round()} to ${pizzaRecipe.getMaxDuration().inHours.round()} hours") + ] + ) + ] + ) + ) + ), + onTap: () { + Navigator.pushNamed(context, "/event/add", arguments: this.pizzaRecipe); + }, + ); + } +} \ No newline at end of file