Instead of a global FoodEntryBloc, every PerDateWidget has one
This commit is contained in:
parent
d2ab82aaf5
commit
be2ab69a3f
@ -20,7 +20,7 @@ class AppDrawer extends StatelessWidget {
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
title: const Text('Menü')),
|
||||
@ -29,7 +29,8 @@ class AppDrawer extends StatelessWidget {
|
||||
title: const Text('Einstellungen'),
|
||||
trailing: const Icon(Icons.settings),
|
||||
onTap: () {
|
||||
context.goNamed('settings');
|
||||
context.pop();
|
||||
context.pushNamed('settings');
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -20,7 +20,7 @@ class CalendarFloatingButton extends StatelessWidget {
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
|
||||
router.goNamed('perDay', extra: datePicked);
|
||||
router.pushNamed('perDay', extra: datePicked);
|
||||
},
|
||||
child: const Icon(Icons.today));
|
||||
}
|
||||
|
@ -3,20 +3,25 @@ import 'package:kalodings/storage/storage.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class FoodEntryBloc extends Bloc<FoodEvent, FoodEntryState> {
|
||||
final FoodEntryState initialState;
|
||||
final FoodStorage storage;
|
||||
final DateTime forDate;
|
||||
|
||||
FoodEntryBloc(super.initialState, {required this.storage}) {
|
||||
FoodEntryBloc(
|
||||
{required this.initialState,
|
||||
required this.forDate,
|
||||
required this.storage})
|
||||
: super(initialState) {
|
||||
on<FoodEntryEvent>(addFoodEntry);
|
||||
on<FoodDeletionEvent>(deleteFood);
|
||||
on<PageChangedEvent>(updateEntries);
|
||||
on<DailyKcalLimitUpdated>(persistDailyLimit);
|
||||
}
|
||||
|
||||
void addFoodEntry(FoodEntryEvent event, Emitter<FoodEntryState> emit) async {
|
||||
FoodEntryState newState = FoodEntryState.from(state);
|
||||
newState.addEntry(event.entry);
|
||||
|
||||
await storage.writeEntriesForDate(event.date, newState.foodEntries);
|
||||
await storage.writeEntriesForDate(forDate, newState.foodEntries);
|
||||
|
||||
emit(newState);
|
||||
}
|
||||
@ -24,7 +29,7 @@ class FoodEntryBloc extends Bloc<FoodEvent, FoodEntryState> {
|
||||
void deleteFood(FoodDeletionEvent event, Emitter<FoodEntryState> emit) async {
|
||||
state.foodEntries.removeWhere((entry) => entry.id == event.entryID);
|
||||
|
||||
await storage.writeEntriesForDate(event.date, state.foodEntries);
|
||||
await storage.writeEntriesForDate(forDate, state.foodEntries);
|
||||
|
||||
emit(FoodEntryState.from(state));
|
||||
}
|
||||
@ -32,35 +37,23 @@ class FoodEntryBloc extends Bloc<FoodEvent, FoodEntryState> {
|
||||
void updateEntries(
|
||||
PageChangedEvent event, Emitter<FoodEntryState> emit) async {
|
||||
var entries = await storage.getEntriesForDate(event.changedToDate);
|
||||
var limit = await storage.readLimit();
|
||||
var newState = FoodEntryState(foodEntries: entries, kcalLimit: limit);
|
||||
var newState = FoodEntryState(foodEntries: entries);
|
||||
emit(newState);
|
||||
}
|
||||
|
||||
void persistDailyLimit(
|
||||
DailyKcalLimitUpdated event, Emitter<FoodEntryState> emit) async {
|
||||
await storage.updateLimit(event.kcal);
|
||||
emit(FoodEntryState(foodEntries: state.foodEntries, kcalLimit: event.kcal));
|
||||
}
|
||||
|
||||
void getDailyLimit(
|
||||
DailyKcalLimitUpdated event, Emitter<FoodEntryState> emit) async {}
|
||||
}
|
||||
|
||||
class FoodEvent {}
|
||||
|
||||
class FoodEntryEvent extends FoodEvent {
|
||||
final FoodEntry entry;
|
||||
final DateTime date;
|
||||
|
||||
FoodEntryEvent({required this.entry, required this.date});
|
||||
FoodEntryEvent({required this.entry});
|
||||
}
|
||||
|
||||
class FoodDeletionEvent extends FoodEvent {
|
||||
final String entryID;
|
||||
final DateTime date;
|
||||
|
||||
FoodDeletionEvent({required this.entryID, required this.date});
|
||||
FoodDeletionEvent({required this.entryID});
|
||||
}
|
||||
|
||||
class PageChangedEvent extends FoodEvent {
|
||||
@ -69,24 +62,18 @@ class PageChangedEvent extends FoodEvent {
|
||||
PageChangedEvent({required this.changedToDate});
|
||||
}
|
||||
|
||||
class DailyKcalLimitUpdated extends FoodEvent {
|
||||
final double kcal;
|
||||
DailyKcalLimitUpdated({required this.kcal});
|
||||
}
|
||||
|
||||
class FoodEntryState {
|
||||
final List<FoodEntry> foodEntries;
|
||||
final double kcalLimit;
|
||||
|
||||
FoodEntryState({required this.foodEntries, required this.kcalLimit});
|
||||
FoodEntryState({required this.foodEntries});
|
||||
|
||||
factory FoodEntryState.init() {
|
||||
return FoodEntryState(foodEntries: [], kcalLimit: 0);
|
||||
return FoodEntryState(foodEntries: []);
|
||||
}
|
||||
|
||||
static from(FoodEntryState state) {
|
||||
List<FoodEntry> newList = List.from(state.foodEntries);
|
||||
return FoodEntryState(foodEntries: newList, kcalLimit: state.kcalLimit);
|
||||
return FoodEntryState(foodEntries: newList);
|
||||
}
|
||||
|
||||
void addEntry(FoodEntry entry) {
|
||||
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:kalodings/food_entry_bloc.dart';
|
||||
import 'package:kalodings/settings_bloc.dart';
|
||||
import 'package:kalodings/perdate_widget.dart';
|
||||
import 'package:kalodings/settings.dart';
|
||||
import 'package:kalodings/storage/storage.dart';
|
||||
@ -10,20 +10,22 @@ import 'package:kalodings/storage/storage.dart';
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
var storage = await FoodStorage.create();
|
||||
var kcalLimit = await storage.readLimit();
|
||||
|
||||
runApp(MainApp(storage: storage));
|
||||
runApp(MainApp(storage: storage, kcalLimit: kcalLimit));
|
||||
}
|
||||
|
||||
class MainApp extends StatelessWidget {
|
||||
final FoodStorage storage;
|
||||
const MainApp({required this.storage, super.key});
|
||||
final double kcalLimit;
|
||||
|
||||
const MainApp({required this.storage, required this.kcalLimit, super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) {
|
||||
return FoodEntryBloc(FoodEntryState.init(), storage: storage);
|
||||
},
|
||||
create: (context) => SettingsDataBloc(SettingsState(kcalLimit: kcalLimit),
|
||||
storage: storage),
|
||||
child: MaterialApp.router(
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
@ -40,16 +42,7 @@ class MainApp extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
final router = GoRouter(routes: [
|
||||
GoRoute(
|
||||
path: '/',
|
||||
name: 'perDayToday',
|
||||
builder: (context, state) {
|
||||
context
|
||||
.read<FoodEntryBloc>()
|
||||
.add(PageChangedEvent(changedToDate: DateTime.now()));
|
||||
return PerDateWidget(DateTime.now());
|
||||
}),
|
||||
final router = GoRouter(initialLocation: '/day', routes: [
|
||||
GoRoute(
|
||||
path: '/day',
|
||||
name: 'perDay',
|
||||
@ -60,11 +53,8 @@ final router = GoRouter(routes: [
|
||||
} else {
|
||||
date = state.extra as DateTime;
|
||||
}
|
||||
context
|
||||
.read<FoodEntryBloc>()
|
||||
.add(PageChangedEvent(changedToDate: date));
|
||||
|
||||
return PerDateWidget(date);
|
||||
return PerDateWidget(date: date);
|
||||
}),
|
||||
GoRoute(
|
||||
path: '/settings',
|
||||
|
@ -6,59 +6,95 @@ import 'package:kalodings/calendar_floating_button.dart';
|
||||
import 'package:kalodings/enter_food_widget.dart';
|
||||
import 'package:kalodings/food_entry_bloc.dart';
|
||||
import 'package:kalodings/food_entry_widget.dart';
|
||||
import 'package:kalodings/storage/storage.dart';
|
||||
import 'package:kalodings/sum_widget.dart';
|
||||
|
||||
class PerDateWidget extends StatelessWidget {
|
||||
class PerDateWidget extends StatefulWidget {
|
||||
final DateTime date;
|
||||
const PerDateWidget(this.date, {super.key});
|
||||
const PerDateWidget({super.key, required this.date});
|
||||
|
||||
@override
|
||||
State<PerDateWidget> createState() => _PerDateWidgetState();
|
||||
}
|
||||
|
||||
class _PerDateWidgetState extends State<PerDateWidget> {
|
||||
late FoodStorage storage;
|
||||
late Future<List<FoodEntry>> entriesFuture;
|
||||
late List<FoodEntry> entries;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
storage = FoodStorage.getInstance();
|
||||
entriesFuture = storage.getEntriesForDate(widget.date);
|
||||
entriesFuture.then((val) {
|
||||
entries = val;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var formattedDate = DateFormat.yMMMMd('de').format(date);
|
||||
var formattedDate = DateFormat.yMMMMd('de').format(widget.date);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(formattedDate),
|
||||
),
|
||||
drawer: const AppDrawer(),
|
||||
body: BlocBuilder<FoodEntryBloc, FoodEntryState>(
|
||||
builder: (context, state) {
|
||||
return ListView.builder(
|
||||
itemCount: state.foodEntries.length + 2,
|
||||
itemBuilder: (BuildContext itemBuilderContext, int index) {
|
||||
if (index == state.foodEntries.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: SumWidget(limit: state.kcalLimit),
|
||||
);
|
||||
}
|
||||
if (index == state.foodEntries.length + 1) {
|
||||
return Column(
|
||||
children: [
|
||||
EnterFoodWidget(
|
||||
onAdd: (context, entry) {
|
||||
context
|
||||
.read<FoodEntryBloc>()
|
||||
.add(FoodEntryEvent(entry: entry, date: date));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 75),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return FoodEntryWidget(
|
||||
entry: state.foodEntries[index],
|
||||
onDelete: (callbackContext) {
|
||||
callbackContext.read<FoodEntryBloc>().add(
|
||||
FoodDeletionEvent(
|
||||
entryID: state.foodEntries[index].id, date: date),
|
||||
body: FutureBuilder(
|
||||
future: entriesFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else {
|
||||
return BlocProvider(
|
||||
create: (context) => FoodEntryBloc(
|
||||
initialState: FoodEntryState(foodEntries: entries),
|
||||
storage: storage,
|
||||
forDate: widget.date),
|
||||
child: BlocBuilder<FoodEntryBloc, FoodEntryState>(
|
||||
builder: (context, state) {
|
||||
return ListView.builder(
|
||||
itemCount: state.foodEntries.length + 2,
|
||||
itemBuilder: (BuildContext itemBuilderContext, int index) {
|
||||
if (index == state.foodEntries.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: SumWidget(foodEntries: state.foodEntries),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
if (index == state.foodEntries.length + 1) {
|
||||
return Column(
|
||||
children: [
|
||||
EnterFoodWidget(
|
||||
onAdd: (context, entry) {
|
||||
context
|
||||
.read<FoodEntryBloc>()
|
||||
.add(FoodEntryEvent(entry: entry));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 75),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return FoodEntryWidget(
|
||||
entry: state.foodEntries[index],
|
||||
onDelete: (callbackContext) {
|
||||
callbackContext
|
||||
.read<FoodEntryBloc>()
|
||||
.add(FoodDeletionEvent(
|
||||
entryID: state.foodEntries[index].id,
|
||||
));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
floatingActionButton: CalendarFloatingButton(date: date));
|
||||
floatingActionButton: CalendarFloatingButton(date: widget.date));
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:kalodings/app_drawer.dart';
|
||||
import 'package:kalodings/calendar_floating_button.dart';
|
||||
import 'package:kalodings/food_entry_bloc.dart';
|
||||
import 'package:kalodings/settings_bloc.dart';
|
||||
import 'package:settings_ui/settings_ui.dart';
|
||||
|
||||
class SettingsWidget extends StatefulWidget {
|
||||
@ -19,7 +19,7 @@ class _SettingsWidgetState extends State<SettingsWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: BlocBuilder<FoodEntryBloc, FoodEntryState>(
|
||||
body: BlocBuilder<SettingsDataBloc, SettingsState>(
|
||||
builder: (context, state) {
|
||||
return SettingsList(sections: [
|
||||
SettingsSection(
|
||||
@ -45,7 +45,7 @@ class _SettingsWidgetState extends State<SettingsWidget> {
|
||||
} catch (e) {
|
||||
setting = 2000.0;
|
||||
}
|
||||
context.read<FoodEntryBloc>().add(
|
||||
context.read<SettingsDataBloc>().add(
|
||||
DailyKcalLimitUpdated(kcal: setting));
|
||||
ctx.pop();
|
||||
},
|
||||
|
37
lib/settings_bloc.dart
Normal file
37
lib/settings_bloc.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:kalodings/storage/storage.dart';
|
||||
|
||||
class SettingsDataBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||
final FoodStorage storage;
|
||||
|
||||
SettingsDataBloc(super.initialState, {required this.storage}) {
|
||||
on<DailyKcalLimitUpdated>(persistDailyLimit);
|
||||
}
|
||||
|
||||
void persistDailyLimit(
|
||||
DailyKcalLimitUpdated event, Emitter<SettingsState> emit) async {
|
||||
await storage.updateLimit(event.kcal);
|
||||
emit(SettingsState(kcalLimit: event.kcal));
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsEvent {}
|
||||
|
||||
class DailyKcalLimitUpdated extends SettingsEvent {
|
||||
final double kcal;
|
||||
DailyKcalLimitUpdated({required this.kcal});
|
||||
}
|
||||
|
||||
class SettingsState {
|
||||
final double kcalLimit;
|
||||
|
||||
SettingsState({required this.kcalLimit});
|
||||
|
||||
factory SettingsState.init() {
|
||||
return SettingsState(kcalLimit: 2000);
|
||||
}
|
||||
|
||||
static from(SettingsState state) {
|
||||
return SettingsState(kcalLimit: state.kcalLimit);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import 'package:kalodings/food_entry_bloc.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class FoodStorage {
|
||||
static late FoodStorage _instance;
|
||||
late String path;
|
||||
FoodStorage._create();
|
||||
|
||||
@ -11,10 +12,13 @@ class FoodStorage {
|
||||
var storage = FoodStorage._create();
|
||||
var directory = await getApplicationCacheDirectory();
|
||||
storage.path = directory.path;
|
||||
_instance = storage;
|
||||
|
||||
return storage;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
static FoodStorage getInstance() => _instance;
|
||||
|
||||
Future<List<FoodEntry>> getEntriesForDate(DateTime date) async {
|
||||
List<FoodEntry> entries = [];
|
||||
var filePath = '$path/${date.year}/${date.month}/${date.day}';
|
||||
|
@ -1,19 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:kalodings/food_entry_bloc.dart';
|
||||
import 'package:kalodings/settings_bloc.dart';
|
||||
import 'package:kalodings/row_with_spacers_widget.dart';
|
||||
|
||||
class SumWidget extends StatelessWidget {
|
||||
final double limit;
|
||||
|
||||
const SumWidget({required this.limit, super.key});
|
||||
class SumWidget extends StatefulWidget {
|
||||
final List<FoodEntry> foodEntries;
|
||||
const SumWidget({required this.foodEntries, super.key});
|
||||
|
||||
@override
|
||||
State<SumWidget> createState() => _SumWidgetState();
|
||||
}
|
||||
|
||||
class _SumWidgetState extends State<SumWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FoodEntryBloc, FoodEntryState>(
|
||||
return BlocBuilder<SettingsDataBloc, SettingsState>(
|
||||
builder: (context, state) {
|
||||
var sum = 0.0;
|
||||
for (var entry in state.foodEntries) {
|
||||
for (var entry in widget.foodEntries) {
|
||||
sum += entry.kcalPerMass / 100 * entry.mass;
|
||||
}
|
||||
|
||||
@ -21,7 +26,7 @@ class SumWidget extends StatelessWidget {
|
||||
null,
|
||||
null,
|
||||
const Text("kcal heute:"),
|
||||
Text('${sum.toString()}/$limit'),
|
||||
Text('${sum.toString()}/${state.kcalLimit}'),
|
||||
null,
|
||||
);
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user