import 'dart:developer'; import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:calorimeter/food_scan/food_fact_lookup.dart'; import 'package:calorimeter/utils/scan_food_floating_button.dart'; import 'package:calorimeter/utils/app_drawer.dart'; import 'package:calorimeter/food_entry/food_entry_bloc.dart'; import 'package:calorimeter/perdate/entry_list.dart'; import 'package:calorimeter/storage/storage.dart'; import 'package:calorimeter/utils/calendar_floating_button.dart'; import 'package:calorimeter/utils/rectangular_notch_shape.dart'; import 'package:calorimeter/utils/sum_widget.dart'; import 'package:calorimeter/utils/theme_switcher_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; class PerDateWidget extends StatefulWidget { final DateTime date; const PerDateWidget({super.key, required this.date}); @override State createState() => _PerDateWidgetState(); } class _PerDateWidgetState extends State { late FoodStorage storage; late Future> entriesFuture; List entries = []; @override void initState() { log("PerDateWidgetState's initState()"); storage = FoodStorage.getInstance(); entriesFuture = storage.getEntriesForDate(widget.date); entriesFuture.then((val) { entries = val; }); super.initState(); } @override Widget build(BuildContext context) { log("PerDateWidgetState's build()"); return FutureBuilder( future: entriesFuture, builder: (context, snapshot) { return snapshot.connectionState != ConnectionState.done ? const Center(child: CircularProgressIndicator()) : MultiProvider( providers: [ ChangeNotifierProvider( create: (context) => EnterFoodController()), BlocProvider( create: (context) => FoodEntryBloc( initialState: FoodEntryState(foodEntries: entries), storage: storage, forDate: widget.date, ), ) ], child: BlocBuilder( builder: (context, state) { return Scaffold( appBar: AppBar( title: Text(DateFormat.yMMMMd('de').format(widget.date)), actions: const [ThemeSwitcherButton()], ), body: FoodEntryList(entries: state.foodEntries), bottomNavigationBar: BottomAppBar( shape: const RectangularNotchShape(), color: Theme.of(context).colorScheme.secondary, child: SumWidget(foodEntries: state.foodEntries)), drawer: const AppDrawer(), floatingActionButton: OverflowBar(children: [ ScanFoodFloatingButton( onPressed: () async { var client = FoodFactLookupClient(); var scanResult = await BarcodeScanner.scan(); if (!context.mounted) return; if (scanResult.type == ResultType.Cancelled) { return; } if (scanResult.type == ResultType.Error) { var snackbar = const SnackBar( content: Text("Error scanning barcode")); ScaffoldMessenger.of(context) .showSnackBar(snackbar); } var response = await client .retrieveFoodInfo(scanResult.rawContent); if (!context.mounted) return; if (response.status == FoodFactResponseStatus.foodNotFound) { var snackbar = const SnackBar( content: Text("Food not found")); ScaffoldMessenger.of(context) .showSnackBar(snackbar); } if (response.status == FoodFactResponseStatus .foodFactServerNotReachable) { var snackbar = const SnackBar( content: Text("FoodFact server not reachable")); ScaffoldMessenger.of(context) .showSnackBar(snackbar); } context.read().set( response.food!.name, response.food!.kcalPer100g.toString(), ); }, ), const SizedBox(width: 8), CalendarFloatingButton( startFromDate: widget.date, onDateSelected: (dateSelected) { Navigator.of(context).push( MaterialPageRoute( builder: (context) { return PerDateWidget(date: dateSelected); }, ), ); }, ), ]), floatingActionButtonLocation: FloatingActionButtonLocation.endDocked); }), ); }); } } class EnterFoodController extends ChangeNotifier { String name = ""; String kcalPer100g = ""; void set(String newName, String newKcal) { name = newName; kcalPer100g = newKcal; notifyListeners(); } }