revert floor stuff

This commit is contained in:
broodjeaap89 2021-07-25 20:35:50 +02:00
parent 914e17fa3c
commit 41bdfe6e4c
21 changed files with 118 additions and 957 deletions

View file

@ -1,37 +0,0 @@
import 'package:pizzaplanner/entities/PizzaEvent.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/Ingredient.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeSubStep.dart';
import 'package:pizzaplanner/entities/dao/IngridientDao.dart';
import 'package:pizzaplanner/entities/dao/PizzaEventDoa.dart';
import 'package:pizzaplanner/entities/dao/PizzaRecipeDao.dart';
import 'package:pizzaplanner/entities/dao/RecipeStepDao.dart';
import 'package:pizzaplanner/entities/dao/RecipeSubStepDao.dart';
import 'dart:async';
import 'package:floor/floor.dart';
import 'package:sqflite/sqflite.dart' as sqflite;
part 'PizzaDatabase.g.dart';
@TypeConverters([DateTimeConverter])
@Database(version: 1, entities: [PizzaEvent, PizzaRecipe, RecipeStep, RecipeSubStep, Ingredient])
abstract class PizzaDatabase extends FloorDatabase {
PizzaEventDoa get pizzaEventDoa;
PizzaRecipeDao get pizzaRecipeDao;
RecipeStepDao get recipeStepDao;
RecipeSubStepDao get recipeSubStepDao;
IngredientDao get ingredientDao;
}
class DateTimeConverter extends TypeConverter<DateTime, int> {
@override
DateTime decode(int databaseValue) {
return DateTime.fromMillisecondsSinceEpoch(databaseValue);
}
@override
int encode(DateTime value) {
return value.millisecondsSinceEpoch;
}
}

View file

@ -1,456 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'PizzaDatabase.dart';
// **************************************************************************
// FloorGenerator
// **************************************************************************
class $FloorPizzaDatabase {
/// Creates a database builder for a persistent database.
/// Once a database is built, you should keep a reference to it and re-use it.
static _$PizzaDatabaseBuilder databaseBuilder(String name) =>
_$PizzaDatabaseBuilder(name);
/// Creates a database builder for an in memory database.
/// Information stored in an in memory database disappears when the process is killed.
/// Once a database is built, you should keep a reference to it and re-use it.
static _$PizzaDatabaseBuilder inMemoryDatabaseBuilder() =>
_$PizzaDatabaseBuilder(null);
}
class _$PizzaDatabaseBuilder {
_$PizzaDatabaseBuilder(this.name);
final String? name;
final List<Migration> _migrations = [];
Callback? _callback;
/// Adds migrations to the builder.
_$PizzaDatabaseBuilder addMigrations(List<Migration> migrations) {
_migrations.addAll(migrations);
return this;
}
/// Adds a database [Callback] to the builder.
_$PizzaDatabaseBuilder addCallback(Callback callback) {
_callback = callback;
return this;
}
/// Creates the database and initializes it.
Future<PizzaDatabase> build() async {
final path = name != null
? await sqfliteDatabaseFactory.getDatabasePath(name!)
: ':memory:';
final database = _$PizzaDatabase();
database.database = await database.open(
path,
_migrations,
_callback,
);
return database;
}
}
class _$PizzaDatabase extends PizzaDatabase {
_$PizzaDatabase([StreamController<String>? listener]) {
changeListener = listener ?? StreamController<String>.broadcast();
}
PizzaEventDoa? _pizzaEventDoaInstance;
PizzaRecipeDao? _pizzaRecipeDaoInstance;
RecipeStepDao? _recipeStepDaoInstance;
RecipeSubStepDao? _recipeSubStepDaoInstance;
IngredientDao? _ingredientDaoInstance;
Future<sqflite.Database> open(String path, List<Migration> migrations,
[Callback? callback]) async {
final databaseOptions = sqflite.OpenDatabaseOptions(
version: 1,
onConfigure: (database) async {
await database.execute('PRAGMA foreign_keys = ON');
await callback?.onConfigure?.call(database);
},
onOpen: (database) async {
await callback?.onOpen?.call(database);
},
onUpgrade: (database, startVersion, endVersion) async {
await MigrationAdapter.runMigrations(
database, startVersion, endVersion, migrations);
await callback?.onUpgrade?.call(database, startVersion, endVersion);
},
onCreate: (database, version) async {
await database.execute(
'CREATE TABLE IF NOT EXISTS `PizzaEvent` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `recipeId` INTEGER NOT NULL, `pizzaCount` INTEGER NOT NULL, `doughBallSize` INTEGER NOT NULL, `dateTime` INTEGER NOT NULL, FOREIGN KEY (`recipeId`) REFERENCES `PizzaRecipe` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION)');
await database.execute(
'CREATE TABLE IF NOT EXISTS `PizzaRecipe` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `description` TEXT NOT NULL)');
await database.execute(
'CREATE TABLE IF NOT EXISTS `RecipeStep` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `pizzaRecipeId` INTEGER NOT NULL, `name` TEXT NOT NULL, `waitDescription` TEXT NOT NULL, `waitUnit` TEXT NOT NULL, `waitMin` INTEGER NOT NULL, `waitMax` INTEGER NOT NULL, `waitValue` INTEGER NOT NULL, `description` TEXT NOT NULL, FOREIGN KEY (`pizzaRecipeId`) REFERENCES `PizzaRecipe` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION)');
await database.execute(
'CREATE TABLE IF NOT EXISTS `RecipeSubStep` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `recipeStepId` INTEGER NOT NULL, `name` TEXT NOT NULL, `description` TEXT NOT NULL, FOREIGN KEY (`recipeStepId`) REFERENCES `RecipeStep` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION)');
await database.execute(
'CREATE TABLE IF NOT EXISTS `Ingredient` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `pizzaRecipeId` INTEGER NOT NULL, `name` TEXT NOT NULL, `unit` TEXT NOT NULL, `value` REAL NOT NULL, FOREIGN KEY (`pizzaRecipeId`) REFERENCES `PizzaRecipe` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION)');
await callback?.onCreate?.call(database, version);
},
);
return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions);
}
@override
PizzaEventDoa get pizzaEventDoa {
return _pizzaEventDoaInstance ??= _$PizzaEventDoa(database, changeListener);
}
@override
PizzaRecipeDao get pizzaRecipeDao {
return _pizzaRecipeDaoInstance ??=
_$PizzaRecipeDao(database, changeListener);
}
@override
RecipeStepDao get recipeStepDao {
return _recipeStepDaoInstance ??= _$RecipeStepDao(database, changeListener);
}
@override
RecipeSubStepDao get recipeSubStepDao {
return _recipeSubStepDaoInstance ??=
_$RecipeSubStepDao(database, changeListener);
}
@override
IngredientDao get ingredientDao {
return _ingredientDaoInstance ??= _$IngredientDao(database, changeListener);
}
}
class _$PizzaEventDoa extends PizzaEventDoa {
_$PizzaEventDoa(this.database, this.changeListener)
: _queryAdapter = QueryAdapter(database, changeListener),
_pizzaEventInsertionAdapter = InsertionAdapter(
database,
'PizzaEvent',
(PizzaEvent item) => <String, Object?>{
'id': item.id,
'name': item.name,
'recipeId': item.recipeId,
'pizzaCount': item.pizzaCount,
'doughBallSize': item.doughBallSize,
'dateTime': _dateTimeConverter.encode(item.dateTime)
},
changeListener);
final sqflite.DatabaseExecutor database;
final StreamController<String> changeListener;
final QueryAdapter _queryAdapter;
final InsertionAdapter<PizzaEvent> _pizzaEventInsertionAdapter;
@override
Future<List<PizzaEvent>> getAllPizzaEvents() async {
return _queryAdapter.queryList('SELECT * FROM PizzaEvent',
mapper: (Map<String, Object?> row) => PizzaEvent(
row['recipeId'] as int,
row['name'] as String,
row['pizzaCount'] as int,
row['doughBallSize'] as int,
_dateTimeConverter.decode(row['dateTime'] as int),
id: row['id'] as int?));
}
@override
Stream<PizzaEvent?> findPizzaEventById(int id) {
return _queryAdapter.queryStream('SELECT * FROM PizzaEvent WHERE id = ?1',
mapper: (Map<String, Object?> row) => PizzaEvent(
row['recipeId'] as int,
row['name'] as String,
row['pizzaCount'] as int,
row['doughBallSize'] as int,
_dateTimeConverter.decode(row['dateTime'] as int),
id: row['id'] as int?),
arguments: [id],
queryableName: 'PizzaEvent',
isView: false);
}
@override
Future<void> insertPizzaEvent(PizzaEvent pizzaEvent) async {
await _pizzaEventInsertionAdapter.insert(
pizzaEvent, OnConflictStrategy.abort);
}
}
class _$PizzaRecipeDao extends PizzaRecipeDao {
_$PizzaRecipeDao(this.database, this.changeListener)
: _queryAdapter = QueryAdapter(database, changeListener),
_pizzaRecipeInsertionAdapter = InsertionAdapter(
database,
'PizzaRecipe',
(PizzaRecipe item) => <String, Object?>{
'id': item.id,
'name': item.name,
'description': item.description
},
changeListener);
final sqflite.DatabaseExecutor database;
final StreamController<String> changeListener;
final QueryAdapter _queryAdapter;
final InsertionAdapter<PizzaRecipe> _pizzaRecipeInsertionAdapter;
@override
Future<List<PizzaRecipe>> getAllPizzaRecipes() async {
return _queryAdapter.queryList('SELECT * FROM PizzaRecipe',
mapper: (Map<String, Object?> row) => PizzaRecipe(
row['name'] as String, row['description'] as String,
id: row['id'] as int?));
}
@override
Stream<PizzaRecipe?> findPizzaRecipeById(int id) {
return _queryAdapter.queryStream('SELECT * FROM PizzaRecipe WHERE id = ?1',
mapper: (Map<String, Object?> row) => PizzaRecipe(
row['name'] as String, row['description'] as String,
id: row['id'] as int?),
arguments: [id],
queryableName: 'PizzaRecipe',
isView: false);
}
@override
Future<void> insertPizzaRecipe(PizzaRecipe pizzaRecipe) async {
await _pizzaRecipeInsertionAdapter.insert(
pizzaRecipe, OnConflictStrategy.abort);
}
}
class _$RecipeStepDao extends RecipeStepDao {
_$RecipeStepDao(this.database, this.changeListener)
: _queryAdapter = QueryAdapter(database, changeListener),
_recipeStepInsertionAdapter = InsertionAdapter(
database,
'RecipeStep',
(RecipeStep item) => <String, Object?>{
'id': item.id,
'pizzaRecipeId': item.pizzaRecipeId,
'name': item.name,
'waitDescription': item.waitDescription,
'waitUnit': item.waitUnit,
'waitMin': item.waitMin,
'waitMax': item.waitMax,
'waitValue': item.waitValue,
'description': item.description
},
changeListener);
final sqflite.DatabaseExecutor database;
final StreamController<String> changeListener;
final QueryAdapter _queryAdapter;
final InsertionAdapter<RecipeStep> _recipeStepInsertionAdapter;
@override
Future<List<RecipeStep>> getAllRecipeSteps() async {
return _queryAdapter.queryList('SELECT * FROM RecipeStep',
mapper: (Map<String, Object?> row) => RecipeStep(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['description'] as String,
row['waitDescription'] as String,
row['waitUnit'] as String,
row['waitMin'] as int,
row['waitMax'] as int,
id: row['id'] as int?));
}
@override
Stream<RecipeStep?> findRecipeStepById(int id) {
return _queryAdapter.queryStream('SELECT * FROM RecipeStep WHERE id = ?1',
mapper: (Map<String, Object?> row) => RecipeStep(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['description'] as String,
row['waitDescription'] as String,
row['waitUnit'] as String,
row['waitMin'] as int,
row['waitMax'] as int,
id: row['id'] as int?),
arguments: [id],
queryableName: 'RecipeStep',
isView: false);
}
@override
Future<List<RecipeStep>> getPizzaRecipeSteps(int pizzaRecipeId) async {
return _queryAdapter.queryList(
'SELECT * FROM RecipeStep WHERE pizzaRecipeId = ?1',
mapper: (Map<String, Object?> row) => RecipeStep(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['description'] as String,
row['waitDescription'] as String,
row['waitUnit'] as String,
row['waitMin'] as int,
row['waitMax'] as int,
id: row['id'] as int?),
arguments: [pizzaRecipeId]);
}
@override
Future<void> insertRecipeStep(RecipeStep recipeStep) async {
await _recipeStepInsertionAdapter.insert(
recipeStep, OnConflictStrategy.abort);
}
}
class _$RecipeSubStepDao extends RecipeSubStepDao {
_$RecipeSubStepDao(this.database, this.changeListener)
: _queryAdapter = QueryAdapter(database, changeListener),
_recipeSubStepInsertionAdapter = InsertionAdapter(
database,
'RecipeSubStep',
(RecipeSubStep item) => <String, Object?>{
'id': item.id,
'recipeStepId': item.recipeStepId,
'name': item.name,
'description': item.description
},
changeListener);
final sqflite.DatabaseExecutor database;
final StreamController<String> changeListener;
final QueryAdapter _queryAdapter;
final InsertionAdapter<RecipeSubStep> _recipeSubStepInsertionAdapter;
@override
Future<List<RecipeSubStep>> getAllRecipeSubSteps() async {
return _queryAdapter.queryList('SELECT * FROM RecipeSubStep',
mapper: (Map<String, Object?> row) => RecipeSubStep(
row['recipeStepId'] as int,
row['name'] as String,
row['description'] as String,
id: row['id'] as int?));
}
@override
Stream<RecipeSubStep?> findRecipeSubStepById(int id) {
return _queryAdapter.queryStream(
'SELECT * FROM RecipeSubStep WHERE id = ?1',
mapper: (Map<String, Object?> row) => RecipeSubStep(
row['recipeStepId'] as int,
row['name'] as String,
row['description'] as String,
id: row['id'] as int?),
arguments: [id],
queryableName: 'RecipeSubStep',
isView: false);
}
@override
Future<List<RecipeSubStep>> getRecipeStepSubSteps(int recipeStepId) async {
return _queryAdapter.queryList(
'SELECT * FROM RecipeStep WHERE recipeStepId = ?1',
mapper: (Map<String, Object?> row) => RecipeSubStep(
row['recipeStepId'] as int,
row['name'] as String,
row['description'] as String,
id: row['id'] as int?),
arguments: [recipeStepId]);
}
@override
Future<void> insertRecipeSubStep(RecipeSubStep recipeSubStep) async {
await _recipeSubStepInsertionAdapter.insert(
recipeSubStep, OnConflictStrategy.abort);
}
}
class _$IngredientDao extends IngredientDao {
_$IngredientDao(this.database, this.changeListener)
: _queryAdapter = QueryAdapter(database, changeListener),
_ingredientInsertionAdapter = InsertionAdapter(
database,
'Ingredient',
(Ingredient item) => <String, Object?>{
'id': item.id,
'pizzaRecipeId': item.pizzaRecipeId,
'name': item.name,
'unit': item.unit,
'value': item.value
},
changeListener);
final sqflite.DatabaseExecutor database;
final StreamController<String> changeListener;
final QueryAdapter _queryAdapter;
final InsertionAdapter<Ingredient> _ingredientInsertionAdapter;
@override
Future<List<Ingredient>> getAllIngredients() async {
return _queryAdapter.queryList('SELECT * FROM Ingredient',
mapper: (Map<String, Object?> row) => Ingredient(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['unit'] as String,
row['value'] as double,
id: row['id'] as int?));
}
@override
Stream<Ingredient?> findIngredientById(int id) {
return _queryAdapter.queryStream('SELECT * FROM Ingredient WHERE id = ?1',
mapper: (Map<String, Object?> row) => Ingredient(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['unit'] as String,
row['value'] as double,
id: row['id'] as int?),
arguments: [id],
queryableName: 'Ingredient',
isView: false);
}
@override
Future<List<Ingredient>> getPizzaRecipeIngredients(int pizzaRecipeId) async {
return _queryAdapter.queryList(
'SELECT * FROM Ingredient WHERE pizzaRecipeId = ?1',
mapper: (Map<String, Object?> row) => Ingredient(
row['pizzaRecipeId'] as int,
row['name'] as String,
row['unit'] as String,
row['value'] as double,
id: row['id'] as int?),
arguments: [pizzaRecipeId]);
}
@override
Future<void> insertIngredient(Ingredient ingredient) async {
await _ingredientInsertionAdapter.insert(
ingredient, OnConflictStrategy.abort);
}
}
// ignore_for_file: unused_element
final _dateTimeConverter = DateTimeConverter();

View file

@ -1,30 +1,18 @@
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:floor/floor.dart';
@Entity(
tableName: "PizzaEvent",
foreignKeys: [
ForeignKey(childColumns: ["recipeId"], parentColumns: ["id"], entity: PizzaRecipe)
]
)
class PizzaEvent {
@PrimaryKey(autoGenerate: true)
final int? id;
final String name;
final int recipeId; // foreign key to recipe for this event
final PizzaRecipe recipe;
final int pizzaCount;
final int doughBallSize;
final DateTime dateTime;
PizzaEvent(
this.recipeId,
this.name,
this.recipe,
this.pizzaCount,
this.doughBallSize,
this.dateTime,
{this.id,}
this.dateTime
);
}

View file

@ -1,32 +1,13 @@
import 'package:flutter/material.dart';
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/util.dart';
@Entity(
tableName: "Ingredient",
foreignKeys: [
ForeignKey(childColumns: ["pizzaRecipeId"], parentColumns: ["id"], entity: PizzaRecipe)
]
)
class Ingredient {
@PrimaryKey(autoGenerate: true)
final int? id;
final int pizzaRecipeId;
final String name;
final String unit;
final double value;
Ingredient(this.pizzaRecipeId, this.name, this.unit, this.value, {this.id});
Future<void> insert() async {
final database = await getDatabase();
final ingredientDao = database.ingredientDao;
await ingredientDao.insertIngredient(this);
}
Ingredient(this.name, this.unit, this.value);
TableRow getIngredientTableRow(int pizzaCount, int doughBallSize){
return TableRow(

View file

@ -1,42 +1,23 @@
import 'package:floor/floor.dart';
import 'package:flutter/material.dart';
import 'package:pizzaplanner/util.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/Ingredient.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/Ingredients.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeSubStep.dart';
import 'package:tuple/tuple.dart';
import 'package:pizzaplanner/util.dart';
import 'package:yaml/yaml.dart';
@entity
class PizzaRecipe {
@PrimaryKey(autoGenerate: true)
final int? id;
final String name;
final String description;
final List<Ingredient> ingredients;
@ignore
List<Ingredient> ingredients = [];
final List<RecipeStep> recipeSteps;
@ignore
List<RecipeStep> recipeSteps = [];
PizzaRecipe(this.name, this.description, this.ingredients, this.recipeSteps);
PizzaRecipe(this.name, this.description, {this.id});
Future<void> insert() async {
final database = await getDatabase();
final pizzaRecipeDao = database.pizzaRecipeDao;
await pizzaRecipeDao.insertPizzaRecipe(this);
}
Future<List<RecipeStep>> getRecipeSteps() async {
final database = await getDatabase();
final recipeStepDao = database.recipeStepDao;
return await recipeStepDao.getPizzaRecipeSteps(this.id!);
}
Future<Table> getIngredientsTable(int pizzaCount, int doughBallSize) async {
Table getIngredientsTable(int pizzaCount, int doughBallSize) {
return Table(
border: TableBorder.all(),
columnWidths: const <int, TableColumnWidth>{
@ -54,13 +35,13 @@ class PizzaRecipe {
)
] +
this.ingredients.map((ingredient) =>
ingredients.map((ingredient) =>
ingredient.getIngredientTableRow(pizzaCount, doughBallSize))
.toList()
);
}
static Future<Tuple4<PizzaRecipe, List<Ingredient>, List<RecipeStep>, List<RecipeSubStep>>> fromYaml(yamlPath) async{
static Future<PizzaRecipe> fromYaml(yamlPath) async{
String yamlString = await loadAsset(yamlPath);
var yaml = loadYaml(yamlString);
var recipe = yaml["recipe"];
@ -68,17 +49,13 @@ class PizzaRecipe {
String name = recipe["name"];
String description = recipe["description"];
PizzaRecipe pizzaRecipe = PizzaRecipe(name, description);
pizzaRecipe.insert();
YamlList ingredientsYamlList = recipe["ingredients"];
List<Ingredient> ingredients = ingredientsYamlList.map((ingredientYaml) => Ingredient(pizzaRecipe.id!, ingredientYaml["name"], ingredientYaml["unit"], ingredientYaml["value"])).toList();
YamlList ingredients = recipe["ingredients"];;
List<Ingredient> newIngredients = ingredients.map((ingredient) => Ingredient(ingredient["name"], ingredient["unit"], ingredient["value"])).toList();
YamlList steps = recipe["steps"];
List<RecipeStep> recipeSteps = [];
List<RecipeSubStep> recipeSubSteps = [];
for (var step in steps){
var newRecipeSteps = List.generate(steps.length, (i) {
YamlMap step = steps[i];
String stepName = step["name"];
String stepDescription = step["description"];
@ -95,50 +72,44 @@ class PizzaRecipe {
waitMin = waitMap["min"];
waitMax = waitMap["max"];
}
var recipeStep = RecipeStep(
pizzaRecipe.id!,
stepName,
stepDescription,
waitDescription,
waitUnit,
waitMin,
waitMax
);
recipeSteps.add(
recipeStep
);
YamlList subSteps = step.containsKey("substeps") ? step["substeps"] : YamlList();
for (var subStep in subSteps ) {
recipeSubSteps.add(
RecipeSubStep(
recipeStep.id!,
subStep["name"],
subStep["description"]
)
);
}
}
return Tuple4(pizzaRecipe, ingredients, recipeSteps, recipeSubSteps);
var newSubSteps = List.generate(subSteps.length, (j) {
var subStep = subSteps[j];
return RecipeSubStep(subStep["name"], subStep["description"]);
});
return RecipeStep(
stepName,
stepDescription,
waitDescription,
waitUnit,
waitMin,
waitMax,
newSubSteps
);
});
return PizzaRecipe(
name,
description,
newIngredients,
newRecipeSteps
);
}
Duration getMinDuration() {
Duration getMinDuration(){
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));
}
Future<Duration> getCurrentDuration() async {
return Duration(seconds: this.recipeSteps.map((recipeStep) => recipeStep.getCurrentWaitInSeconds()).reduce((a, b) => a+b));
Duration getCurrentDuration(){
return Duration(seconds: recipeSteps.map((recipeStep) => recipeStep.getCurrentWaitInSeconds()).reduce((a, b) => a+b));
}
String toString() {
return "PizzaRecipe(${this.name})";
return "PizzaRecipe(${this.name}, ${this.ingredients.length}, ${this.recipeSteps.length})";
}
Future<Table> getStepTimeTable(DateTime startTime) async {
Table getStepTimeTable(DateTime startTime) {
List<TableRow> stepRows = [];
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(startTime.millisecondsSinceEpoch);
for (var recipeStep in this.recipeSteps.reversed) {

View file

@ -1,18 +1,6 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeSubStep.dart';
import 'package:pizzaplanner/util.dart';
@Entity(
tableName: "RecipeStep",
foreignKeys: [
ForeignKey(childColumns: ["pizzaRecipeId"], parentColumns: ["id"], entity: PizzaRecipe)
]
)
class RecipeStep {
@PrimaryKey(autoGenerate: true)
final int? id;
final int pizzaRecipeId;
final String name;
final String waitDescription;
final String waitUnit;
@ -20,20 +8,12 @@ class RecipeStep {
final int waitMax;
late int waitValue;
final String description;
final List<RecipeSubStep> subSteps;
@ignore
List<RecipeSubStep> subSteps = [];
RecipeStep(this.pizzaRecipeId, this.name, this.description, this.waitDescription, this.waitUnit, this.waitMin, this.waitMax, {this.id}) {
RecipeStep(this.name, this.description, this.waitDescription, this.waitUnit, this.waitMin, this.waitMax, this.subSteps) {
waitValue = waitMin;
}
Future<void> insert() async {
final database = await getDatabase();
final recipeStepDao = database.recipeStepDao;
await recipeStepDao.insertRecipeStep(this);
}
int convertToSeconds(int value){
switch (waitUnit){
case "minutes": {

View file

@ -1,26 +1,6 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart';
import 'package:pizzaplanner/util.dart';
@Entity(
tableName: "RecipeSubStep",
foreignKeys: [
ForeignKey(childColumns: ["recipeStepId"], parentColumns: ["id"], entity: RecipeStep)
]
)
class RecipeSubStep {
@PrimaryKey(autoGenerate: true)
final int? id;
final int recipeStepId;
final String name;
final String description;
RecipeSubStep(this.recipeStepId, this.name, this.description, {this.id});
Future<void> insert() async {
final database = await getDatabase();
final recipeSubStepDao = database.recipeSubStepDao;
await recipeSubStepDao.insertRecipeSubStep(this);
}
RecipeSubStep(this.name, this.description);
}

View file

@ -1,38 +0,0 @@
import 'package:pizzaplanner/entities/PizzaDatabase.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/util.dart';
class AppDao {
static const DATABASE_PATH = "pizza.db";
static Future<List<PizzaRecipe>> getPizzaRecipes() async {
final database = await $FloorPizzaDatabase.databaseBuilder(DATABASE_PATH).build();
final pizzaRecipeDao = database.pizzaRecipeDao;
final recipeStepDao = database.recipeStepDao;
final recipeSubStepDao = database.recipeSubStepDao;
final ingredientDao = database.ingredientDao;
List<PizzaRecipe> pizzaRecipes = await pizzaRecipeDao.getAllPizzaRecipes();
if (pizzaRecipes.isEmpty){
await loadYamlRecipesIntoDb();
pizzaRecipes = await pizzaRecipeDao.getAllPizzaRecipes();
}
for (var pizzaRecipe in pizzaRecipes) {
pizzaRecipe.ingredients = await ingredientDao.getPizzaRecipeIngredients(pizzaRecipe.id!);
print(pizzaRecipe.ingredients);
pizzaRecipe.recipeSteps = await recipeStepDao.getPizzaRecipeSteps(pizzaRecipe.id!);
print(pizzaRecipe.recipeSteps);
for (var pizzaRecipeStep in pizzaRecipe.recipeSteps){
pizzaRecipeStep.subSteps = await recipeSubStepDao.getRecipeStepSubSteps(pizzaRecipeStep.id!);
print(pizzaRecipeStep.subSteps);
}
}
return pizzaRecipes;
}
}

View file

@ -1,18 +0,0 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/Ingredient.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
@dao
abstract class IngredientDao {
@Query("SELECT * FROM Ingredient")
Future<List<Ingredient>> getAllIngredients();
@Query("SELECT * FROM Ingredient WHERE id = :id")
Stream<Ingredient?> findIngredientById(int id);
@Query("SELECT * FROM Ingredient WHERE pizzaRecipeId = :pizzaRecipeId")
Future<List<Ingredient>> getPizzaRecipeIngredients(int pizzaRecipeId);
@insert
Future<void> insertIngredient(Ingredient ingredient);
}

View file

@ -1,14 +0,0 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaEvent.dart';
@dao
abstract class PizzaEventDoa {
@Query("SELECT * FROM PizzaEvent")
Future<List<PizzaEvent>> getAllPizzaEvents();
@Query("SELECT * FROM PizzaEvent WHERE id = :id")
Stream<PizzaEvent?> findPizzaEventById(int id);
@insert
Future<void> insertPizzaEvent(PizzaEvent pizzaEvent);
}

View file

@ -1,14 +0,0 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
@dao
abstract class PizzaRecipeDao {
@Query("SELECT * FROM PizzaRecipe")
Future<List<PizzaRecipe>> getAllPizzaRecipes();
@Query("SELECT * FROM PizzaRecipe WHERE id = :id")
Stream<PizzaRecipe?> findPizzaRecipeById(int id);
@insert
Future<void> insertPizzaRecipe(PizzaRecipe pizzaRecipe);
}

View file

@ -1,17 +0,0 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart';
@dao
abstract class RecipeStepDao {
@Query("SELECT * FROM RecipeStep")
Future<List<RecipeStep>> getAllRecipeSteps();
@Query("SELECT * FROM RecipeStep WHERE id = :id")
Stream<RecipeStep?> findRecipeStepById(int id);
@Query("SELECT * FROM RecipeStep WHERE pizzaRecipeId = :pizzaRecipeId")
Future<List<RecipeStep>> getPizzaRecipeSteps(int pizzaRecipeId);
@insert
Future<void> insertRecipeStep(RecipeStep recipeStep);
}

View file

@ -1,17 +0,0 @@
import 'package:floor/floor.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeSubStep.dart';
@dao
abstract class RecipeSubStepDao {
@Query("SELECT * FROM RecipeSubStep")
Future<List<RecipeSubStep>> getAllRecipeSubSteps();
@Query("SELECT * FROM RecipeSubStep WHERE id = :id")
Stream<RecipeSubStep?> findRecipeSubStepById(int id);
@Query("SELECT * FROM RecipeStep WHERE recipeStepId = :recipeStepId")
Future<List<RecipeSubStep>> getRecipeStepSubSteps(int recipeStepId);
@insert
Future<void> insertRecipeSubStep(RecipeSubStep recipeSubStep);
}

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:pizzaplanner/pages/AddPizzaEvent/AddPizzaEventPage.dart';
import 'package:pizzaplanner/pages/AddPizzaEvent/PickPizzaRecipePage.dart';
import 'package:pizzaplanner/pages/AddPizzaEventPage.dart';
import 'package:pizzaplanner/pages/PizzaEventsPage.dart';
void main() {
@ -25,9 +24,6 @@ class RouteGenerator {
case "/": {
return MaterialPageRoute(builder: (context) => PizzaEventsPage());
}
case "/pickRecipe": {
return MaterialPageRoute(builder: (context) => PickPizzaRecipePage());
}
case "/add": {
return MaterialPageRoute(builder: (context) => AddPizzaEventPage());
}

View file

@ -1,61 +0,0 @@
import 'package:flutter/material.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/entities/dao/AppDao.dart';
import 'package:pizzaplanner/widgets/PizzaRecipeWidget.dart';
class PickPizzaRecipePage extends StatefulWidget {
@override
PickPizzaRecipePageState createState() => PickPizzaRecipePageState();
}
class PickPizzaRecipePageState extends State<PickPizzaRecipePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Pizza2 Event"),
),
resizeToAvoidBottomInset: false,
body: Container(
padding: EdgeInsets.all(8),
child: Column(
children: <Widget>[
Expanded(
flex: 80,
child: FutureBuilder(
future: AppDao.getPizzaRecipes(),
builder: (BuildContext context, AsyncSnapshot<List<PizzaRecipe>> snapshot) {
if (snapshot.hasData && !snapshot.hasError){
return ListView(
children: snapshot.data!.map((pizzaRecipe) {
return PizzaRecipeWidget(pizzaRecipe);
}).toList(),
);
} else if (snapshot.hasError){
print(snapshot.error);
return Text("Something went wrong");
} else {
return Text("Loading Pizza Recipes");
}
}
)
),
Divider(),
SizedBox(
width: double.infinity,
height: 70,
child: Container(
color: Colors.blue,
child: TextButton(
child: Text("Review", style: TextStyle(color: Colors.white)),
onPressed: () {
},
)
)
)
]
)
)
);
}
}

View file

@ -4,7 +4,6 @@ import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:pizzaplanner/entities/PizzaEvent.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/RecipeStep.dart';
import 'package:pizzaplanner/util.dart';
class AddPizzaEventPage extends StatefulWidget {
@ -14,14 +13,29 @@ class AddPizzaEventPage extends StatefulWidget {
class AddPizzaEventPageState extends State<AddPizzaEventPage> {
String name = "";
late Future<PizzaRecipe> pizzaRecipe;
//final Future<List<PizzaRecipe>> pizzaRecipes = getRecipes();
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;});
}, onError: (e, stacktrace) {
print(e);
print(stacktrace);
Navigator.pop(context);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -56,35 +70,25 @@ class AddPizzaEventPageState extends State<AddPizzaEventPage> {
)
]
),
Row(
children: <Widget>[
Icon(FontAwesome5.pizza_slice),
Container(width: 25),
/*Expanded(
child: FutureBuilder<List<PizzaRecipe>>(
future: pizzaRecipes,
builder: (BuildContext context, AsyncSnapshot<List<PizzaRecipe>> snapshot){
if(snapshot.hasData && !snapshot.hasError){
//this.pizzaRecipe = snapshot.data!.first;
return DropdownButton<String>(
value: "this.pizzaRecipe.name",
onChanged: (String? newType) {
//setState(() => this.pizzaRecipe = snapshot.data!.firstWhere((pizzaRecipe) => pizzaRecipe.name == newType));
},
items: snapshot.data!.map((pizzaRecipe) {
return DropdownMenuItem(
value: pizzaRecipe.name,
child: Text(pizzaRecipe.name)
);
}).toList()
);
} else {
return CircularProgressIndicator();
}
}
),
)*/
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()
)
]
),
Row(
@ -137,40 +141,31 @@ class AddPizzaEventPageState extends State<AddPizzaEventPage> {
flex: 45,
child: ListView(
children: <Widget>[
/*FutureBuilder(
future: RecipeStep.getRecipeStepForRecipe(this.pizzaRecipe),
builder: (BuildContext context, AsyncSnapshot<List<RecipeStep>> snapshot){
if (snapshot.hasData && !snapshot.hasError) {
return Column(
children: snapshot.data!.where((recipeStep) => recipeStep.waitDescription.length > 0).map((recipeStep) {
return <Widget>[
Text(recipeStep.waitDescription),
Row(
children: <Widget>[
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())
)
]
this.initialized ? Column(
children: this.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.length > 0).map((recipeStep) {
return <Widget>[
Text(recipeStep.waitDescription),
Row(
children: <Widget>[
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()
);
} else {
return CircularProgressIndicator();
}
}
)*/
]
)
];
}).expand((option) => option).toList()
) : Container(),
]
)
),
@ -193,15 +188,15 @@ class AddPizzaEventPageState extends State<AddPizzaEventPage> {
DateTime? eventTime = await showDialog(
context: context,
builder: (context) {
return Text("tmp") //ConfirmPizzaEventDialog(name: name, pizzaRecipe: pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize);
return ConfirmPizzaEventDialog(name: name, pizzaRecipe: pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize);
}
);
if (eventTime == null){
return;
}
Navigator.pop(context, PizzaEvent(
1, // this.pizzaRecipe.id!,
this.name,
this.pizzaRecipe,
this.pizzaCount,
this.doughBallSize,
eventTime
@ -239,11 +234,10 @@ class ConfirmPizzaEventState extends State<ConfirmPizzaEventDialog> {
late final DateTime minTime;
@override
void initState() async {
void initState() {
super.initState();
var currentDuration = await widget.pizzaRecipe.getCurrentDuration();
eventTime = DateTime.now().add(currentDuration).add(Duration(minutes: 1));
minTime = DateTime.now().add(currentDuration);
eventTime = DateTime.now().add(widget.pizzaRecipe.getCurrentDuration()).add(Duration(minutes: 1));
minTime = DateTime.now().add(widget.pizzaRecipe.getCurrentDuration());
}
@override
@ -261,7 +255,7 @@ class ConfirmPizzaEventState extends State<ConfirmPizzaEventDialog> {
Text(widget.name),
Divider(),
Text("Ingredients"),
//widget.pizzaRecipe.getIngredientsTable(widget.pizzaCount, widget.doughBallSize),
widget.pizzaRecipe.getIngredientsTable(widget.pizzaCount, widget.doughBallSize),
Divider(),
SizedBox(
width: double.infinity,
@ -299,7 +293,7 @@ class ConfirmPizzaEventState extends State<ConfirmPizzaEventDialog> {
flex: 60,
child: ListView(
children: <Widget>[
//widget.pizzaRecipe.getStepTimeTable(eventTime)
widget.pizzaRecipe.getStepTimeTable(eventTime)
]
)
),

View file

@ -21,14 +21,14 @@ class PizzaEventsState extends State<PizzaEventsPage> {
body: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: pizzaEvents.length,
itemBuilder: (BuildContext context, int i) => const Divider(),// PizzaEventWidget(pizzaEvents[i]),
itemBuilder: (BuildContext context, int i) => PizzaEventWidget(pizzaEvents[i]),
separatorBuilder: (BuildContext context, int i) => const Divider(),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final dynamic newPizzaEvent = await Navigator.pushNamed(
context,
"/pickRecipe",
"/add",
);
if (newPizzaEvent != null){

View file

@ -2,28 +2,20 @@ import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
import 'package:intl/intl.dart';
import 'package:pizzaplanner/entities/PizzaDatabase.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
Future<List<PizzaRecipe>> loadYamlRecipesIntoDb() async {
// load recipes from yaml files in the asset directory
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> newPizzaRecipes = [];
final List<PizzaRecipe> pizzaRecipes = [];
for (var filePath in fileList) {
if (filePath.startsWith("assets/recipes") && filePath.endsWith(".yaml")) {
var parsedPizzaRecipe = await PizzaRecipe.fromYaml(filePath);
await parsedPizzaRecipe.item1.insert();
newPizzaRecipes.add(parsedPizzaRecipe.item1);
print(parsedPizzaRecipe.item1.name);
parsedPizzaRecipe.item2.forEach((ingredient) async { await ingredient.insert(); });
parsedPizzaRecipe.item3.forEach((recipeStep) async { await recipeStep.insert(); });
parsedPizzaRecipe.item4.forEach((recipeSubStep) async { await recipeSubStep.insert(); });
print(parsedPizzaRecipe.item1.description);
PizzaRecipe pizzaRecipe = await PizzaRecipe.fromYaml(filePath);
pizzaRecipes.add(pizzaRecipe);
}
}
return newPizzaRecipes;
return pizzaRecipes;
}
Future<String> loadAsset(String path) async {
@ -38,8 +30,4 @@ extension StringExtensions on String {
DateFormat getDateFormat(){
return DateFormat("yyyy-MM-dd H:mm");
}
Future<PizzaDatabase> getDatabase() async {
return await $FloorPizzaDatabase.databaseBuilder("pizza.db").build();
}

View file

@ -1,13 +1,11 @@
import 'package:flutter/material.dart';
import 'package:pizzaplanner/entities/PizzaEvent.dart';
import 'package:pizzaplanner/entities/PizzaRecipe/PizzaRecipe.dart';
import 'package:pizzaplanner/util.dart';
class PizzaEventWidget extends StatelessWidget {
final PizzaEvent pizzaEvent;
final PizzaRecipe pizzaRecipe;
PizzaEventWidget(this.pizzaEvent, this.pizzaRecipe);
PizzaEventWidget(this.pizzaEvent);
@override
Widget build(BuildContext context){
@ -71,7 +69,7 @@ class PizzaEventWidget extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(getDateFormat().format(pizzaEvent.dateTime)),
Text(pizzaRecipe.name)
Text(pizzaEvent.recipe.name)
],
),

View file

@ -1,37 +0,0 @@
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 Container(
height: 120,
color: Colors.blueAccent,
child: Container(
padding: const EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(pizzaRecipe.name),
]
),
Text(pizzaRecipe.description),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("${pizzaRecipe.getMinDuration().inHours.round()} to ${pizzaRecipe.getMaxDuration().inHours.round()} hours")
]
)
]
)
)
);
}
}

View file

@ -35,16 +35,10 @@ dependencies:
ref: "df4ed6fc2e24725604e90f79aedb98a7af7fb04d"
yaml: ^3.1.0
floor: ^1.1.0
tuple: ^2.0.0
dev_dependencies:
flutter_test:
sdk: flutter
floor_generator: ^1.1.0
build_runner: ^2.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec