mirror of
https://github.com/supleed2/ELEC60013-ES-CW1.git
synced 2024-12-22 21:45:48 +00:00
Added metrics page
This commit is contained in:
parent
cdcd7d6d6b
commit
716d2f7b62
|
@ -2,5 +2,4 @@ package com.legbarkr.leg_barkr_app
|
|||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
||||
class MainActivity: FlutterActivity()
|
||||
|
|
|
@ -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'),
|
||||
],
|
||||
|
|
16
lib/model/metrics_data.dart
Normal file
16
lib/model/metrics_data.dart
Normal 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
|
||||
);
|
||||
}
|
6
lib/model/temp_series.dart
Normal file
6
lib/model/temp_series.dart
Normal 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
13
lib/utils/constants.dart
Normal 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;
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
26
lib/view/metrics/metrics_min_max.dart
Normal file
26
lib/view/metrics/metrics_min_max.dart
Normal 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))
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
98
lib/view/metrics/metrics_now.dart
Normal file
98
lib/view/metrics/metrics_now.dart
Normal 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)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
54
lib/view/metrics/metrics_page.dart
Normal file
54
lib/view/metrics/metrics_page.dart
Normal 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)
|
||||
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
32
lib/view/metrics/metrics_row.dart
Normal file
32
lib/view/metrics/metrics_row.dart
Normal 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)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
27
lib/view/metrics/metrics_summary.dart
Normal file
27
lib/view/metrics/metrics_summary.dart
Normal 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)
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
36
lib/view/metrics/temp_chart.dart
Normal file
36
lib/view/metrics/temp_chart.dart
Normal 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),
|
||||
),)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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),
|
||||
|
|
14
pubspec.lock
14
pubspec.lock
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue