Marco
cb18e1d1f0
1. Show PerDate widgets inside of an PageView 2. Introduce GoRouter so we can intercept back button taps with BackButtonListener 3. Implement rudimentary navigation 4. Fix bug that still showed a spinner event when the barcode was not found.
134 lines
4.9 KiB
Dart
134 lines
4.9 KiB
Dart
import 'package:barcode_scan2/barcode_scan2.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;
|
|
final Function(DateTime?) onDateSelected;
|
|
const PerDateWidget(
|
|
{super.key, required this.date, required this.onDateSelected});
|
|
|
|
@override
|
|
State<PerDateWidget> createState() => _PerDateWidgetState();
|
|
}
|
|
|
|
class _PerDateWidgetState extends State<PerDateWidget>
|
|
with AutomaticKeepAliveClientMixin<PerDateWidget> {
|
|
late FoodStorage storage;
|
|
late Future<List<FoodEntryState>> entriesFuture;
|
|
List<FoodEntryState> entries = [];
|
|
|
|
@override
|
|
void initState() {
|
|
storage = FoodStorage.getInstance();
|
|
entriesFuture = storage.getEntriesForDate(widget.date);
|
|
entriesFuture.then((val) {
|
|
entries = val;
|
|
});
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
super.build(context);
|
|
|
|
return FutureBuilder(
|
|
future: entriesFuture,
|
|
builder: (context, snapshot) {
|
|
return snapshot.connectionState != ConnectionState.done
|
|
? const Center(child: CircularProgressIndicator())
|
|
: MultiProvider(
|
|
providers: [
|
|
BlocProvider(
|
|
create: (context) => FoodEntryBloc(
|
|
initialState: PageState(foodEntries: entries),
|
|
storage: storage,
|
|
forDate: widget.date,
|
|
),
|
|
)
|
|
],
|
|
child: BlocConsumer<FoodEntryBloc, PageState>(
|
|
listener: (context, pageState) {
|
|
if (pageState.errorString != null) {
|
|
showNewSnackbarWith(context, pageState.errorString!);
|
|
}
|
|
},
|
|
builder: (context, pageState) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(
|
|
DateFormat.yMMMMd('de').format(widget.date)),
|
|
actions: const [ThemeSwitcherButton()],
|
|
),
|
|
body: FoodEntryList(entries: pageState.foodEntries),
|
|
bottomNavigationBar: BottomAppBar(
|
|
shape: const RectangularNotchShape(),
|
|
color: Theme.of(context).colorScheme.secondary,
|
|
child: SumWidget(
|
|
foodEntries: pageState.foodEntries)),
|
|
drawer: const AppDrawer(),
|
|
floatingActionButton: OverflowBar(children: [
|
|
ScanFoodFloatingButton(
|
|
onPressed: () {
|
|
var result = BarcodeScanner.scan();
|
|
context.read<FoodEntryBloc>().add(
|
|
BarcodeScanned(scanResultFuture: result));
|
|
},
|
|
),
|
|
const SizedBox(width: 8),
|
|
CalendarFloatingButton(
|
|
startFromDate: widget.date,
|
|
onDateSelected: (dateSelected) {
|
|
widget.onDateSelected(dateSelected);
|
|
},
|
|
),
|
|
]),
|
|
floatingActionButtonLocation:
|
|
FloatingActionButtonLocation.endDocked);
|
|
},
|
|
),
|
|
);
|
|
});
|
|
}
|
|
|
|
void showNewSnackbarWith(BuildContext context, String text) {
|
|
var snackbar =
|
|
ErrorSnackbar(colorScheme: Theme.of(context).colorScheme, text: text);
|
|
|
|
ScaffoldMessenger.of(context)
|
|
..removeCurrentSnackBar()
|
|
..showSnackBar(snackbar);
|
|
}
|
|
|
|
@override
|
|
bool get wantKeepAlive => true;
|
|
}
|
|
|
|
class ErrorSnackbar extends SnackBar {
|
|
final String text;
|
|
final ColorScheme colorScheme;
|
|
ErrorSnackbar({
|
|
required this.text,
|
|
required this.colorScheme,
|
|
super.key,
|
|
}) : super(
|
|
content: Text(text, style: TextStyle(color: colorScheme.onError)),
|
|
backgroundColor: colorScheme.error);
|
|
}
|