Skip to content

Commit

Permalink
Merge pull request #93 from Sinnaj94/feat/make-entries-editable
Browse files Browse the repository at this point in the history
Feature: Make Entries Editable (#36)
  • Loading branch information
simonoppowa authored Jun 29, 2024
2 parents 06f4cd0 + e9c883f commit 943728d
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 22 deletions.
10 changes: 5 additions & 5 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ PODS:
- GoogleToolboxForMac/Defines (= 2.3.2)
- "GoogleToolboxForMac/NSString+URLArguments (= 2.3.2)"
- "GoogleToolboxForMac/NSString+URLArguments (2.3.2)"
- GoogleUtilities/Environment (7.13.0):
- GoogleUtilities/Environment (7.13.3):
- GoogleUtilities/Privacy
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.13.0):
- GoogleUtilities/Logger (7.13.3):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (7.13.0)
- GoogleUtilities/UserDefaults (7.13.0):
- GoogleUtilities/Privacy (7.13.3)
- GoogleUtilities/UserDefaults (7.13.3):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilitiesComponents (1.1.0):
Expand Down Expand Up @@ -150,7 +150,7 @@ SPEC CHECKSUMS:
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleMLKit: 2bd0dc6253c4d4f227aad460f69215a504b2980e
GoogleToolboxForMac: 8bef7c7c5cf7291c687cf5354f39f9db6399ad34
GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
MLImage: 7bb7c4264164ade9bf64f679b40fb29c8f33ee9b
Expand Down
20 changes: 20 additions & 0 deletions lib/core/data/data_source/intake_data_source.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:logging/logging.dart';
Expand Down Expand Up @@ -25,6 +26,25 @@ class IntakeDataSource {
});
}

Future<IntakeDBO?> updateIntake(String intakeId, Map<String, dynamic> fields) async {
log.fine('Updating intake $intakeId with fields ${fields.toString()} in db');
var intakeObject = _intakeBox.values.indexed
.where((indexedDbo) => indexedDbo.$2.id == intakeId).firstOrNull;
if(intakeObject == null) {
log.fine('Cannot update intake $intakeId as it is non existent');
return null;
}
intakeObject.$2.amount = fields['amount'] ?? intakeObject.$2.amount;
_intakeBox.putAt(intakeObject.$1, intakeObject.$2);
return _intakeBox.getAt(intakeObject.$1);
}

Future<IntakeDBO?> getIntakeById(String intakeId) async {
return _intakeBox.values.firstWhereOrNull(
(intake) => intake.id == intakeId
);
}

Future<List<IntakeDBO>> getAllIntakesByDate(
IntakeTypeDBO intakeType, DateTime dateTime) async {
return _intakeBox.values
Expand Down
10 changes: 10 additions & 0 deletions lib/core/data/repository/intake_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class IntakeRepository {
await _intakeDataSource.deleteIntakeFromId(intakeEntity.id);
}

Future<IntakeEntity?> updateIntake(String intakeId, Map<String, dynamic> fields) async {
var result = await _intakeDataSource.updateIntake(intakeId, fields);
return result == null ? null : IntakeEntity.fromIntakeDBO(result);
}

Future<List<IntakeEntity>> getIntakeByDateAndType(
IntakeTypeEntity intakeType, DateTime date) async {
final intakeDBOList = await _intakeDataSource.getAllIntakesByDate(
Expand All @@ -36,4 +41,9 @@ class IntakeRepository {
.map((intakeDBO) => IntakeEntity.fromIntakeDBO(intakeDBO))
.toList();
}

Future<IntakeEntity?> getIntakeById(String intakeId) async {
final result = await _intakeDataSource.getIntakeById(intakeId);
return result == null ? null : IntakeEntity.fromIntakeDBO(result);
}
}
4 changes: 4 additions & 0 deletions lib/core/domain/usecase/get_intake_usecase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ class GetIntakeUsecase {
Future<List<IntakeEntity>> getRecentIntake() async {
return _intakeRepository.getRecentIntake();
}

Future<IntakeEntity?> getIntakeById(String intakeId) async {
return _intakeRepository.getIntakeById(intakeId);
}
}
13 changes: 13 additions & 0 deletions lib/core/domain/usecase/update_intake_usecase.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:opennutritracker/core/data/repository/intake_repository.dart';
import 'package:opennutritracker/core/domain/entity/intake_entity.dart';

class UpdateIntakeUsecase {
final IntakeRepository _intakeRepository;

UpdateIntakeUsecase(this._intakeRepository);

Future<IntakeEntity?> updateIntake(
String intakeId, Map<String, dynamic> intakeFields) async {
return await _intakeRepository.updateIntake(intakeId, intakeFields);
}
}
47 changes: 47 additions & 0 deletions lib/core/presentation/widgets/edit_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
import 'package:opennutritracker/core/domain/entity/intake_entity.dart';
import 'package:opennutritracker/generated/l10n.dart';

class EditDialog extends StatefulWidget {
final IntakeEntity intakeEntity;

const EditDialog({super.key, required this.intakeEntity});

@override
State<StatefulWidget> createState() => _EditDialogState();
}

class _EditDialogState extends State<EditDialog> {


@override
Widget build(BuildContext context) {
var amountEditingController = TextEditingController(text: widget.intakeEntity.amount.toInt().toString());
return AlertDialog(
title: Text(S.of(context).editItemDialogTitle),
content: Column(mainAxisSize: MainAxisSize.min, children: [
TextFormField(
controller: amountEditingController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: S.of(context).quantityLabel,
suffixText: widget.intakeEntity.meal.mealUnit ?? S.of(context).gramMilliliterUnit
),
)
]),
actions: [
TextButton(
onPressed: () {
double newAmount = double.parse(amountEditingController.text);
Navigator.of(context).pop(newAmount);
},
child: Text(S.of(context).dialogOKLabel)),
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(S.of(context).dialogCancelLabel))
],
);
}
}
13 changes: 10 additions & 3 deletions lib/core/presentation/widgets/intake_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import 'package:opennutritracker/core/utils/locator.dart';
class IntakeCard extends StatelessWidget {
final IntakeEntity intake;
final Function(BuildContext, IntakeEntity)? onItemLongPressed;
final Function(BuildContext, IntakeEntity)? onItemTapped;
final bool firstListElement;

const IntakeCard(
{required super.key,
required this.intake,
this.onItemLongPressed,
this.onItemTapped,
required this.firstListElement});

@override
Expand All @@ -35,6 +37,9 @@ class IntakeCard extends StatelessWidget {
onLongPress: onItemLongPressed != null
? () => onLongPressedItem(context)
: null,
onTap: onItemTapped != null
? () => onTappedItem(context)
: null,
child: Stack(
children: [
intake.meal.mainImageUrl != null
Expand Down Expand Up @@ -122,8 +127,10 @@ class IntakeCard extends StatelessWidget {
}

void onLongPressedItem(BuildContext context) {
if (onItemLongPressed != null) {
onItemLongPressed!(context, intake);
}
onItemLongPressed?.call(context, intake);
}

void onTappedItem(BuildContext context) {
onItemTapped?.call(context, intake);
}
}
5 changes: 4 additions & 1 deletion lib/core/utils/locator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:opennutritracker/core/domain/usecase/get_physical_activity_useca
import 'package:opennutritracker/core/domain/usecase/get_tracked_day_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/get_user_activity_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/get_user_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/update_intake_usecase.dart';
import 'package:opennutritracker/core/utils/env.dart';
import 'package:opennutritracker/core/utils/hive_db_provider.dart';
import 'package:opennutritracker/core/utils/ont_image_cache_manager.dart';
Expand Down Expand Up @@ -73,7 +74,7 @@ Future<void> initLocator() async {
// BLoCs
locator.registerLazySingleton<OnboardingBloc>(
() => OnboardingBloc(locator(), locator()));
locator.registerLazySingleton<HomeBloc>(() => HomeBloc(locator(), locator(),
locator.registerLazySingleton<HomeBloc>(() => HomeBloc(locator(), locator(), locator(),
locator(), locator(), locator(), locator(), locator(), locator()));
locator.registerLazySingleton(() => DiaryBloc(locator()));
locator.registerLazySingleton(() => CalendarDayBloc(
Expand Down Expand Up @@ -114,6 +115,8 @@ Future<void> initLocator() async {
() => AddIntakeUsecase(locator()));
locator.registerLazySingleton<DeleteIntakeUsecase>(
() => DeleteIntakeUsecase(locator()));
locator.registerLazySingleton<UpdateIntakeUsecase>(
() => UpdateIntakeUsecase(locator()));
locator.registerLazySingleton<GetUserActivityUsecase>(
() => GetUserActivityUsecase(locator()));
locator.registerLazySingleton<AddUserActivityUsecase>(
Expand Down
21 changes: 21 additions & 0 deletions lib/features/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:opennutritracker/core/domain/entity/intake_entity.dart';
import 'package:opennutritracker/core/domain/entity/intake_type_entity.dart';
import 'package:opennutritracker/core/domain/entity/user_activity_entity.dart';
import 'package:opennutritracker/core/presentation/widgets/activity_vertial_list.dart';
import 'package:opennutritracker/core/presentation/widgets/edit_dialog.dart';
import 'package:opennutritracker/core/presentation/widgets/delete_dialog.dart';
import 'package:opennutritracker/core/presentation/widgets/disclaimer_dialog.dart';
import 'package:opennutritracker/core/utils/locator.dart';
Expand Down Expand Up @@ -139,6 +140,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
addMealType: AddMealType.breakfastType,
intakeList: breakfastIntakeList,
onItemDragCallback: onIntakeItemDrag,
onItemTappedCallback: onIntakeItemTapped,
),
IntakeVerticalList(
day: DateTime.now(),
Expand All @@ -147,6 +149,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
addMealType: AddMealType.lunchType,
intakeList: lunchIntakeList,
onItemDragCallback: onIntakeItemDrag,
onItemTappedCallback: onIntakeItemTapped,
),
IntakeVerticalList(
day: DateTime.now(),
Expand All @@ -155,6 +158,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
listIcon: IntakeTypeEntity.dinner.getIconData(),
intakeList: dinnerIntakeList,
onItemDragCallback: onIntakeItemDrag,
onItemTappedCallback: onIntakeItemTapped,
),
IntakeVerticalList(
day: DateTime.now(),
Expand All @@ -163,6 +167,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
addMealType: AddMealType.snackType,
intakeList: snackIntakeList,
onItemDragCallback: onIntakeItemDrag,
onItemTappedCallback: onIntakeItemTapped,
),
const SizedBox(height: 48.0)
]),
Expand Down Expand Up @@ -234,6 +239,22 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
});
}

void onIntakeItemTapped(
BuildContext context, IntakeEntity intakeEntity) async {
final changeIntakeAmount = await showDialog<double>(
context: context, builder: (context) => EditDialog(
intakeEntity: intakeEntity)
);
if(changeIntakeAmount != null) {
_homeBloc.updateIntakeItem(intakeEntity.id, { 'amount': changeIntakeAmount });
_homeBloc.add(const LoadItemsEvent());
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(S.of(context).itemUpdatedSnackbar)));
}
}
}

void _confirmDelete(BuildContext context, IntakeEntity intake) async {
bool? delete = await showDialog<bool>(
context: context, builder: (context) => const DeleteDialog());
Expand Down
32 changes: 32 additions & 0 deletions lib/features/home/presentation/bloc/home_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:opennutritracker/core/domain/usecase/get_config_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/get_intake_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/get_user_activity_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/get_user_usecase.dart';
import 'package:opennutritracker/core/domain/usecase/update_intake_usecase.dart';
import 'package:opennutritracker/core/utils/calc/calorie_goal_calc.dart';
import 'package:opennutritracker/core/utils/calc/macro_calc.dart';
import 'package:opennutritracker/core/utils/locator.dart';
Expand All @@ -26,6 +27,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
final AddConfigUsecase _addConfigUsecase;
final GetIntakeUsecase _getIntakeUsecase;
final DeleteIntakeUsecase _deleteIntakeUsecase;
final UpdateIntakeUsecase _updateIntakeUsecase;
final GetUserActivityUsecase _getUserActivityUsecase;
final DeleteUserActivityUsecase _deleteUserActivityUsecase;
final GetUserUsecase _getUserUsecase;
Expand All @@ -38,6 +40,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
this._addConfigUsecase,
this._getIntakeUsecase,
this._deleteIntakeUsecase,
this._updateIntakeUsecase,
this._getUserActivityUsecase,
this._deleteUserActivityUsecase,
this._getUserUsecase,
Expand Down Expand Up @@ -143,6 +146,35 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
_addConfigUsecase.setConfigDisclaimer(acceptedDisclaimer);
}

Future<void> updateIntakeItem(
String intakeId, Map<String, dynamic> fields) async {
final dateTime = DateTime.now();
// Get old intake values
final oldIntakeObject = await _getIntakeUsecase.getIntakeById(intakeId);
assert(oldIntakeObject != null);
final newIntakeObject =
await _updateIntakeUsecase.updateIntake(intakeId, fields);
assert(newIntakeObject != null);
if(oldIntakeObject!.amount > newIntakeObject!.amount) {
// Amounts shrunk
await _addTrackedDayUseCase.removeDayCaloriesTracked(
dateTime, oldIntakeObject.totalKcal - newIntakeObject.totalKcal);
await _addTrackedDayUseCase.removeDayMacrosTracked(dateTime,
carbsTracked: oldIntakeObject.totalCarbsGram - newIntakeObject.totalCarbsGram,
fatTracked: oldIntakeObject.totalFatsGram - newIntakeObject.totalFatsGram,
proteinTracked: oldIntakeObject.totalProteinsGram - newIntakeObject.totalProteinsGram);
} else if(newIntakeObject.amount > oldIntakeObject.amount) {
// Amounts gained
await _addTrackedDayUseCase.addDayCaloriesTracked(
dateTime, newIntakeObject.totalKcal - oldIntakeObject.totalKcal);
await _addTrackedDayUseCase.addDayMacrosTracked(dateTime,
carbsTracked: newIntakeObject.totalCarbsGram - oldIntakeObject.totalCarbsGram,
fatTracked: newIntakeObject.totalFatsGram - oldIntakeObject.totalFatsGram,
proteinTracked: newIntakeObject.totalProteinsGram - oldIntakeObject.totalProteinsGram);
}
_updateDiaryPage(dateTime);
}

Future<void> deleteIntakeItem(IntakeEntity intakeEntity) async {
final dateTime = DateTime.now();
await _deleteIntakeUsecase.deleteIntake(intakeEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class IntakeVerticalList extends StatefulWidget {
final List<IntakeEntity> intakeList;
final Function(BuildContext, IntakeEntity)? onItemLongPressedCallback;
final Function(bool)? onItemDragCallback;
final Function(BuildContext, IntakeEntity)? onItemTappedCallback;

const IntakeVerticalList({
super.key,
Expand All @@ -30,6 +31,7 @@ class IntakeVerticalList extends StatefulWidget {
required this.intakeList,
this.onItemLongPressedCallback,
this.onItemDragCallback,
this.onItemTappedCallback
});

@override
Expand Down Expand Up @@ -142,6 +144,7 @@ class _IntakeVerticalListState extends State<IntakeVerticalList> {
key: ValueKey(intakeEntity.meal.code),
intake: intakeEntity,
onItemLongPressed: widget.onItemLongPressedCallback,
onItemTapped: widget.onItemTappedCallback,
firstListElement: firstListElement,
),
);
Expand Down
20 changes: 20 additions & 0 deletions lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 943728d

Please sign in to comment.