diff --git a/lib/Widgets/reading_graph.dart b/lib/Widgets/reading_graph.dart new file mode 100644 index 0000000..ecaeb39 --- /dev/null +++ b/lib/Widgets/reading_graph.dart @@ -0,0 +1,88 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' as intl; +import 'dart:math'; + +import '../model/reading.dart'; + +class ReadingGraph extends StatelessWidget { + const ReadingGraph({super.key, required List readings}) + : _readings = readings; + final List _readings; + + @override + Widget build(BuildContext context) { + if (_readings.isEmpty) { + return Text('No readings on record.'); + } + + final spots = _readings + .map( + (e) => FlSpot( + e.dateTime.millisecondsSinceEpoch.toDouble() / 1000 / 60, + e.value), + ) + .toList(); + + return LineChart( + LineChartData( + maxY: _readings.map((e) => e.value).reduce(max) + 0.05, + minY: _readings.map((e) => e.value).reduce(min) - 0.05, + lineBarsData: [ + LineChartBarData( + isCurved: true, + color: Colors.cyan, + barWidth: 2, + isStrokeCapRound: true, + dotData: const FlDotData(show: false), + spots: _readings + .map( + (e) => FlSpot( + e.dateTime.millisecondsSinceEpoch.toDouble() / 1000 / 60, + e.value), + ) + .toList(), + ) + ], + titlesData: FlTitlesData( + bottomTitles: getBottomTitles(spots), + topTitles: const AxisTitles(sideTitles: SideTitles()), + rightTitles: const AxisTitles(sideTitles: SideTitles()), + ), + ), + ); + } + + AxisTitles getBottomTitles(List spots) { + final maxX = double.parse( + spots.map((e) => (e.x)).reduce(max).toStringAsFixed(0)); + final minX = double.parse( + spots.map((e) => e.x).reduce(min).toStringAsFixed(0)); + final middle = + double.parse(spots[spots.length ~/ 2].x.toStringAsFixed(0)) + 4; + + return AxisTitles( + sideTitles: SideTitles( + interval: 1, + showTitles: true, + getTitlesWidget: (value, meta) { + String text = ''; + if (value == maxX) { + text = getDate(spots.first.x); + } else if (double.parse(value.toStringAsFixed(0)) == minX) { + text = getDate(spots.last.x); + } else if (value == middle) { + text = getDate(middle); + } + return Text(text); + }, + ), + ); + } + + String getDate(double value) { + intl.DateFormat hmFormat = intl.DateFormat('Hm'); + return hmFormat.format( + DateTime.fromMillisecondsSinceEpoch((value * 1000 * 60).toInt())); + } +} diff --git a/lib/pages/flood_station_page.dart b/lib/pages/flood_station_page.dart index 57ed9aa..3cd6ba3 100644 --- a/lib/pages/flood_station_page.dart +++ b/lib/pages/flood_station_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../Widgets/reading_graph.dart'; import '../model/flood_station.dart'; import '../model/reading.dart'; import '../services/api.dart'; @@ -18,15 +19,19 @@ class FloodStationPage extends StatelessWidget { future: Api.fetchReadingsFromStation(_floodStation.id), builder: (context, snapshot) { if (snapshot.hasData) { - return ListView.builder( - itemBuilder: (context, index) { - return ListTile( - title: - Text(snapshot.data!.elementAt(index).value.toString()), - ); - }, - itemCount: snapshot.data!.length, + return ReadingGraph( + readings: snapshot.data!, ); + + // return ListView.builder( + // itemBuilder: (context, index) { + // return ListTile( + // title: + // Text(snapshot.data!.elementAt(index).value.toString()), + // ); + // }, + // itemCount: snapshot.data!.length, + // ); } else { return Placeholder(); } diff --git a/lib/services/api.dart b/lib/services/api.dart index bab7bf9..e49d7bf 100644 --- a/lib/services/api.dart +++ b/lib/services/api.dart @@ -25,7 +25,7 @@ class Api { List readings = []; final dateTime = DateTime.now().subtract(Duration(days: 1)); final url = - '$_rootUrl/id/stations/$stationId/readings?since=${dateTime.toIso8601String()}'; + '$_rootUrl/id/stations/$stationId/readings?since=${dateTime.toIso8601String()}Z&_sorted'; final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { final Map jsonStr = jsonDecode(response.body); @@ -33,6 +33,6 @@ class Api { readings.add(Reading.fromMap(str)); } } - return readings; + return readings.reversed.toList(); } } diff --git a/pubspec.yaml b/pubspec.yaml index b56a10f..41d8b76 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: cupertino_icons: ^1.0.8 fl_chart: ^0.70.2 http: ^1.3.0 + intl: ^0.20.2 dev_dependencies: flutter_test: