Commit 9578ba1

derdilla <derdilla06@gmail.com>
2023-05-02 15:53:38
FEAT: make graph history browsable
1 parent 6fbebb1
Changed files (4)
lib/components/measurement_graph.dart
@@ -25,22 +25,9 @@ class _LineChart extends StatelessWidget {
                 builder: (context, settings, child) {
                   return Consumer<BloodPressureModel>(
                     builder: (context, model, child) {
-                      late final Future<UnmodifiableListView<BloodPressureRecord>> dataFuture;
-                      DateTime now = DateTime.now();
-                      switch (settings.graphStepSize) {
-                        case TimeStep.day:
-                          dataFuture = model.getInTimeRange(DateTime(now.year, now.month, now.day), now);
-                          break;
-                        case TimeStep.month:
-                          dataFuture = model.getInTimeRange(DateTime(now.year, now.month), now);
-                          break;
-                        case TimeStep.year:
-                          dataFuture = model.getInTimeRange(DateTime(now.year), now);
-                          break;
-                        case TimeStep.lifetime:
-                          dataFuture = model.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), now);
-                          break;
-                      }
+                      var end = settings.graphEnd;
+                      if (settings.graphStepSize == TimeStep.lifetime) end = DateTime.now();
+                      final dataFuture = model.getInTimeRange(settings.graphStart, end);
 
                       return FutureBuilder<UnmodifiableListView<BloodPressureRecord>>(
                           future: dataFuture,
@@ -166,37 +153,112 @@ class _LineChart extends StatelessWidget {
 class MeasurementGraph extends StatelessWidget {
   const MeasurementGraph({super.key});
 
+  void moveGraphWithStep(int directionalStep, Settings settings) {
+    final oldStart = settings.graphStart;
+    final oldEnd = settings.graphEnd;
+    switch (settings.graphStepSize) {
+      case TimeStep.day:
+        settings.graphStart = oldStart.copyWith(day: oldStart.day + directionalStep);
+        settings.graphEnd = oldEnd.copyWith(day: oldEnd.day + directionalStep);
+        break;
+      case TimeStep.month:
+        settings.graphStart = oldStart.copyWith(month: oldStart.month + directionalStep);
+        settings.graphEnd = oldEnd.copyWith(month: oldEnd.month + directionalStep);
+        break;
+      case TimeStep.year:
+        settings.graphStart = oldStart.copyWith(year: oldStart.year + directionalStep);
+        settings.graphEnd = oldEnd.copyWith(year: oldEnd.year + directionalStep);
+        break;
+      case TimeStep.lifetime:
+        settings.graphStart = DateTime.fromMillisecondsSinceEpoch(0);
+        settings.graphEnd = oldStart;
+        break;
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
-    // TODO: implement build
     return SizedBox(
-      height: 1000,
+      height: 290,
       child: Padding(
         padding: const EdgeInsets.only(right: 16, left: 6, top: 2),
         child: Column(
           children: [
+            const SizedBox(height: 20,),
             _LineChart(),
+            const SizedBox(height: 7,),
             Consumer<Settings>(
                 builder: (context, settings, child) {
-                  return Container(
-                    color: Colors.white,
-                    child: DropdownButton<int>(
-                      value: settings.graphStepSize,
-                      onChanged: (int? value) {
-                        if (value != null) {
-                          settings.graphStepSize = value;
-                        }
-                      },
-                      dropdownColor: Colors.white,
-                      items: TimeStep.options.map<DropdownMenuItem<int>>((v) {
-                        return DropdownMenuItem(
-                            value: v,
-                            child: Text(
-                                TimeStep.getName(v)
-                            )
-                        );
-                      }).toList(),
-                    ),
+                  return Row(
+                    children: [
+                      Expanded(
+                        flex: 30,
+                        child: MaterialButton(
+                          onPressed: () {
+                            moveGraphWithStep(-1, settings);
+                          },
+                          child: const Icon(
+                            Icons.chevron_left,
+                            size: 48,
+                          ),
+                        ),
+                      ),
+
+                      Expanded(
+                        flex: 40,
+                          child: DropdownButton<int>(
+                            value: settings.graphStepSize,
+                            isExpanded: true,
+                            onChanged: (int? value) {
+                              if (value != null) {
+                                settings.graphStepSize = value;
+                                final now = DateTime.now();
+                                switch (settings.graphStepSize) {
+                                  case TimeStep.day:
+                                    settings.graphStart = DateTime(now.year, now.month, now.day);
+                                    settings.graphEnd = settings.graphStart.copyWith(day: now.day + 1);
+                                    break;
+                                  case TimeStep.month:
+                                    settings.graphStart = DateTime(now.year, now.month);
+                                    settings.graphEnd = settings.graphStart.copyWith(month: now.month + 1);
+                                    break;
+                                  case TimeStep.year:
+                                    settings.graphStart = DateTime(now.year);
+                                    settings.graphEnd = settings.graphStart.copyWith(year: now.year + 1);
+                                    break;
+                                  case TimeStep.lifetime:
+                                    settings.graphStart = DateTime.fromMillisecondsSinceEpoch(0);
+                                    settings.graphEnd = now;
+                                    break;
+                                }
+                              }
+                            },
+                            dropdownColor: Colors.white,
+                            items: TimeStep.options.map<DropdownMenuItem<int>>((v) {
+                              return DropdownMenuItem(
+                                  value: v,
+                                  child: Text(
+                                      TimeStep.getName(v)
+                                  )
+                              );
+                            }).toList(),
+                          ),
+                      ),
+
+
+                      Expanded(
+                        flex: 30,
+                        child: MaterialButton(
+                          onPressed: () {
+                            moveGraphWithStep(1, settings);
+                          },
+                          child: const Icon(
+                            Icons.chevron_right,
+                            size: 48,
+                          ),
+                        ),
+                      ),
+                    ]
                   );
                 }
             )
lib/model/settings.dart
@@ -16,6 +16,8 @@ class Settings extends ChangeNotifier {
   late final Database _database;
 
   late int _graphStepSize;
+  late DateTime _graphStart;
+  late DateTime _graphEnd;
 
   Settings._create();
   Future<void> _asyncInit() async {
@@ -53,9 +55,13 @@ class Settings extends ChangeNotifier {
 
   Future<void> _loadSettings() async {
     var pGraphStepSize = _getSetting('_graphStepSize');
+    var pGraphStart = _getSetting('_graphStart');
+    var pGraphEnd = _getSetting('_graphEnd');
     // var ...
 
     _graphStepSize = (await pGraphStepSize as int?) ?? TimeStep.day;
+    _graphStart = DateTime.fromMillisecondsSinceEpoch((await pGraphStart as int?) ?? -1);
+    _graphEnd = DateTime.fromMillisecondsSinceEpoch((await pGraphEnd as int?) ?? -1);
     // ...
   }
 
@@ -68,6 +74,24 @@ class Settings extends ChangeNotifier {
     notifyListeners();
   }
 
+  DateTime get graphStart {
+    return _graphStart;
+  }
+  set graphStart(DateTime newGraphStart) {
+    _graphStart = newGraphStart;
+    _saveSetting('_graphStart', newGraphStart.millisecondsSinceEpoch);
+    notifyListeners();
+  }
+
+  DateTime get graphEnd {
+    return _graphEnd;
+  }
+  set graphEnd(DateTime newGraphEnd) {
+    _graphEnd = newGraphEnd;
+    _saveSetting('_graphEnd', newGraphEnd.millisecondsSinceEpoch);
+    notifyListeners();
+  }
+
 }
 
 class TimeStep {
lib/screens/home.dart
@@ -23,12 +23,9 @@ class AppHome extends StatelessWidget {
           padding: _padding,
           child: Column(
             children: [
-              const Expanded(
-                  flex: 40,
-                  child: MeasurementGraph()
-              ),
+              MeasurementGraph(),
               Expanded(
-                flex: 60,
+                flex: 50,
                   child: MeasurementList(context)
               ),
             ]
@@ -37,7 +34,7 @@ class AppHome extends StatelessWidget {
       ),
       floatingActionButton:
         Container(
-          height: 100,
+          height: 110,
           child: Column(
             children: [
               Ink(
test/model_test.dart
@@ -2,18 +2,4 @@ import 'package:flutter_test/flutter_test.dart';
 import 'package:blood_pressure_app/model/blood_pressure.dart';
 
 void main() {
-  test('test storing and loading blood pressures', () {
-    final pressureStorage = BloodPressureModel();
-    var listenerCalled = 0;
-    pressureStorage.addListener(() {
-      expect(pressureStorage.allMeasurements.length, 1);
-      expect(pressureStorage.allMeasurements.first.systolic, 100);
-      expect(pressureStorage.allMeasurements.first.diastolic, 90);
-      expect(pressureStorage.allMeasurements.first.pulse, 80);
-      expect(pressureStorage.allMeasurements.first.notes, "Test comment 测试评论");
-      listenerCalled++;
-    });
-    pressureStorage.add(BloodPressureRecord(DateTime.fromMicrosecondsSinceEpoch(0), 100, 90, 80, "Test comment 测试评论"));
-    expect(listenerCalled, 1);
-  });
 }
\ No newline at end of file