added creating products
This commit is contained in:
		
							parent
							
								
									f6e1a08d06
								
							
						
					
					
						commit
						1f5c1ceaa7
					
				
					 4 changed files with 239 additions and 1 deletions
				
			
		| 
						 | 
					@ -219,4 +219,19 @@ class ApiClient {
 | 
				
			||||||
      "order": order,
 | 
					      "order": order,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<Map<String, dynamic>> addProduct({
 | 
				
			||||||
 | 
					    required String name,
 | 
				
			||||||
 | 
					    required double protein,
 | 
				
			||||||
 | 
					    required double carb,
 | 
				
			||||||
 | 
					    required double fat,
 | 
				
			||||||
 | 
					  }) async {
 | 
				
			||||||
 | 
					    var response = await post("/product", {
 | 
				
			||||||
 | 
					      "name": name,
 | 
				
			||||||
 | 
					      "protein": protein,
 | 
				
			||||||
 | 
					      "carb": carb,
 | 
				
			||||||
 | 
					      "fat": fat,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    return response;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ 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/models/meal.dart';
 | 
				
			||||||
import 'package:fooder_web/widgets/product.dart';
 | 
					import 'package:fooder_web/widgets/product.dart';
 | 
				
			||||||
 | 
					import 'package:fooder_web/screens/add_product.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddEntryScreen extends BasedScreen {
 | 
					class AddEntryScreen extends BasedScreen {
 | 
				
			||||||
| 
						 | 
					@ -132,6 +133,27 @@ class _AddEntryScreen extends State<AddEntryScreen> {
 | 
				
			||||||
                controller: productNameController,
 | 
					                controller: productNameController,
 | 
				
			||||||
                onChanged: (_) => _getProducts(),
 | 
					                onChanged: (_) => _getProducts(),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 | 
					              TextButton(
 | 
				
			||||||
 | 
					                onPressed: () {
 | 
				
			||||||
 | 
					                  Navigator.push(
 | 
				
			||||||
 | 
					                    context,
 | 
				
			||||||
 | 
					                    MaterialPageRoute(
 | 
				
			||||||
 | 
					                      builder: (context) => AddProductScreen(
 | 
				
			||||||
 | 
					                        apiClient: widget.apiClient,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ).then((product) {
 | 
				
			||||||
 | 
					                    if (product == null) {
 | 
				
			||||||
 | 
					                      return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    setState(() {
 | 
				
			||||||
 | 
					                      products = [product];
 | 
				
			||||||
 | 
					                      productNameController.text = product.name;
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                child: const Text("Don't see your product? Add it!"),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
              for (var product in products)
 | 
					              for (var product in products)
 | 
				
			||||||
                ListTile(
 | 
					                ListTile(
 | 
				
			||||||
                onTap: () {
 | 
					                onTap: () {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										180
									
								
								lib/screens/add_product.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								lib/screens/add_product.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,180 @@
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:fooder_web/screens/based.dart';
 | 
				
			||||||
 | 
					import 'package:fooder_web/models/product.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddProductScreen extends BasedScreen {
 | 
				
			||||||
 | 
					  const AddProductScreen({super.key, required super.apiClient});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<AddProductScreen> createState() => _AddProductScreen();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _AddProductScreen extends State<AddProductScreen> {
 | 
				
			||||||
 | 
					  final nameController = TextEditingController();
 | 
				
			||||||
 | 
					  final carbController = TextEditingController();
 | 
				
			||||||
 | 
					  final fatController = TextEditingController();
 | 
				
			||||||
 | 
					  final proteinController = TextEditingController();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void dispose() {
 | 
				
			||||||
 | 
					    nameController.dispose();
 | 
				
			||||||
 | 
					    carbController.dispose();
 | 
				
			||||||
 | 
					    fatController.dispose();
 | 
				
			||||||
 | 
					    proteinController.dispose();
 | 
				
			||||||
 | 
					    super.dispose();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void popMeDady(Product product) {
 | 
				
			||||||
 | 
					    Navigator.pop(
 | 
				
			||||||
 | 
					      context,
 | 
				
			||||||
 | 
					      product,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void showError(String message)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    ScaffoldMessenger.of(context).showSnackBar(
 | 
				
			||||||
 | 
					      SnackBar(
 | 
				
			||||||
 | 
					        content: Text(message, textAlign: TextAlign.center),
 | 
				
			||||||
 | 
					        backgroundColor: Theme.of(context).colorScheme.error,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> _addProduct() async {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      double.parse(carbController.text);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      showError("Carbs must be a number");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      double.parse(fatController.text);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      showError("Fat must be a number");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      double.parse(proteinController.text);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      showError("Protein must be a number");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      var productJson = await widget.apiClient.addProduct(
 | 
				
			||||||
 | 
					        carb: double.parse(carbController.text),
 | 
				
			||||||
 | 
					        fat: double.parse(fatController.text),
 | 
				
			||||||
 | 
					        protein: double.parse(proteinController.text),
 | 
				
			||||||
 | 
					        name: nameController.text,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      var product = Product.fromJson(productJson);
 | 
				
			||||||
 | 
					      popMeDady(product);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      showError("Error adding product, make sure there is no product with the same name");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double calculateCalories() {
 | 
				
			||||||
 | 
					    double calories = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      calories += double.parse(carbController.text) * 4;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      // ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      calories += double.parse(fatController.text) * 9;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      // ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      calories += double.parse(proteinController.text) * 4;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      // ignore
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return calories;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @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: Column(
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              TextFormField(
 | 
				
			||||||
 | 
					                decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                  labelText: 'Product name',
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                controller: nameController,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              TextFormField(
 | 
				
			||||||
 | 
					                decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                  labelText: 'Carbs',
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                keyboardType:const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
 | 
					                  FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                controller: carbController,
 | 
				
			||||||
 | 
					                onChanged: (String value) {
 | 
				
			||||||
 | 
					                  setState(() {});
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              TextFormField(
 | 
				
			||||||
 | 
					                decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                  labelText: 'Fat',
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                keyboardType:const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
 | 
					                  FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                controller: fatController,
 | 
				
			||||||
 | 
					                onChanged: (String value) {
 | 
				
			||||||
 | 
					                  setState(() {});
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              TextFormField(
 | 
				
			||||||
 | 
					                decoration: const InputDecoration(
 | 
				
			||||||
 | 
					                  labelText: 'Protein',
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                keyboardType:const TextInputType.numberWithOptions(decimal: true),
 | 
				
			||||||
 | 
					                inputFormatters: <TextInputFormatter>[
 | 
				
			||||||
 | 
					                  FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                controller: proteinController,
 | 
				
			||||||
 | 
					                onChanged: (String value) {
 | 
				
			||||||
 | 
					                  setState(() {});
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Text(
 | 
				
			||||||
 | 
					                "${calculateCalories()} kcal",
 | 
				
			||||||
 | 
					                textAlign: TextAlign.right,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      floatingActionButton: FloatingActionButton(
 | 
				
			||||||
 | 
					        onPressed: _addProduct,
 | 
				
			||||||
 | 
					        child: const Icon(Icons.add),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ 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';
 | 
					import 'package:fooder_web/screens/add_product.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EditEntryScreen extends BasedScreen {
 | 
					class EditEntryScreen extends BasedScreen {
 | 
				
			||||||
| 
						 | 
					@ -118,6 +118,27 @@ class _EditEntryScreen extends State<EditEntryScreen> {
 | 
				
			||||||
                controller: productNameController,
 | 
					                controller: productNameController,
 | 
				
			||||||
                onChanged: (_) => _getProducts(),
 | 
					                onChanged: (_) => _getProducts(),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 | 
					              TextButton(
 | 
				
			||||||
 | 
					                onPressed: () {
 | 
				
			||||||
 | 
					                  Navigator.push(
 | 
				
			||||||
 | 
					                    context,
 | 
				
			||||||
 | 
					                    MaterialPageRoute(
 | 
				
			||||||
 | 
					                      builder: (context) => AddProductScreen(
 | 
				
			||||||
 | 
					                        apiClient: widget.apiClient,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ).then((product) {
 | 
				
			||||||
 | 
					                    if (product == null) {
 | 
				
			||||||
 | 
					                      return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    setState(() {
 | 
				
			||||||
 | 
					                      products = [product];
 | 
				
			||||||
 | 
					                      productNameController.text = product.name;
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                child: const Text("Don't see your product? Add it!"),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
              for (var product in products)
 | 
					              for (var product in products)
 | 
				
			||||||
                ListTile(
 | 
					                ListTile(
 | 
				
			||||||
                onTap: () {
 | 
					                onTap: () {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue