Added metrics page

This commit is contained in:
Benjamin Ramhorst 2022-02-10 11:06:37 +00:00
parent cdcd7d6d6b
commit 716d2f7b62
16 changed files with 335 additions and 18 deletions

View file

@ -2,5 +2,4 @@ package com.legbarkr.leg_barkr_app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
class MainActivity: FlutterActivity()

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/view/metrics/metrics_page.dart';
import 'package:leg_barkr_app/view/steps/steps_page.dart';
import 'package:leg_barkr_app/view/data_page.dart';
import 'package:leg_barkr_app/view/map_page.dart';
import 'package:leg_barkr_app/view/settings_page.dart';
@ -29,16 +29,21 @@ class _HomeScreenState extends State<HomeScreen> {
body: PageView(
controller: _pageController,
children: const <Widget>[
DataPage(),
MetricsPage(),
StepsPage(),
MapPage(),
SettingsPage()
],
onPageChanged: (page) {
setState(() {
_page = page;
});
},
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.data_usage), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.pets), label: 'Steps'),
BottomNavigationBarItem(icon: Icon(Icons.location_on_outlined), label: 'Location'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
],

View file

@ -0,0 +1,16 @@
class MetricsData{
double currentReading, lowestReading, highestReading, minimumPossible, maximumPossible, lowCutOff, highCutOff;
String metric, units;
MetricsData(
this.currentReading,
this.lowestReading,
this.highestReading,
this.minimumPossible,
this.maximumPossible,
this.lowCutOff,
this.highCutOff,
this.metric,
this.units
);
}

View file

@ -0,0 +1,6 @@
class TempSeries {
final DateTime date;
final double temperature;
TempSeries(this.date, this.temperature);
}

13
lib/utils/constants.dart Normal file
View file

@ -0,0 +1,13 @@
const double LOW_AIR_TEMP_DOG = -5.0;
const double HIGH_AIR_TEMP_DOG = 29.0;
const double LOW_SKIN_TEMP_DOG = 37.5;
const double HIGH_SKIN_TEMP_DOG = 39.4;
const double LOW_HUMIDITY_DOG = 0.0;
const double HIGH_HUMIDITY_DOG = 100.0;
const double MAX_AIR_TEMP = 50.0;
const double MIN_AIR_TEMP = -25.0;
const double MAX_SKIN_TEMP = 42;
const double MIN_SKIN_TEMP = 35;
const double MAX_HUMIDITY = 100;
const double MIN_HUMIDITY = 0;

View file

@ -1,10 +0,0 @@
import 'package:flutter/material.dart';
class DataPage extends StatelessWidget {
const DataPage({ Key? key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Text("Data Page");
}
}

View file

@ -11,7 +11,7 @@ class MapPage extends StatefulWidget {
class _MapPageState extends State<MapPage> {
late GoogleMapController _mapController;
// This will be changed, to center around the dog (once app reads data from the server)
// This will be changed, to center around the dog (once app reads metrics from the server)
final LatLng _center = const LatLng(51.498356, -0.176894);
void _onMapCreated(GoogleMapController mapController) {

View file

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
class MetricsMinMax extends StatelessWidget {
double lowest, highest;
String units;
MetricsMinMax(this.lowest, this.highest, this.units);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.fromLTRB(0.0, 10.0, 5.0, 10.0),
child: Text("Minimum\n" + lowest.toString() + " " + units, textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold))
),
Padding(
padding: EdgeInsets.fromLTRB(5.0, 10.0, 0.0, 10.0),
child: Text("Maximum\n" + highest.toString() + " " + units, textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold))
)
],
);
}
}

View file

@ -0,0 +1,98 @@
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/model/metrics_data.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
class MetricsNow extends StatelessWidget {
MetricsData data;
Color textColor;
bool showGauge;
MetricsNow(this.data, this.textColor, this.showGauge);
@override
Widget build(BuildContext context) {
if (showGauge) {
return SizedBox(
height: 150,
width: 150,
child: SfRadialGauge(
axes: [
RadialAxis(
minimum: data.minimumPossible,
maximum: data.maximumPossible,
ranges: [
GaugeRange(
startValue: data.minimumPossible,
endValue: data.lowCutOff,
color: Colors.blue,
startWidth: 10,
endWidth: 10),
GaugeRange(
startValue: data.lowCutOff,
endValue: data.highCutOff,
color: textColor,
startWidth: 10,
endWidth: 10),
GaugeRange(
startValue: data.highCutOff,
endValue: data.maximumPossible,
color: Colors.red,
startWidth: 10,
endWidth: 10)
],
pointers: [
MarkerPointer(
value: data.currentReading,
color: Colors.black,
markerWidth: 20)
],
annotations: [
GaugeAnnotation(
angle: 90,
positionFactor: 0.75,
widget: Column(
children: [
Text(data.currentReading.toString(),
style: TextStyle(fontSize: 26,
color: textColor,
fontWeight: FontWeight.bold)),
Text(data.units, style: TextStyle(fontSize: 16,
color: textColor,
fontWeight: FontWeight.bold)),
],
)
)
]
)
]
)
);
} else {
return ElevatedButton(
onPressed: () {},
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(data.currentReading.toString(),
style: TextStyle(fontSize: 32,
color: textColor,
fontWeight: FontWeight.bold)),
Text(data.units, style: TextStyle(fontSize: 18,
color: textColor,
fontWeight: FontWeight.bold)),
],
),
style: ElevatedButton.styleFrom(
alignment: Alignment.center,
side: BorderSide(width: 15.0, color: textColor),
shape: CircleBorder(),
padding: EdgeInsets.all(25),
primary: Colors.green,
minimumSize: Size(150, 150),
maximumSize: Size(150, 150)
),
);
}
}
}

View file

@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/model/metrics_data.dart';
import 'package:leg_barkr_app/model/temp_series.dart';
import 'metrics_row.dart';
import 'package:leg_barkr_app/utils/constants.dart' as Constants;
import 'temp_chart.dart';
class MetricsPage extends StatefulWidget {
const MetricsPage({ Key? key }) : super(key: key);
@override
_MetricsPageState createState() => _MetricsPageState();
}
class _MetricsPageState extends State<MetricsPage> {
// Dummy data, will be removed
final List<TempSeries> data = [
TempSeries(DateTime.parse('2022-02-09 20:00:00Z'), 38.4),
TempSeries(DateTime.parse('2022-02-09 19:30:00Z'), 38.8),
TempSeries(DateTime.parse('2022-02-09 19:00:00Z'), 38.2),
TempSeries(DateTime.parse('2022-02-09 18:30:00Z'), 39.2),
TempSeries(DateTime.parse('2022-02-09 18:00:00Z'), 39.5),
TempSeries(DateTime.parse('2022-02-09 17:30:00Z'), 37.8)
];
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(0.0, 50.0, 0.0, 0.0),
child: Expanded(
child: ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Text("Today's summary", textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 36, fontWeight: FontWeight.bold)),
// Dummy data
MetricsRow(new MetricsData(38.6, 38.1, 39.2, Constants.MIN_SKIN_TEMP, Constants.MAX_SKIN_TEMP, Constants.LOW_SKIN_TEMP_DOG, Constants.HIGH_SKIN_TEMP_DOG, "Skin temperature", "°C"), Colors.white, Colors.green, true),
MetricsRow(new MetricsData(22, 16, 34, Constants.MIN_HUMIDITY, Constants.MAX_HUMIDITY, Constants.LOW_HUMIDITY_DOG, Constants.HIGH_HUMIDITY_DOG, "Humidity", "%"), Colors.green, Colors.black, false),
MetricsRow(new MetricsData(24, 21, 29, Constants.MIN_AIR_TEMP, Constants.MAX_AIR_TEMP, Constants.LOW_AIR_TEMP_DOG, Constants.HIGH_AIR_TEMP_DOG, "Air temperature", "°C"), Colors.white, Colors.green, true),
Padding(
padding: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: Text("Today's temperature", textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 36, fontWeight: FontWeight.bold)),
),
TempChart(data)
]
)
)
);
}
}

View file

@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/model/metrics_data.dart';
import 'metrics_now.dart';
import 'metrics_summary.dart';
class MetricsRow extends StatelessWidget {
MetricsData data;
Color backgroundColour;
Color textColour;
bool showGauge;
MetricsRow(this.data, this.backgroundColour, this.textColour, this.showGauge);
@override
Widget build(BuildContext context) {
return Card(
elevation: 10,
shadowColor: Colors.black,
color: backgroundColour,
child: Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: [
MetricsNow(data, textColour, showGauge),
MetricsSummary(data, textColour)
],
),
),
);
}
}

View file

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/model/metrics_data.dart';
import 'metrics_min_max.dart';
class MetricsSummary extends StatelessWidget {
MetricsData data;
Color textColour;
MetricsSummary(this.data, this.textColour);
@override
Widget build(BuildContext context) {
return Expanded(
child: Padding(
padding: EdgeInsets.all(15.0),
child: Center(
child: Column(
children: [
Text(data.metric, textAlign: TextAlign.center, style: TextStyle(color: textColour, fontSize: 24, fontWeight: FontWeight.bold)),
MetricsMinMax(data.lowestReading, data.highestReading, data.units)
],
)
)
)
);
}
}

View file

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:leg_barkr_app/model/temp_series.dart';
import 'package:leg_barkr_app/utils/constants.dart' as Constants;
class TempChart extends StatelessWidget {
List<TempSeries> tempData;
TempChart(this.tempData);
@override
Widget build(BuildContext context) {
List<charts.Series<TempSeries, DateTime>> series = [
charts.Series(
id: "Temperature",
data: tempData,
domainFn: (TempSeries series, _) => series.date,
measureFn: (TempSeries series, _) => series.temperature,
colorFn: (TempSeries series, _) => charts.ColorUtil.fromDartColor(Colors.green)
)
];
return Container(
height: 600,
width: double.infinity,
child: charts.TimeSeriesChart(
series,
animate: true,
primaryMeasureAxis: const charts.NumericAxisSpec(
tickProviderSpec: charts.BasicNumericTickProviderSpec(zeroBound: false),
viewport: charts.NumericExtents(Constants.MIN_SKIN_TEMP, Constants.MAX_SKIN_TEMP),
),)
);
}
}

View file

@ -1,4 +1,3 @@
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'package:leg_barkr_app/model/steps_series.dart';
import 'package:leg_barkr_app/view/steps/steps_chart.dart';
@ -12,7 +11,7 @@ class StepsPage extends StatefulWidget {
}
class _StepsPageState extends State<StepsPage> {
// Dummy data
// Dummy metrics
final List<StepsSeries> data = [
StepsSeries(DateTime.utc(2022, 2, 9), 9867),
StepsSeries(DateTime.utc(2022, 2, 8), 8123),

View file

@ -266,6 +266,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
url: "https://pub.dartlang.org"
source: hosted
version: "19.4.50"
syncfusion_flutter_gauges:
dependency: "direct main"
description:
name: syncfusion_flutter_gauges
url: "https://pub.dartlang.org"
source: hosted
version: "19.4.50"
term_glyph:
dependency: transitive
description:

View file

@ -37,6 +37,8 @@ dependencies:
google_maps_flutter: ^2.1.1
google_maps_flutter_web: ^0.3.2+1
charts_flutter: ^0.12.0
syncfusion_flutter_gauges: ^19.4.50
dev_dependencies:
flutter_test: