added meal handling

This commit is contained in:
doman 2023-07-30 14:40:45 +02:00
parent 18bad804b7
commit dff45b0ec4
8 changed files with 168 additions and 12 deletions

View file

@ -211,4 +211,12 @@ class ApiClient {
throw Exception("Failed to register"); throw Exception("Failed to register");
} }
} }
Future<void> addMeal({required String name, required int diaryId, required int order}) async {
await post("/meal", {
"name": name,
"diary_id": diaryId,
"order": order,
});
}
} }

View file

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fooder_web/screens/based.dart'; import 'package:fooder_web/screens/based.dart';
import 'package:fooder_web/models/product.dart'; import 'package:fooder_web/models/product.dart';
import 'package:fooder_web/models/diary.dart'; import 'package:fooder_web/models/diary.dart';
import 'package:fooder_web/models/meal.dart';
import 'package:fooder_web/widgets/product.dart'; import 'package:fooder_web/widgets/product.dart';
@ -18,6 +20,7 @@ class AddEntryScreen extends BasedScreen {
class _AddEntryScreen extends State<AddEntryScreen> { class _AddEntryScreen extends State<AddEntryScreen> {
final gramsController = TextEditingController(); final gramsController = TextEditingController();
final productNameController = TextEditingController(); final productNameController = TextEditingController();
Meal? meal;
List<Product> products = []; List<Product> products = [];
@override @override
@ -36,6 +39,9 @@ class _AddEntryScreen extends State<AddEntryScreen> {
@override @override
void initState () { void initState () {
super.initState(); super.initState();
setState(() {
meal = widget.diary.meals[0];
});
_getProducts().then((value) => null); _getProducts().then((value) => null);
} }
@ -90,10 +96,33 @@ class _AddEntryScreen extends State<AddEntryScreen> {
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: ListView( child: ListView(
children: <Widget>[ children: <Widget>[
DropdownButton<Meal>(
value: meal,
// Callback that sets the selected popup menu item.
onChanged: (Meal? meal) {
if (meal == null) {
return;
}
setState(() {
this.meal = meal;
});
},
items: <DropdownMenuItem<Meal>>[
for (var meal in widget.diary.meals)
DropdownMenuItem<Meal>(
value: meal,
child: Text(meal.name),
),
],
),
TextFormField( TextFormField(
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Grams', labelText: 'Grams',
), ),
keyboardType:const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
],
controller: gramsController, controller: gramsController,
), ),
TextFormField( TextFormField(
@ -108,6 +137,7 @@ class _AddEntryScreen extends State<AddEntryScreen> {
onTap: () { onTap: () {
setState(() { setState(() {
products = [product]; products = [product];
productNameController.text = product.name;
}); });
}, },
title: ProductWidget( title: ProductWidget(

75
lib/screens/add_meal.dart Normal file
View file

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:fooder_web/screens/based.dart';
import 'package:fooder_web/models/diary.dart';
class AddMealScreen extends BasedScreen {
final Diary diary;
const AddMealScreen({super.key, required super.apiClient, required this.diary});
@override
State<AddMealScreen> createState() => _AddMealScreen();
}
class _AddMealScreen extends State<AddMealScreen> {
final nameController = TextEditingController();
@override
void dispose() {
nameController.dispose();
super.dispose();
}
void popMeDady() {
Navigator.pop(
context,
);
}
void showError(String message)
{
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message, textAlign: TextAlign.center),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
}
Future<void> _addMeal() async {
await widget.apiClient.addMeal(
name: nameController.text,
diaryId: widget.diary.id,
order: widget.diary.meals.length,
);
popMeDady();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text("🅵🅾🅾🅳🅴🆁"),
),
body: Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 720),
padding: const EdgeInsets.all(10),
child: TextFormField(
decoration: const InputDecoration(
labelText: 'Meal name',
),
controller: nameController,
),
)
),
floatingActionButton: FloatingActionButton(
onPressed: _addMeal,
child: const Icon(Icons.add),
),
);
}
}

View file

@ -1,8 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fooder_web/screens/based.dart'; import 'package:fooder_web/screens/based.dart';
import 'package:fooder_web/models/product.dart'; import 'package:fooder_web/models/product.dart';
import 'package:fooder_web/models/entry.dart'; import 'package:fooder_web/models/entry.dart';
import 'package:fooder_web/widgets/product.dart'; import 'package:fooder_web/widgets/product.dart';
import 'package:fooder_web/models/meal.dart';
class EditEntryScreen extends BasedScreen { class EditEntryScreen extends BasedScreen {
@ -20,6 +22,7 @@ class _EditEntryScreen extends State<EditEntryScreen> {
final productNameController = TextEditingController(); final productNameController = TextEditingController();
List<Product> products = []; List<Product> products = [];
@override @override
void dispose() { void dispose() {
gramsController.dispose(); gramsController.dispose();
@ -102,6 +105,10 @@ class _EditEntryScreen extends State<EditEntryScreen> {
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Grams', labelText: 'Grams',
), ),
keyboardType:const TextInputType.numberWithOptions(decimal: true),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
],
controller: gramsController, controller: gramsController,
), ),
TextFormField( TextFormField(
@ -116,6 +123,7 @@ class _EditEntryScreen extends State<EditEntryScreen> {
onTap: () { onTap: () {
setState(() { setState(() {
products = [product]; products = [product];
productNameController.text = product.name;
}); });
}, },
title: ProductWidget( title: ProductWidget(

View file

@ -91,7 +91,7 @@ class _LoginScreen extends State<LoginScreen> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text("FOODER"), title: const Text("🅵🅾🅾🅳🅴🆁"),
), ),
body: Center( body: Center(
child: Container( child: Container(

View file

@ -71,7 +71,7 @@ class _RegisterScreen extends State<RegisterScreen> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text("FOODER"), title: const Text("🅵🅾🅾🅳🅴🆁"),
), ),
body: Center( body: Center(
child: Container( child: Container(

View file

@ -3,6 +3,7 @@ import 'package:fooder_web/models/diary.dart';
import 'package:fooder_web/widgets/meal.dart'; import 'package:fooder_web/widgets/meal.dart';
import 'package:fooder_web/widgets/macro.dart'; import 'package:fooder_web/widgets/macro.dart';
import 'package:fooder_web/client.dart'; import 'package:fooder_web/client.dart';
import 'package:fooder_web/screens/add_meal.dart';
import 'dart:core'; import 'dart:core';
@ -21,8 +22,9 @@ class DiaryWidget extends StatelessWidget {
slivers: <Widget>[ slivers: <Widget>[
SliverAppBar( SliverAppBar(
title: Row( title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
const Spacer(), Spacer(),
Text( Text(
"${diary.calories.toStringAsFixed(1)} kcal", "${diary.calories.toStringAsFixed(1)} kcal",
style: Theme.of(context).textTheme.headlineLarge!.copyWith( style: Theme.of(context).textTheme.headlineLarge!.copyWith(
@ -40,16 +42,38 @@ class DiaryWidget extends StatelessWidget {
floating: true, floating: true,
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(
title: MacroWidget( title: MacroWidget(
protein: diary.protein, protein: diary.protein,
carb: diary.carb, carb: diary.carb,
fat: diary.fat, fat: diary.fat,
style: Theme.of(context).textTheme.bodyMedium!.copyWith( style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onSecondary, color: Theme.of(context).colorScheme.onSecondary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
),
child: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddMealScreen(
apiClient: apiClient,
diary: diary,
),
),
).then((_) {
refreshParent();
});
},
child: Text(
"Add meal",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onSecondary,
fontWeight: FontWeight.bold,
),
),
),
), ),
), )
), ),
),
SliverList( SliverList(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(
[ [

View file

@ -8,11 +8,13 @@ class MacroWidget extends StatelessWidget {
final double carb; final double carb;
final double fat; final double fat;
final TextStyle style; final TextStyle style;
final Widget? child;
const MacroWidget({ const MacroWidget({
Key? key, Key? key,
this.calories, this.calories,
this.amount, this.amount,
this.child,
required this.protein, required this.protein,
required this.carb, required this.carb,
required this.fat, required this.fat,
@ -74,7 +76,16 @@ class MacroWidget extends StatelessWidget {
); );
} }
if (amount == null && calories == null) { if (child != null) {
elements.add(
Expanded(
flex: 1,
child: child!,
),
);
}
if (amount == null && calories == null && child == null) {
elements.add( elements.add(
Expanded( Expanded(
flex: 1, flex: 1,