moved to a wrapped scaffold, to get some consistency and one place to add the nav drawer
This commit is contained in:
parent
44cedd1a29
commit
af0be6fe8b
10 changed files with 577 additions and 580 deletions
|
@ -7,6 +7,7 @@ import 'package:fluttericon/font_awesome5_icons.dart';
|
||||||
import 'package:pizzaplanner/entities/pizza_event.dart';
|
import 'package:pizzaplanner/entities/pizza_event.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
||||||
import 'package:pizzaplanner/main.dart';
|
import 'package:pizzaplanner/main.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:pizzaplanner/util.dart';
|
import 'package:pizzaplanner/util.dart';
|
||||||
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -31,178 +32,172 @@ class AddPizzaEventPageState extends State<AddPizzaEventPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
title: const Text("Add Pizza Event"),
|
||||||
title: const Text("Add Pizza Event"),
|
body: Column(
|
||||||
),
|
children: <Widget>[
|
||||||
resizeToAvoidBottomInset: false,
|
Expanded(
|
||||||
body: Container(
|
flex: 40,
|
||||||
padding: const EdgeInsets.all(16),
|
child: Column(
|
||||||
child: Column(
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Row(
|
||||||
Expanded(
|
children: <Widget>[
|
||||||
flex: 40,
|
const Icon(Icons.title),
|
||||||
child: Column(
|
Container(width: 25),
|
||||||
children: <Widget>[
|
Expanded(
|
||||||
Row(
|
child: TextField(
|
||||||
children: <Widget>[
|
decoration: InputDecoration(
|
||||||
const Icon(Icons.title),
|
hintText: "Event Name",
|
||||||
Container(width: 25),
|
errorText: nameValidation ? """Name can't be empty""" : null
|
||||||
Expanded(
|
),
|
||||||
child: TextField(
|
onChanged: (String newName) {
|
||||||
decoration: InputDecoration(
|
setState(() {
|
||||||
hintText: "Event Name",
|
name = newName;
|
||||||
errorText: nameValidation ? """Name can't be empty""" : null
|
});
|
||||||
),
|
},
|
||||||
onChanged: (String newName) {
|
),
|
||||||
setState(() {
|
)
|
||||||
name = newName;
|
]
|
||||||
});
|
),
|
||||||
},
|
Row(
|
||||||
),
|
children: <Widget>[
|
||||||
)
|
const Icon(FontAwesome5.hashtag),
|
||||||
]
|
Expanded(
|
||||||
),
|
child: Slider(
|
||||||
Row(
|
|
||||||
children: <Widget>[
|
|
||||||
const Icon(FontAwesome5.hashtag),
|
|
||||||
Expanded(
|
|
||||||
child: Slider(
|
|
||||||
|
|
||||||
value: pizzaCount.toDouble(),
|
value: pizzaCount.toDouble(),
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 20,
|
max: 20,
|
||||||
divisions: 19,
|
divisions: 19,
|
||||||
label: pizzaCount.toString(),
|
label: pizzaCount.toString(),
|
||||||
onChanged: (double newPizzaCount) {
|
onChanged: (double newPizzaCount) {
|
||||||
setState(() {pizzaCount = newPizzaCount.round();});
|
setState(() {pizzaCount = newPizzaCount.round();});
|
||||||
},
|
},
|
||||||
)
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 25,
|
|
||||||
child: Text(pizzaCount.toString())
|
|
||||||
)
|
)
|
||||||
]
|
),
|
||||||
),
|
SizedBox(
|
||||||
Row(
|
width: 25,
|
||||||
children: <Widget>[
|
child: Text(pizzaCount.toString())
|
||||||
const Icon(FontAwesome5.weight_hanging),
|
)
|
||||||
Expanded(
|
]
|
||||||
child: Slider(
|
),
|
||||||
value: doughBallSize.toDouble(),
|
Row(
|
||||||
min: 100,
|
children: <Widget>[
|
||||||
max: 400,
|
const Icon(FontAwesome5.weight_hanging),
|
||||||
divisions: 30,
|
Expanded(
|
||||||
label: doughBallSize.toString(),
|
child: Slider(
|
||||||
onChanged: (double newDoughBallSize) {
|
value: doughBallSize.toDouble(),
|
||||||
setState(() {doughBallSize = newDoughBallSize.round();});
|
min: 100,
|
||||||
},
|
max: 400,
|
||||||
)
|
divisions: 30,
|
||||||
),
|
label: doughBallSize.toString(),
|
||||||
SizedBox(
|
onChanged: (double newDoughBallSize) {
|
||||||
width: 25,
|
setState(() {doughBallSize = newDoughBallSize.round();});
|
||||||
child: Text(doughBallSize.toString())
|
},
|
||||||
)
|
)
|
||||||
]
|
),
|
||||||
),
|
SizedBox(
|
||||||
widget.pizzaRecipe.getIngredientsTable(pizzaCount, doughBallSize),
|
width: 25,
|
||||||
]
|
child: Text(doughBallSize.toString())
|
||||||
)
|
)
|
||||||
),
|
]
|
||||||
const Divider(),
|
),
|
||||||
Expanded(
|
widget.pizzaRecipe.getIngredientsTable(pizzaCount, doughBallSize),
|
||||||
flex: 45,
|
]
|
||||||
child: ListView(
|
)
|
||||||
children: <Widget>[
|
),
|
||||||
Column(
|
const Divider(),
|
||||||
children: widget.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.isNotEmpty).map((recipeStep) {
|
Expanded(
|
||||||
return <Widget>[
|
flex: 45,
|
||||||
Text(recipeStep.waitDescription),
|
child: ListView(
|
||||||
Row(
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Column(
|
||||||
Expanded(
|
children: widget.pizzaRecipe.recipeSteps.where((recipeStep) => recipeStep.waitDescription.isNotEmpty).map((recipeStep) {
|
||||||
child: Slider(
|
return <Widget>[
|
||||||
value: recipeStep.waitValue!.toDouble(),
|
Text(recipeStep.waitDescription),
|
||||||
min: recipeStep.waitMin.toDouble(),
|
Row(
|
||||||
max: recipeStep.waitMax.toDouble(),
|
children: <Widget>[
|
||||||
divisions: recipeStep.waitMax - recipeStep.waitMin,
|
Expanded(
|
||||||
label: recipeStep.waitValue.toString(),
|
child: Slider(
|
||||||
onChanged: (newValue) => setState(() => recipeStep.waitValue = newValue.toInt()),
|
value: recipeStep.waitValue!.toDouble(),
|
||||||
)
|
min: recipeStep.waitMin.toDouble(),
|
||||||
),
|
max: recipeStep.waitMax.toDouble(),
|
||||||
SizedBox(
|
divisions: recipeStep.waitMax - recipeStep.waitMin,
|
||||||
width: 25,
|
label: recipeStep.waitValue.toString(),
|
||||||
child: Text(recipeStep.waitValue.toString())
|
onChanged: (newValue) => setState(() => recipeStep.waitValue = newValue.toInt()),
|
||||||
)
|
)
|
||||||
]
|
),
|
||||||
)
|
SizedBox(
|
||||||
];
|
width: 25,
|
||||||
}).expand((option) => option).toList()
|
child: Text(recipeStep.waitValue.toString())
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
];
|
||||||
const Divider(),
|
}).expand((option) => option).toList()
|
||||||
const Spacer(),
|
)
|
||||||
SizedBox(
|
]
|
||||||
width: double.infinity,
|
)
|
||||||
height: 70,
|
),
|
||||||
child: Container(
|
const Divider(),
|
||||||
color: Colors.blue,
|
const Spacer(),
|
||||||
child: TextButton(
|
SizedBox(
|
||||||
onPressed: () async {
|
width: double.infinity,
|
||||||
|
height: 70,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.blue,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
|
||||||
if (name.isEmpty){
|
if (name.isEmpty){
|
||||||
setState(() { nameValidation = true; });
|
setState(() { nameValidation = true; });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(() { nameValidation = false; });
|
setState(() { nameValidation = false; });
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
DateTime? eventTime = await showDialog(
|
DateTime? eventTime = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return ConfirmPizzaEventDialog(name: name, pizzaRecipe: widget.pizzaRecipe, pizzaCount: pizzaCount, doughBallSize: doughBallSize);
|
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 (eventTime == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final pizzaEventsBox = Hive.box<PizzaEvent>("PizzaEvents");
|
// if the user waited to long on the confirmation dialog that the first step time is now in the past
|
||||||
final PizzaEvent pizzaEvent = PizzaEvent(
|
final durationUntilFirstStep = Duration(seconds: widget.pizzaRecipe.getCurrentDuration().inSeconds);
|
||||||
name,
|
final firstStepDateTime = eventTime.subtract(durationUntilFirstStep);
|
||||||
widget.pizzaRecipe,
|
if (firstStepDateTime.isBefore(DateTime.now())){
|
||||||
pizzaCount,
|
eventTime = DateTime.now()
|
||||||
doughBallSize,
|
.add(durationUntilFirstStep)
|
||||||
eventTime
|
.add(const Duration(minutes: 1));
|
||||||
);
|
}
|
||||||
await pizzaEventsBox.add(pizzaEvent);
|
|
||||||
|
|
||||||
pizzaEvent.createPizzaEventNotifications();
|
final pizzaEventsBox = Hive.box<PizzaEvent>("PizzaEvents");
|
||||||
|
final PizzaEvent pizzaEvent = PizzaEvent(
|
||||||
if(!mounted) {
|
name,
|
||||||
return; //https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
|
widget.pizzaRecipe,
|
||||||
}
|
pizzaCount,
|
||||||
Navigator.of(context).pop();
|
doughBallSize,
|
||||||
Navigator.of(context).pop(); // two times because of the pick recipe page
|
eventTime
|
||||||
},
|
);
|
||||||
child: const Text("Review", style: TextStyle(color: Colors.white)),
|
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)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
]
|
)
|
||||||
)
|
]
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/ingredient.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/ingredient.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class AddRecipePage extends StatefulWidget {
|
class AddRecipePage extends StatefulWidget {
|
||||||
|
@ -34,107 +35,101 @@ class AddRecipePageState extends State<AddRecipePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context){
|
Widget build(BuildContext context){
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
title: const Text("Add Recipe"),
|
||||||
title: const Text("Add Pizza Recipe"),
|
body: ListView(
|
||||||
),
|
children: <Widget>[
|
||||||
resizeToAvoidBottomInset: false,
|
TextField(
|
||||||
body: Container(
|
decoration: InputDecoration(
|
||||||
padding: const EdgeInsets.all(16),
|
hintText: "Recipe Name",
|
||||||
child: ListView(
|
errorText: nameValidation ? """Name can't be empty""" : null
|
||||||
children: <Widget>[
|
|
||||||
TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "Recipe Name",
|
|
||||||
errorText: nameValidation ? """Name can't be empty""" : null
|
|
||||||
),
|
|
||||||
onChanged: (String newName) {
|
|
||||||
setState(() {
|
|
||||||
pizzaRecipe.name = newName;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
onChanged: (String newName) {
|
||||||
TextField(
|
setState(() {
|
||||||
decoration: InputDecoration(
|
pizzaRecipe.name = newName;
|
||||||
hintText: "Recipe Description",
|
});
|
||||||
errorText: nameValidation ? """Description can't be empty""" : null
|
},
|
||||||
),
|
),
|
||||||
maxLines: 8,
|
const Divider(),
|
||||||
onChanged: (String newDescription) {
|
TextField(
|
||||||
setState(() {
|
decoration: InputDecoration(
|
||||||
pizzaRecipe.description = newDescription;
|
hintText: "Recipe Description",
|
||||||
});
|
errorText: nameValidation ? """Description can't be empty""" : null
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
maxLines: 8,
|
||||||
Row(
|
onChanged: (String newDescription) {
|
||||||
children: <Widget>[
|
setState(() {
|
||||||
Expanded(
|
pizzaRecipe.description = newDescription;
|
||||||
flex: 2,
|
});
|
||||||
child: Container(
|
},
|
||||||
color: Colors.blue,
|
),
|
||||||
width: double.infinity,
|
const Divider(),
|
||||||
child: TextButton(
|
Row(
|
||||||
onPressed: () {
|
children: <Widget>[
|
||||||
showDialog(
|
Expanded(
|
||||||
context: context,
|
flex: 2,
|
||||||
builder: (context) {
|
child: Container(
|
||||||
return PreviewMarkdownDescription(pizzaRecipe.description);
|
color: Colors.blue,
|
||||||
}
|
width: double.infinity,
|
||||||
);
|
child: TextButton(
|
||||||
},
|
onPressed: () {
|
||||||
child: const Text("Preview", style: TextStyle(color: Colors.white)),
|
showDialog(
|
||||||
)
|
context: context,
|
||||||
)
|
builder: (context) {
|
||||||
),
|
return PreviewMarkdownDescription(pizzaRecipe.description);
|
||||||
const Expanded(
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text("Preview", style: TextStyle(color: Colors.white)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
child: SizedBox()
|
child: SizedBox()
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
launch("https://guides.github.com/features/mastering-markdown/");
|
launch("https://guides.github.com/features/mastering-markdown/");
|
||||||
},
|
},
|
||||||
child: const Text("Markdown?", style: TextStyle(color: Colors.white)),
|
child: const Text("Markdown?", style: TextStyle(color: Colors.white)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
const Center(
|
const Center(
|
||||||
child: Text("Ingredients")
|
child: Text("Ingredients")
|
||||||
|
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
Container(
|
Container(
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
pizzaRecipe.ingredients.add(
|
pizzaRecipe.ingredients.add(
|
||||||
Ingredient(
|
Ingredient(
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
0.0
|
0.0
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: const Text("Add Ingredient", style: TextStyle(color: Colors.white)),
|
child: const Text("Add Ingredient", style: TextStyle(color: Colors.white)),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
] + pizzaRecipe.ingredients.map((ingredient) => buildIngredientRow(ingredient)).toList() + [
|
] + pizzaRecipe.ingredients.map((ingredient) => buildIngredientRow(ingredient)).toList() + [
|
||||||
|
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,42 +2,36 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
||||||
import 'package:pizzaplanner/pages/nav_drawer.dart';
|
import 'package:pizzaplanner/pages/nav_drawer.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
||||||
|
|
||||||
class PickPizzaRecipePage extends StatelessWidget {
|
class PickPizzaRecipePage extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context){
|
Widget build(BuildContext context){
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
drawer: NavDrawer(),
|
title: const Text("Pick Recipe"),
|
||||||
appBar: AppBar(
|
body: ValueListenableBuilder(
|
||||||
title: const Text("Pick Pizza Recipe"),
|
valueListenable: Hive.box<PizzaRecipe>("PizzaRecipes").listenable(),
|
||||||
),
|
builder: (context, Box<PizzaRecipe> pizzaRecipesBox, widget) {
|
||||||
resizeToAvoidBottomInset: false,
|
return ListView.separated(
|
||||||
body: Container(
|
padding: const EdgeInsets.all(8),
|
||||||
padding: const EdgeInsets.all(16),
|
itemCount: pizzaRecipesBox.length,
|
||||||
child: ValueListenableBuilder(
|
itemBuilder: (context, i) {
|
||||||
valueListenable: Hive.box<PizzaRecipe>("PizzaRecipes").listenable(),
|
final pizzaRecipe = pizzaRecipesBox.get(i);
|
||||||
builder: (context, Box<PizzaRecipe> pizzaRecipesBox, widget) {
|
if (pizzaRecipe == null){
|
||||||
return ListView.separated(
|
return const SizedBox();
|
||||||
padding: const EdgeInsets.all(8),
|
}
|
||||||
itemCount: pizzaRecipesBox.length,
|
return InkWell(
|
||||||
itemBuilder: (context, i) {
|
onTap: () {
|
||||||
final pizzaRecipe = pizzaRecipesBox.get(i);
|
Navigator.pushNamed(context, "/event/add", arguments: pizzaRecipe);
|
||||||
if (pizzaRecipe == null){
|
},
|
||||||
return const SizedBox();
|
child: PizzaRecipeWidget(pizzaRecipe),
|
||||||
}
|
);
|
||||||
return InkWell(
|
},
|
||||||
onTap: () {
|
separatorBuilder: (BuildContext context, int i) => const Divider(),
|
||||||
Navigator.pushNamed(context, "/event/add", arguments: pizzaRecipe);
|
);
|
||||||
},
|
}
|
||||||
child: PizzaRecipeWidget(pizzaRecipe),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
separatorBuilder: (BuildContext context, int i) => const Divider(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ import 'package:pizzaplanner/entities/pizza_event.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
||||||
import 'package:pizzaplanner/main.dart';
|
import 'package:pizzaplanner/main.dart';
|
||||||
import 'package:pizzaplanner/pages/recipe_step_instruction_page.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:timezone/timezone.dart' as tz;
|
||||||
import 'package:vibration/vibration.dart';
|
import 'package:vibration/vibration.dart';
|
||||||
|
@ -56,98 +57,92 @@ class PizzaEventNotificationState extends State<PizzaEventNotificationPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
title: Text(recipeStep.name),
|
||||||
title: const Text("From notification"),
|
body: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
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: <Widget>[
|
|
||||||
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)),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_step.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart';
|
||||||
import 'package:pizzaplanner/main.dart';
|
import 'package:pizzaplanner/main.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:pizzaplanner/util.dart';
|
import 'package:pizzaplanner/util.dart';
|
||||||
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
@ -26,35 +27,30 @@ class PizzaEventPageState extends State<PizzaEventPage> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final recipeStepCount = widget.pizzaEvent.recipe.recipeSteps.length;
|
final recipeStepCount = widget.pizzaEvent.recipe.recipeSteps.length;
|
||||||
final completedRecipeStepCount = widget.pizzaEvent.recipe.recipeSteps.where((recipeStep) => recipeStep.completed).length;
|
final completedRecipeStepCount = widget.pizzaEvent.recipe.recipeSteps.where((recipeStep) => recipeStep.completed).length;
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
title: Text(widget.pizzaEvent.name),
|
||||||
title: Text(widget.pizzaEvent.name),
|
body: Column(
|
||||||
),
|
children: <Widget>[
|
||||||
resizeToAvoidBottomInset: false,
|
Expanded(
|
||||||
body: Container(
|
flex: 15,
|
||||||
padding: const EdgeInsets.all(16),
|
child: Column(
|
||||||
child: Column(
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Text(widget.pizzaEvent.name),
|
||||||
Expanded(
|
Text(getTimeRemainingString(widget.pizzaEvent.dateTime)),
|
||||||
flex: 15,
|
Container(
|
||||||
child: Column(
|
color: Colors.blue,
|
||||||
children: <Widget>[
|
child: TextButton(
|
||||||
Text(widget.pizzaEvent.name),
|
onPressed: () {
|
||||||
Text(getTimeRemainingString(widget.pizzaEvent.dateTime)),
|
Navigator.pushNamed(context, "/recipe/view", arguments: widget.pizzaEvent.recipe);
|
||||||
Container(
|
},
|
||||||
color: Colors.blue,
|
child: Text(widget.pizzaEvent.recipe.name, style: const TextStyle(color: Colors.white)),
|
||||||
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,
|
flex: 80,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -78,28 +74,27 @@ class PizzaEventPageState extends State<PizzaEventPage> {
|
||||||
] + widget.pizzaEvent.recipe.ingredients.map((ingredient) => buildIngredientWidget(ingredient)).toList(),
|
] + widget.pizzaEvent.recipe.ingredients.map((ingredient) => buildIngredientWidget(ingredient)).toList(),
|
||||||
),
|
),
|
||||||
Table(
|
Table(
|
||||||
columnWidths: const <int, TableColumnWidth>{
|
columnWidths: const <int, TableColumnWidth>{
|
||||||
0: FlexColumnWidth(4),
|
0: FlexColumnWidth(4),
|
||||||
1: FlexColumnWidth(3),
|
1: FlexColumnWidth(3),
|
||||||
2: FlexColumnWidth(),
|
2: FlexColumnWidth(),
|
||||||
},
|
},
|
||||||
children: <TableRow>[
|
children: <TableRow>[
|
||||||
TableRow(
|
TableRow(
|
||||||
children: <TableCell>[
|
children: <TableCell>[
|
||||||
const TableCell(child: Text("Recipe Step")),
|
const TableCell(child: Text("Recipe Step")),
|
||||||
const TableCell(child: Text("When")),
|
const TableCell(child: Text("When")),
|
||||||
TableCell(child: Text("$completedRecipeStepCount/$recipeStepCount")),
|
TableCell(child: Text("$completedRecipeStepCount/$recipeStepCount")),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
] + widget.pizzaEvent.recipe.recipeSteps.map((recipeStep) => buildRecipeStepWhenWidget(recipeStep)).toList()
|
] + widget.pizzaEvent.recipe.recipeSteps.map((recipeStep) => buildRecipeStepWhenWidget(recipeStep)).toList()
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pizzaplanner/entities/pizza_event.dart';
|
import 'package:pizzaplanner/entities/pizza_event.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:pizzaplanner/widgets/pizza_event_widget.dart';
|
import 'package:pizzaplanner/widgets/pizza_event_widget.dart';
|
||||||
|
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -17,47 +18,42 @@ class PizzaEventsState extends State<PizzaEventsPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
title: const Text("Pizza Events"),
|
||||||
title: const Text("Pizza Events"),
|
body: ValueListenableBuilder(
|
||||||
),
|
valueListenable: Hive.box<PizzaEvent>("PizzaEvents").listenable(),
|
||||||
body: Container(
|
builder: (context, Box<PizzaEvent> box, widget) {
|
||||||
padding: const EdgeInsets.all(16),
|
if (box.isEmpty){
|
||||||
child: ValueListenableBuilder(
|
return Container();
|
||||||
valueListenable: Hive.box<PizzaEvent>("PizzaEvents").listenable(),
|
|
||||||
builder: (context, Box<PizzaEvent> 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 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(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final dynamic newPizzaEvent = await Navigator.pushNamed(
|
final dynamic newPizzaEvent = await Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
"/event/pick_recipe",
|
"/event/pick_recipe",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newPizzaEvent != null){
|
if (newPizzaEvent != null){
|
||||||
addPizzaEvent(newPizzaEvent as PizzaEvent);
|
addPizzaEvent(newPizzaEvent as PizzaEvent);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tooltip: "Add Pizza Plans",
|
tooltip: "Add Pizza Plans",
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Icon(Icons.add),
|
Icon(Icons.add),
|
||||||
Icon(Icons.local_pizza_rounded),
|
Icon(Icons.local_pizza_rounded),
|
||||||
]
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
||||||
import 'package:pizzaplanner/entities/pizza_event.dart';
|
import 'package:pizzaplanner/entities/pizza_event.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class RecipePage extends StatefulWidget {
|
class RecipePage extends StatefulWidget {
|
||||||
|
@ -41,38 +42,35 @@ class RecipePageState extends State<RecipePage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(widget.pizzaRecipe.name),
|
title: Text(widget.pizzaRecipe.name),
|
||||||
),
|
body: Column(
|
||||||
resizeToAvoidBottomInset: false,
|
children: <Widget>[
|
||||||
body: Column(
|
Expanded(
|
||||||
children: <Widget>[
|
flex: 95,
|
||||||
Expanded(
|
child: PageView(
|
||||||
flex: 95,
|
onPageChanged: (newPage) => setState(() {page = newPage;}),
|
||||||
child: PageView(
|
controller: controller,
|
||||||
onPageChanged: (newPage) => setState(() {page = newPage;}),
|
children: <Widget>[
|
||||||
controller: controller,
|
Markdown(
|
||||||
children: <Widget>[
|
data: widget.pizzaRecipe.description,
|
||||||
Markdown(
|
onTapLink: (text, url, title) {
|
||||||
data: widget.pizzaRecipe.description,
|
launch(url!);
|
||||||
onTapLink: (text, url, title) {
|
},
|
||||||
launch(url!);
|
),
|
||||||
},
|
] + widget.pizzaRecipe.recipeSteps.map((recipeStep) => buildRecipeStep(recipeStep)).toList()
|
||||||
),
|
)
|
||||||
] + widget.pizzaRecipe.recipeSteps.map((recipeStep) => buildRecipeStep(recipeStep)).toList()
|
),
|
||||||
)
|
Expanded(
|
||||||
),
|
flex: 5,
|
||||||
Expanded(
|
child: Row(
|
||||||
flex: 5,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
child: Row(
|
children: pageIndex
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
)
|
||||||
children: pageIndex
|
)
|
||||||
)
|
],
|
||||||
)
|
),
|
||||||
],
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:pizzaplanner/entities/PizzaRecipe/recipe_step.dart';
|
||||||
|
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/recipe_substep.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class RecipeStepInstructionPageArguments {
|
class RecipeStepInstructionPageArguments {
|
||||||
|
@ -49,41 +50,37 @@ class RecipeStepInstructionState extends State<RecipeStepInstructionPage> {
|
||||||
} else if (page > 0){
|
} else if (page > 0){
|
||||||
nextButtonText = "Next step";
|
nextButtonText = "Next step";
|
||||||
}
|
}
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
return PizzaPlannerScaffold(
|
||||||
title: Text(widget.recipeStep.name),
|
title: Text(widget.recipeStep.name),
|
||||||
),
|
body: Column(
|
||||||
resizeToAvoidBottomInset: false,
|
|
||||||
body: Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 90,
|
flex: 90,
|
||||||
child: PageView(
|
child: PageView(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
onPageChanged: (newPage) => setState(() {
|
onPageChanged: (newPage) => setState(() {
|
||||||
page = newPage;
|
page = newPage;
|
||||||
if (widget.recipeStep.subSteps.isNotEmpty && page != 0) {
|
if (widget.recipeStep.subSteps.isNotEmpty && page != 0) {
|
||||||
currentSubStep = widget.recipeStep.subSteps.elementAt(newPage-1);
|
currentSubStep = widget.recipeStep.subSteps.elementAt(newPage-1);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Markdown(
|
Markdown(
|
||||||
data: widget.recipeStep.description,
|
data: widget.recipeStep.description,
|
||||||
onTapLink: (text, url, title) {
|
onTapLink: (text, url, title) {
|
||||||
launch(url!);
|
launch(url!);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
] + widget.recipeStep.subSteps.map((subStep) {
|
] + widget.recipeStep.subSteps.map((subStep) {
|
||||||
return Markdown(
|
return Markdown(
|
||||||
data: subStep.description,
|
data: subStep.description,
|
||||||
onTapLink: (text, url, title) {
|
onTapLink: (text, url, title) {
|
||||||
launch(url!);
|
launch(url!);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}).toList()
|
}).toList()
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 10,
|
flex: 10,
|
||||||
|
@ -139,8 +136,7 @@ class RecipeStepInstructionState extends State<RecipeStepInstructionPage> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
),
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,63 +2,57 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
import 'package:pizzaplanner/entities/PizzaRecipe/pizza_recipe.dart';
|
||||||
import 'package:pizzaplanner/pages/nav_drawer.dart';
|
import 'package:pizzaplanner/pages/nav_drawer.dart';
|
||||||
|
import 'package:pizzaplanner/pages/scaffold.dart';
|
||||||
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
import 'package:pizzaplanner/widgets/pizza_recipe_widget.dart';
|
||||||
|
|
||||||
class RecipesPage extends StatelessWidget {
|
class RecipesPage extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context){
|
Widget build(BuildContext context){
|
||||||
return Scaffold(
|
return PizzaPlannerScaffold(
|
||||||
drawer: NavDrawer(),
|
title: const Text("Pizza Recipes"),
|
||||||
appBar: AppBar(
|
body: Column(
|
||||||
title: const Text("Recipes"),
|
children: <Widget>[
|
||||||
),
|
const Expanded(
|
||||||
resizeToAvoidBottomInset: false,
|
flex: 5,
|
||||||
body: Container(
|
child: Text("Search here maybe")
|
||||||
padding: const EdgeInsets.all(16),
|
),
|
||||||
child: Column(
|
Container(
|
||||||
children: <Widget>[
|
color: Colors.blue,
|
||||||
const Expanded(
|
width: double.infinity,
|
||||||
flex: 5,
|
child: TextButton(
|
||||||
child: Text("Search here maybe")
|
onPressed: () async {
|
||||||
),
|
Navigator.pushNamed(context, "/recipes/add");
|
||||||
Container(
|
},
|
||||||
color: Colors.blue,
|
child: const Text("New Recipe", style: TextStyle(color: Colors.white)),
|
||||||
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<PizzaRecipe>("PizzaRecipes").listenable(),
|
|
||||||
builder: (context, Box<PizzaRecipe> 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(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
]
|
),
|
||||||
)
|
const Divider(),
|
||||||
)
|
Expanded(
|
||||||
|
flex: 50,
|
||||||
|
child: ValueListenableBuilder(
|
||||||
|
valueListenable: Hive.box<PizzaRecipe>("PizzaRecipes").listenable(),
|
||||||
|
builder: (context, Box<PizzaRecipe> 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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
39
lib/pages/scaffold.dart
Normal file
39
lib/pages/scaffold.dart
Normal file
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue