Skip to content

Commit 51ec089

Browse files
committed
progress reading data, using ivm tables
1 parent 99e4961 commit 51ec089

15 files changed

+344
-175
lines changed

lib/models/nutrition/log.dart

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,14 @@ class Log {
107107
return ingredient.nutritionalValues / (100 / weight);
108108
}
109109

110+
static Future<List<Log>> readByMealId(int mealId) async {
111+
final results = await db.getAll('SELECT * FROM $tableLogItems WHERE meal_id = ?', [mealId]);
112+
return results.map((r) => Log.fromRow(r)).toList();
113+
}
114+
110115
static Future<List<Log>> readByPlanId(int planId) async {
111116
final results = await db.getAll('SELECT * FROM $tableLogItems WHERE plan_id = ?', [planId]);
112-
return results.map((r) {
113-
final log = Log.fromRow(r);
114-
// TODO:
115-
// need to find a way to set ingredients. since we don't use powersync for it, we need to fetch
116-
// but this needs a context, therofere this needs a context, and all callers do, so we should probably
117-
// move all that stuff into the nutritionprovider, so we keep context out of the models
118-
// however, still unsolved:
119-
// mealItem stuff then?
120-
// nutrition image
121-
// nutrition_ingredientcategory
122-
// nutrition_ingredientweightunit
123-
// nutrition_weightunit;
124-
// nutrition_mealitem
125-
log.ingredient = Provider.of<NutritionPlansProvider>(context, listen: false).fetchIngredient(id),
126-
return log;
127-
}).toList();
117+
return results.map((r) => Log.fromRow(r)).toList();
128118
}
129119

130120
/*

lib/models/nutrition/meal.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class Meal {
9393
factory Meal.fromRow(sqlite.Row row) {
9494
return Meal(
9595
id: int.parse(row['id']),
96-
plan: row['plan'],
96+
plan: row['plan_id'],
9797
time: stringToTime(row['time']),
9898
name: row['name'],
9999
);
@@ -103,22 +103,30 @@ class Meal {
103103

104104
Meal copyWith({
105105
int? id,
106-
int? planId,
106+
int? plan,
107107
TimeOfDay? time,
108108
String? name,
109109
List<MealItem>? mealItems,
110110
List<Log>? diaryEntries,
111111
}) {
112112
return Meal(
113113
id: id ?? this.id,
114-
plan: planId ?? this.planId,
114+
plan: plan ?? planId,
115115
time: time ?? this.time,
116116
name: name ?? this.name,
117117
mealItems: mealItems ?? this.mealItems,
118118
diaryEntries: diaryEntries ?? this.diaryEntries,
119119
);
120120
}
121121

122+
Future<Meal> loadChildren() async {
123+
print('loadChildren called. plan is $planId');
124+
return copyWith(
125+
mealItems: await MealItem.readByMealId(id!),
126+
diaryEntries: await Log.readByMealId(id!),
127+
);
128+
}
129+
122130
static Future<Meal> read(int id) async {
123131
final results = await db.get('SELECT * FROM $tableMeals WHERE id = ?', [id]);
124132
return Meal.fromRow(results);
@@ -128,6 +136,6 @@ class Meal {
128136
print('Meal.readByPlanId: SELECT * FROM $tableMeals WHERE plan_id = $planId');
129137
final results = await db.getAll('SELECT * FROM $tableMeals WHERE plan_id = ?', [planId]);
130138
print(results.rows.length);
131-
return results.map((r) => Meal.fromRow(r)).toList();
139+
return Future.wait(results.map((r) => Meal.fromRow(r).loadChildren()));
132140
}
133141
}

lib/models/nutrition/meal_item.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
*/
1818

1919
import 'package:json_annotation/json_annotation.dart';
20+
import 'package:powersync/sqlite3.dart' as sqlite;
21+
2022
import 'package:wger/helpers/json.dart';
2123
import 'package:wger/models/nutrition/ingredient.dart';
2224
import 'package:wger/models/nutrition/ingredient_weight_unit.dart';
2325
import 'package:wger/models/nutrition/nutritional_values.dart';
26+
import 'package:wger/models/schema.dart';
27+
import 'package:wger/powersync.dart';
2428

2529
part 'meal_item.g.dart';
2630

@@ -71,6 +75,15 @@ class MealItem {
7175

7276
Map<String, dynamic> toJson() => _$MealItemToJson(this);
7377

78+
factory MealItem.fromRow(sqlite.Row row) {
79+
return MealItem(
80+
amount: row['amount'],
81+
weightUnitId: row['weight_unit_id'],
82+
mealId: row['meal_id'],
83+
ingredientId: row['ingredient_id'],
84+
);
85+
}
86+
7487
/// Calculations
7588
/// TODO why does this not consider weightUnitObj ? should we do the same as Log.nutritionalValues here?
7689
NutritionalValues get nutritionalValues {
@@ -112,4 +125,9 @@ class MealItem {
112125
m.weightUnitObj = weightUnitObj ?? this.weightUnitObj;
113126
return m;
114127
}
128+
129+
static Future<List<MealItem>> readByMealId(int mealId) async {
130+
final results = await db.getAll('SELECT * FROM $tableMealItems WHERE meal_id = ?', [mealId]);
131+
return results.map((r) => MealItem.fromRow(r)).toList();
132+
}
115133
}

lib/models/nutrition/nutritional_plan.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,10 @@ class NutritionalPlan {
327327
});
328328
}
329329

330-
static Stream<NutritionalPlan> watchNutritionPlan(int id) {
330+
static Stream<NutritionalPlan?> watchNutritionPlan(int id) {
331331
return db.onChange([tableNutritionPlans, tableLogItems, tableMeals]).asyncMap((event) async {
332-
final row = await db.get('SELECT * FROM $tableNutritionPlans WHERE id = ?', [id]);
333-
return NutritionalPlan.fromRow(row).loadChildren();
332+
final row = await db.getOptional('SELECT * FROM $tableNutritionPlans WHERE id = ?', [id]);
333+
return row == null ? null : NutritionalPlan.fromRow(row).loadChildren();
334334
});
335335
}
336336

lib/models/schema.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ assumptions: nutrition_ingredientcategory, nutrition_weightunit, nutrition_ingre
1616

1717
// User,NutritionPlan,Meal,LogItem,MealItem,Ingredient
1818
const tableMuscles = 'exercises_muscle';
19-
const tableLogItems = 'nutrition_logitem';
19+
const tableLogItems = 'ivm_nutrition_logitem';
2020
const tableNutritionPlans = 'nutrition_nutritionplan';
21-
const tableMeals = 'nutrition_meal';
22-
const tableMealItems = 'nutrition_mealitem';
21+
const tableMeals = 'ivm_nutrition_meal';
22+
const tableMealItems = 'ivm_nutrition_mealitem';
2323

2424
Schema schema = const Schema([
2525
Table(

lib/providers/nutrition.dart

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19+
import 'dart:async';
1920
import 'dart:convert';
2021
import 'dart:developer';
2122

@@ -91,6 +92,66 @@ class NutritionPlansProvider with ChangeNotifier {
9192
return null;
9293
}
9394

95+
Future<NutritionalPlan> _enrichPlan(NutritionalPlan plan) async {
96+
// TODO: set up ingredient images
97+
98+
final List<Log> diaryEntries = [];
99+
for (final diaryEntry in plan.diaryEntries) {
100+
diaryEntry.ingredient = await fetchIngredient(diaryEntry.ingredientId);
101+
diaryEntries.add(diaryEntry);
102+
}
103+
104+
final List<Meal> meals = [];
105+
for (final meal in plan.meals) {
106+
final List<MealItem> mealItems = [];
107+
for (final mealItem in meal.mealItems) {
108+
mealItem.ingredient = await fetchIngredient(mealItem.ingredientId);
109+
mealItems.add(mealItem);
110+
}
111+
meal.mealItems = mealItems;
112+
meal.diaryEntries = diaryEntries.where((d) => d.mealId == meal.id).toList();
113+
meals.add(meal);
114+
}
115+
116+
plan.meals = meals;
117+
plan.diaryEntries = diaryEntries;
118+
119+
return plan;
120+
}
121+
122+
Stream<NutritionalPlan?> watchNutritionPlan(int id) {
123+
return NutritionalPlan.watchNutritionPlan(id).transform(
124+
StreamTransformer.fromHandlers(
125+
handleData: (plan, sink) async {
126+
if (plan == null) {
127+
sink.add(plan);
128+
return;
129+
}
130+
sink.add(await _enrichPlan(plan));
131+
},
132+
),
133+
);
134+
}
135+
136+
Stream<NutritionalPlan> watchNutritionPlanLast() {
137+
return NutritionalPlan.watchNutritionPlanLast().transform(
138+
StreamTransformer.fromHandlers(
139+
handleData: (plan, sink) async {
140+
sink.add(await _enrichPlan(plan));
141+
},
142+
),
143+
);
144+
}
145+
146+
Stream<List<NutritionalPlan>> watchNutritionPlans() {
147+
return NutritionalPlan.watchNutritionPlans().transform(
148+
StreamTransformer.fromHandlers(
149+
handleData: (plans, sink) async {
150+
sink.add(await Future.wait(plans.map((plan) => _enrichPlan(plan))));
151+
},
152+
),
153+
);
154+
}
94155
/*
95156
TODO implement:
96157
ingredient.image = image;

lib/screens/dashboard.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class _DashboardScreenState extends State<DashboardScreen> {
4242
padding: EdgeInsets.all(10),
4343
child: Column(
4444
children: [
45-
DashboardMuscleWidget(),
4645
DashboardWorkoutWidget(),
4746
DashboardNutritionWidget(),
4847
DashboardWeightWidget(),

lib/screens/nutritional_diary_screen.dart

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19+
import 'dart:async';
20+
1921
import 'package:flutter/material.dart';
2022
import 'package:intl/intl.dart';
2123
import 'package:provider/provider.dart';
@@ -26,31 +28,58 @@ import 'package:wger/widgets/nutrition/nutritional_diary_detail.dart';
2628
/// Arguments passed to the form screen
2729
class NutritionalDiaryArguments {
2830
/// Nutritional plan
29-
final NutritionalPlan plan;
31+
final int plan;
3032

3133
/// Date to show data for
3234
final DateTime date;
3335

3436
const NutritionalDiaryArguments(this.plan, this.date);
3537
}
3638

37-
class NutritionalDiaryScreen extends StatelessWidget {
39+
class NutritionalDiaryScreen extends StatefulWidget {
3840
const NutritionalDiaryScreen();
3941
static const routeName = '/nutritional-diary';
4042

4143
@override
42-
Widget build(BuildContext context) {
44+
State<NutritionalDiaryScreen> createState() => _NutritionalDiaryScreenState();
45+
}
46+
47+
class _NutritionalDiaryScreenState extends State<NutritionalDiaryScreen> {
48+
NutritionalPlan? _plan;
49+
late DateTime date;
50+
StreamSubscription? _subscription;
51+
52+
@override
53+
void didChangeDependencies() {
54+
super.didChangeDependencies();
4355
final args = ModalRoute.of(context)!.settings.arguments as NutritionalDiaryArguments;
56+
date = args.date;
57+
58+
final stream =
59+
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlan(args.plan);
60+
_subscription = stream.listen((plan) {
61+
if (!context.mounted) {
62+
return;
63+
}
64+
setState(() {
65+
_plan = plan;
66+
});
67+
});
68+
}
4469

70+
@override
71+
Widget build(BuildContext context) {
4572
return Scaffold(
4673
appBar: AppBar(
47-
title: Text(DateFormat.yMd(Localizations.localeOf(context).languageCode).format(args.date)),
74+
title: Text(DateFormat.yMd(Localizations.localeOf(context).languageCode).format(date)),
4875
),
4976
body: Consumer<NutritionPlansProvider>(
5077
builder: (context, nutritionProvider, child) => SingleChildScrollView(
5178
child: Padding(
5279
padding: const EdgeInsets.all(8.0),
53-
child: NutritionalDiaryDetailWidget(args.plan, args.date),
80+
child: _plan == null
81+
? const Text('plan not found')
82+
: NutritionalDiaryDetailWidget(_plan!, date),
5483
),
5584
),
5685
),

0 commit comments

Comments
 (0)