switched the addPizzaEventPage to a recipe list from yamls on the device
This commit is contained in:
parent
2ffe58e75c
commit
c43d92c0f1
8 changed files with 296 additions and 144 deletions
54
assets/recipes/neapolitan_quick.yaml
Normal file
54
assets/recipes/neapolitan_quick.yaml
Normal file
|
@ -0,0 +1,54 @@
|
|||
recipe:
|
||||
name: "Neapolitan Day Dough"
|
||||
description: >
|
||||
A Neapolitan Style pizza prepared in a day
|
||||
ingredients:
|
||||
method: ratio
|
||||
items:
|
||||
- name: flour
|
||||
unit: g
|
||||
value: 0.595
|
||||
- name: water
|
||||
unit: ml
|
||||
value: 0.386
|
||||
- name: salt
|
||||
unit: g
|
||||
value: 0.0178
|
||||
- name: yeast
|
||||
unit: g
|
||||
value: 0.0012
|
||||
steps:
|
||||
- name: Make the dough
|
||||
wait:
|
||||
unit: hours
|
||||
min: 4
|
||||
max: 6
|
||||
description: >
|
||||
Combine all the ingredients to make the dough, we start with just the water and salt and add the yeast after adding some of the flour to not kill the yeast.
|
||||
substeps:
|
||||
- name: Salt+Water
|
||||
description: >
|
||||
Combine the salt and the water in a bowl, stir until the salt dissolves.
|
||||
- name: +20% flour
|
||||
description: >
|
||||
Add ~20% of the flour to the water/salt mixture and mix everything together.
|
||||
- name: Yeast
|
||||
description: >
|
||||
Add the yeast to the mixture.
|
||||
- name: Flour
|
||||
description: >
|
||||
Add the rest of the flour to the mixture, knead the dough for 15-20 minutes.
|
||||
- name: Rise
|
||||
description: >
|
||||
Split the dough into doughballs and place the dough in a sealed/covered container at room temperature.
|
||||
- name: Preheat Oven
|
||||
wait:
|
||||
unit: minutes
|
||||
min: 30
|
||||
max: 120
|
||||
description: >
|
||||
Preheat the oven in advance to ensure it's as hot as it can be
|
||||
A high (250 to 300 degrees celsius) is recommended)
|
||||
- name: Pizza Time!
|
||||
description: >
|
||||
Time to make pizza!
|
54
assets/recipes/new_york.yaml
Normal file
54
assets/recipes/new_york.yaml
Normal file
|
@ -0,0 +1,54 @@
|
|||
recipe:
|
||||
name: "New York"
|
||||
description: >
|
||||
A Neapolitan Style pizza prepared in a day
|
||||
ingredients:
|
||||
method: ratio
|
||||
items:
|
||||
- name: flour
|
||||
unit: g
|
||||
value: 0.545
|
||||
- name: water
|
||||
unit: ml
|
||||
value: 0.436
|
||||
- name: salt
|
||||
unit: g
|
||||
value: 0.0178
|
||||
- name: yeast
|
||||
unit: g
|
||||
value: 0.0012
|
||||
steps:
|
||||
- name: Make the dough
|
||||
wait:
|
||||
unit: hours
|
||||
min: 4
|
||||
max: 6
|
||||
description: >
|
||||
Combine all the ingredients to make the dough, we start with just the water and salt and add the yeast after adding some of the flour to not kill the yeast.
|
||||
substeps:
|
||||
- name: Salt+Water
|
||||
description: >
|
||||
Combine the salt and the water in a bowl, stir until the salt dissolves.
|
||||
- name: +20% flour
|
||||
description: >
|
||||
Add ~20% of the flour to the water/salt mixture and mix everything together.
|
||||
- name: Yeast
|
||||
description: >
|
||||
Add the yeast to the mixture.
|
||||
- name: Flour
|
||||
description: >
|
||||
Add the rest of the flour to the mixture, knead the dough for 15-20 minutes.
|
||||
- name: Rise
|
||||
description: >
|
||||
Split the dough into doughballs and place the dough in a sealed/covered container at room temperature.
|
||||
- name: Preheat Oven
|
||||
wait:
|
||||
unit: minutes
|
||||
min: 30
|
||||
max: 120
|
||||
description: >
|
||||
Preheat the oven in advance to ensure it's as hot as it can be
|
||||
A high (250 to 300 degrees celsius) is recommended)
|
||||
- name: Pizza Time!
|
||||
description: >
|
||||
Time to make pizza!
|
|
@ -1,14 +1,16 @@
|
|||
|
||||
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
|
||||
|
||||
class PizzaEvent {
|
||||
final String name;
|
||||
final String type;
|
||||
final PizzaRecipe recipe;
|
||||
final int pizzaCount;
|
||||
final int doughBallSize;
|
||||
final DateTime dateTime;
|
||||
|
||||
PizzaEvent(
|
||||
this.name,
|
||||
this.type,
|
||||
this.recipe,
|
||||
this.pizzaCount,
|
||||
this.doughBallSize,
|
||||
this.dateTime
|
||||
|
|
|
@ -15,8 +15,8 @@ class PizzaRecipe {
|
|||
|
||||
PizzaRecipe(this.name, this.description, this.ingredients, this.recipeSteps);
|
||||
|
||||
static Future<PizzaRecipe> fromYaml() async{
|
||||
String yamlString = await loadAsset("assets/recipes/neapolitan_cold.yaml");
|
||||
static Future<PizzaRecipe> fromYaml(yamlPath) async{
|
||||
String yamlString = await loadAsset(yamlPath);
|
||||
var yaml = loadYaml(yamlString);
|
||||
var recipe = yaml["recipe"];
|
||||
|
||||
|
@ -38,11 +38,16 @@ class PizzaRecipe {
|
|||
String stepName = step["name"];
|
||||
String stepDescription = step["description"];
|
||||
|
||||
YamlMap waitMap = step.containsKey("wait") ? step["wait"] : YamlList();
|
||||
String waitUnit = waitMap["unit"];
|
||||
int waitMin = waitMap["min"];
|
||||
int waitMax = waitMap["max"];
|
||||
print(step);
|
||||
String waitUnit = "none";
|
||||
int waitMin = 0;
|
||||
int waitMax = 0;
|
||||
|
||||
if (step.containsKey("wait")) {
|
||||
YamlMap waitMap = step["wait"];
|
||||
waitUnit = waitMap["unit"];
|
||||
waitMin = waitMap["min"];
|
||||
waitMax = waitMap["max"];
|
||||
}
|
||||
|
||||
YamlList subSteps = step.containsKey("substeps") ? step["substeps"] : YamlList();
|
||||
var newSubSteps = List.generate(subSteps.length, (j) {
|
||||
|
@ -66,5 +71,9 @@ class PizzaRecipe {
|
|||
newRecipeSteps
|
||||
);
|
||||
}
|
||||
|
||||
String toString() {
|
||||
return "PizzaRecipe(${this.name}, ${this.ingredients.ingredients.length}, ${this.recipeSteps.length})";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
|||
import 'package:fluttericon/font_awesome5_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:pizzaplanner/entities/PizzaEvent.dart';
|
||||
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
|
||||
import 'package:pizzaplanner/util.dart';
|
||||
|
||||
class AddPizzaEventPage extends StatefulWidget {
|
||||
@override
|
||||
|
@ -15,156 +17,167 @@ class AddPizzaEventPageState extends State<AddPizzaEventPage> {
|
|||
final DateFormat dateFormatter = DateFormat("yyyy-MM-dd hh:mm");
|
||||
|
||||
String name = "";
|
||||
String pizzaType = "Neapolitan";
|
||||
bool initialized = false;
|
||||
late PizzaRecipe pizzaRecipe;
|
||||
late List<PizzaRecipe> pizzaTypes;
|
||||
int pizzaCount = 1;
|
||||
int doughBallSize = 250;
|
||||
DateTime eventTime = DateTime.now();
|
||||
|
||||
bool nameValidation = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getRecipes().then((pTypes) {
|
||||
this.pizzaTypes = pTypes;
|
||||
this.pizzaRecipe = this.pizzaTypes.first;
|
||||
setState(() {this.initialized = true;});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Add Pizza Event"),
|
||||
),
|
||||
body: Container(
|
||||
padding: EdgeInsets.fromLTRB(40, 10, 40, 10),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
appBar: AppBar(
|
||||
title: Text("Add Pizza Event"),
|
||||
),
|
||||
body: Container(
|
||||
padding: EdgeInsets.fromLTRB(40, 10, 40, 10),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
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: <Widget>[
|
||||
Icon(FontAwesome5.pizza_slice),
|
||||
Container(width: 25),
|
||||
Expanded(
|
||||
child: DropdownButton<String>(
|
||||
value: pizzaType,
|
||||
onChanged: (String? newType) {
|
||||
setState(() => pizzaType = newType!);
|
||||
},
|
||||
items: <String>["Neapolitan", "New York", "Chicago"]
|
||||
.map<DropdownMenuItem<String>>((String v) {
|
||||
return DropdownMenuItem(
|
||||
value: v,
|
||||
child: Text(v)
|
||||
);
|
||||
}).toList()
|
||||
),
|
||||
)
|
||||
]
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
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();});
|
||||
},
|
||||
)
|
||||
Row(
|
||||
children: <Widget>[
|
||||
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(this.pizzaCount.toString())
|
||||
)
|
||||
]
|
||||
),
|
||||
|
||||
Row(
|
||||
children: <Widget>[
|
||||
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();});
|
||||
},
|
||||
)
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Icon(FontAwesome5.pizza_slice),
|
||||
Container(width: 25),
|
||||
Expanded(
|
||||
child: this.initialized ? // Only render the dropdown if the recipes have been loaded from storage
|
||||
DropdownButton<String>(
|
||||
value: this.pizzaRecipe.name,
|
||||
onChanged: (String? newType) {
|
||||
setState(() => this.pizzaRecipe = this.pizzaTypes.firstWhere((pizzaRecipe) => pizzaRecipe.name == newType));
|
||||
},
|
||||
items: this.pizzaTypes.map((pizzaRecipe) {
|
||||
return DropdownMenuItem(
|
||||
value: pizzaRecipe.name,
|
||||
child: Text(pizzaRecipe.name)
|
||||
);
|
||||
}).toList()
|
||||
) : CircularProgressIndicator()
|
||||
)
|
||||
]
|
||||
),
|
||||
Container(
|
||||
width: 25,
|
||||
child: Text(this.doughBallSize.toString())
|
||||
)
|
||||
]
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Icon(FontAwesome5.calendar_alt),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
child: Center(
|
||||
child: Text(dateFormatter.format(this.eventTime)),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
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();});
|
||||
},
|
||||
)
|
||||
),
|
||||
onTap: () {
|
||||
DatePicker.showDateTimePicker(context,
|
||||
showTitleActions: true,
|
||||
minTime: DateTime.now(),
|
||||
currentTime: this.eventTime.difference(DateTime.now()).isNegative ? DateTime.now() : this.eventTime,
|
||||
maxTime: DateTime.now().add(Duration(days: 365*10)),
|
||||
onConfirm: (newEventTime) {
|
||||
setState((){ this.eventTime = newEventTime; });
|
||||
}
|
||||
);
|
||||
}
|
||||
Container(
|
||||
width: 25,
|
||||
child: Text(this.pizzaCount.toString())
|
||||
)
|
||||
]
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
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())
|
||||
)
|
||||
]
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Icon(FontAwesome5.calendar_alt),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
child: Center(
|
||||
child: Text(dateFormatter.format(this.eventTime)),
|
||||
),
|
||||
onTap: () {
|
||||
DatePicker.showDateTimePicker(context,
|
||||
showTitleActions: true,
|
||||
minTime: DateTime.now(),
|
||||
currentTime: this.eventTime.difference(DateTime.now()).isNegative ? DateTime.now() : this.eventTime,
|
||||
maxTime: DateTime.now().add(Duration(days: 365*10)),
|
||||
onConfirm: (newEventTime) {
|
||||
setState((){ this.eventTime = newEventTime; });
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
Spacer(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 70,
|
||||
child: Container(
|
||||
color: Colors.blue,
|
||||
child: TextButton(
|
||||
child: Text("Add", style: TextStyle(color: Colors.white)),
|
||||
onPressed: () {
|
||||
if (this.name.length == 0){
|
||||
setState(() { this.nameValidation = true; });
|
||||
return;
|
||||
}
|
||||
Navigator.pop(context, PizzaEvent(
|
||||
this.name,
|
||||
this.pizzaRecipe,
|
||||
this.pizzaCount,
|
||||
this.doughBallSize,
|
||||
this.eventTime
|
||||
));
|
||||
},
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
Spacer(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 70,
|
||||
child: Container(
|
||||
color: Colors.blue,
|
||||
child: TextButton(
|
||||
child: Text("Add", style: TextStyle(color: Colors.white)),
|
||||
onPressed: () {
|
||||
if (this.name.length == 0){
|
||||
setState(() { this.nameValidation = true; });
|
||||
return;
|
||||
}
|
||||
Navigator.pop(context, PizzaEvent(
|
||||
this.name,
|
||||
this.pizzaType,
|
||||
this.pizzaCount,
|
||||
this.doughBallSize,
|
||||
this.eventTime
|
||||
));
|
||||
},
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pizzaplanner/entities/PizzaEvent.dart';
|
||||
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
|
||||
import 'package:pizzaplanner/util.dart';
|
||||
import 'package:pizzaplanner/widgets/PizzaEventWidget.dart';
|
||||
|
||||
class PizzaEventsPage extends StatefulWidget {
|
||||
|
@ -30,6 +32,7 @@ class PizzaEventsState extends State<PizzaEventsPage> {
|
|||
context,
|
||||
"/add",
|
||||
);
|
||||
|
||||
if (newPizzaEvent != null){
|
||||
this.addPizzaEvent(newPizzaEvent);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,21 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
|
||||
|
||||
Future<List<PizzaRecipe>> getRecipes() async {
|
||||
final manifestContent = await rootBundle.loadString('AssetManifest.json');
|
||||
final Map<String, dynamic> manifestMap = json.decode(manifestContent);
|
||||
final List<String> fileList = manifestMap.keys.toList();
|
||||
final List<PizzaRecipe> pizzaRecipes = [];
|
||||
for (var filePath in fileList) {
|
||||
if (filePath.startsWith("assets/recipes") && filePath.endsWith(".yaml")) {
|
||||
PizzaRecipe pizzaRecipe = await PizzaRecipe.fromYaml(filePath);
|
||||
pizzaRecipes.add(pizzaRecipe);
|
||||
}
|
||||
}
|
||||
return pizzaRecipes;
|
||||
}
|
||||
|
||||
Future<String> loadAsset(String path) async {
|
||||
return await rootBundle.loadString(path);
|
||||
|
|
|
@ -70,7 +70,7 @@ class PizzaEventWidget extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(dateFormatter.format(pizzaEvent.dateTime)),
|
||||
Text(pizzaEvent.type)
|
||||
Text(pizzaEvent.recipe.name)
|
||||
],
|
||||
),
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue