Compare commits
2 Commits
bedd9c7d88
...
dfb9b59560
| Author | SHA1 | Date | |
|---|---|---|---|
| dfb9b59560 | |||
| 08c266bc95 |
28
lib/Widgets/flood_station_list_view.dart
Normal file
28
lib/Widgets/flood_station_list_view.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../model/flood_station.dart';
|
||||||
|
import '../pages/flood_station_page.dart';
|
||||||
|
|
||||||
|
class FloodStationListView extends StatelessWidget {
|
||||||
|
const FloodStationListView({super.key, required List<FloodStation> stations})
|
||||||
|
: _stations = stations;
|
||||||
|
|
||||||
|
final List<FloodStation> _stations;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView.builder(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item = _stations.elementAt(index);
|
||||||
|
return ListTile(
|
||||||
|
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (context) => FloodStationPage(floodStation: item),
|
||||||
|
)),
|
||||||
|
title: Text(item.label),
|
||||||
|
subtitle: Text(item.town),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: _stations.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,41 @@
|
|||||||
class FloodStation {
|
class FloodStation {
|
||||||
final String id;
|
final String id;
|
||||||
final String town;
|
final String town;
|
||||||
final double? latestReading;
|
final double lat;
|
||||||
|
final double long;
|
||||||
|
final DateTime? dateOpened;
|
||||||
|
final String catchmentName;
|
||||||
|
final String label;
|
||||||
|
|
||||||
FloodStation({
|
FloodStation({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.town,
|
required this.town,
|
||||||
this.latestReading,
|
required this.lat,
|
||||||
|
required this.long,
|
||||||
|
this.dateOpened,
|
||||||
|
required this.catchmentName,
|
||||||
|
required this.label,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory FloodStation.fromMap(Map<String, dynamic> json) => FloodStation(
|
factory FloodStation.fromMap(Map<String, dynamic> json) => FloodStation(
|
||||||
id: json['@id'] ?? '',
|
id: json['wiskiID'] ?? '',
|
||||||
town: json['town'] ?? '',
|
town: json['town'] ?? '',
|
||||||
latestReading: double.tryParse(json['latestReading']?.toString() ?? ''),
|
lat: parseDoubleValue(json['lat']),
|
||||||
|
long: parseDoubleValue(json['long']),
|
||||||
|
dateOpened: DateTime.tryParse(json['dateOpened'] ?? ''),
|
||||||
|
catchmentName: parseStringValue(json['catchmentName']),
|
||||||
|
label: parseStringValue(json['label']),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static double parseDoubleValue(dynamic value) {
|
||||||
|
if (value is double) return value;
|
||||||
|
if (value is String) return double.parse(value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String parseStringValue(dynamic value) {
|
||||||
|
if (value is String) return value;
|
||||||
|
if (value is List<dynamic>) return value[0];
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
lib/model/reading.dart
Normal file
11
lib/model/reading.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class Reading {
|
||||||
|
final DateTime dateTime;
|
||||||
|
final double value;
|
||||||
|
|
||||||
|
factory Reading.fromMap(Map<String, dynamic> json) => Reading(
|
||||||
|
dateTime: DateTime.parse(json['dateTime']),
|
||||||
|
value: json['value'],
|
||||||
|
);
|
||||||
|
|
||||||
|
Reading({required this.dateTime, required this.value});
|
||||||
|
}
|
||||||
36
lib/pages/flood_station_page.dart
Normal file
36
lib/pages/flood_station_page.dart
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../model/flood_station.dart';
|
||||||
|
import '../model/reading.dart';
|
||||||
|
import '../services/api.dart';
|
||||||
|
|
||||||
|
class FloodStationPage extends StatelessWidget {
|
||||||
|
const FloodStationPage({super.key, required FloodStation floodStation})
|
||||||
|
: _floodStation = floodStation;
|
||||||
|
final FloodStation _floodStation;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(_floodStation.label),
|
||||||
|
),
|
||||||
|
body: FutureBuilder<List<Reading>>(
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Placeholder();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../Widgets/flood_station_list_view.dart';
|
||||||
import '../model/flood_station.dart';
|
import '../model/flood_station.dart';
|
||||||
import '../services/api.dart';
|
import '../services/api.dart';
|
||||||
|
|
||||||
@@ -13,16 +14,11 @@ class LandingPage extends StatelessWidget {
|
|||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return CircularProgressIndicator();
|
return CircularProgressIndicator();
|
||||||
} else if (snapshot.hasData) {
|
} else if (snapshot.hasData) {
|
||||||
return ListView.builder(
|
return FloodStationListView(stations: snapshot.data!);
|
||||||
itemBuilder: (context, index) {
|
} else if (snapshot.hasError) {
|
||||||
return ListTile(
|
return Text(snapshot.error.toString());
|
||||||
title: Text(snapshot.data!.elementAt(index).town),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
itemCount: snapshot.data!.length,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return Placeholder();
|
return Text('An unknown error occured.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:http/http.dart' as http;
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import '../model/flood_station.dart';
|
import '../model/flood_station.dart';
|
||||||
|
import '../model/reading.dart';
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
static const String _rootUrl =
|
static const String _rootUrl =
|
||||||
@@ -18,4 +19,20 @@ class Api {
|
|||||||
}
|
}
|
||||||
return stations;
|
return stations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<Reading>> fetchReadingsFromStation(
|
||||||
|
String stationId) async {
|
||||||
|
List<Reading> readings = [];
|
||||||
|
final dateTime = DateTime.now().subtract(Duration(days: 1));
|
||||||
|
final url =
|
||||||
|
'$_rootUrl/id/stations/$stationId/readings?since=${dateTime.toIso8601String()}';
|
||||||
|
final response = await http.get(Uri.parse(url));
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final Map<String, dynamic> jsonStr = jsonDecode(response.body);
|
||||||
|
for (final str in jsonStr['items']) {
|
||||||
|
readings.add(Reading.fromMap(str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return readings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user