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,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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/meal.dart';
 | 
			
		||||
import 'package:fooder_web/widgets/product.dart';
 | 
			
		||||
import 'package:fooder_web/screens/add_product.dart';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AddEntryScreen extends BasedScreen {
 | 
			
		||||
| 
						 | 
				
			
			@ -132,6 +133,27 @@ class _AddEntryScreen extends State<AddEntryScreen> {
 | 
			
		|||
                controller: productNameController,
 | 
			
		||||
                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)
 | 
			
		||||
                ListTile(
 | 
			
		||||
                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/entry.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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +118,27 @@ class _EditEntryScreen extends State<EditEntryScreen> {
 | 
			
		|||
                controller: productNameController,
 | 
			
		||||
                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)
 | 
			
		||||
                ListTile(
 | 
			
		||||
                onTap: () {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue