implementing API graphs and getting frustrated at async stuff

This commit is contained in:
Felix 2019-07-18 12:05:09 +01:00
parent bf1046c4e5
commit d7625f7b88
No known key found for this signature in database
GPG key ID: 130EF6DC43E4DD07
7 changed files with 134 additions and 169 deletions

View file

@ -1,17 +0,0 @@
TODO
Show username
add confirm logout
Splash Screen
Splash screen transition - fade
Login
save login details option (checkbox or something)
Navigation
Make it look good
Submit Receipt
Categories
Recurring
'organisation name' dialog works

View file

@ -26,4 +26,4 @@ subprojects {
task clean(type: Delete) {
delete rootProject.buildDir
}
}

View file

@ -2,13 +2,12 @@ import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
enum DataPoint {date, String}
import 'package:charts_flutter/flutter.dart' as charts;
class GraphData {
List<DataPoint> data = new List<DataPoint>();
List<charts.Series> data = new List<charts.Series>();
Future<List<DataPoint>> getGraphData(String graphType) async {
Future<List<charts.Series>> getGraphData(String graphType) async {
/// Graph types:
/// - total_last_week
/// - avg_spend_last_week
@ -18,6 +17,7 @@ class GraphData {
/// HTTP POST request sample:
/// {"graph":"total_last_week","session_key":"blahblahblah"}
charts.Series dataSeries = new charts.Series();
final url = "https://dev.peartrade.org/api/v1/customer/graphs";
SharedPreferences preferences = await SharedPreferences.getInstance();
@ -33,17 +33,62 @@ class GraphData {
if (response.statusCode == 200) {
final responseJson = jsonDecode(response.body);
final labels = responseJson['graph']['labels'];
final data = responseJson['graph']['data'];
// final bounds = responseJson['graph']['bounds']; // why is this even returned?
final List<dynamic> labels = responseJson['graph']['labels'];
final List<dynamic> data = responseJson['graph']['data'];
// final List<String> bounds = responseJson['graph']['bounds']; // why is this even returned?
/*
final data = [
new TimeSeriesSales(new DateTime(2017, 9, 19), 5),
new TimeSeriesSales(new DateTime(2017, 9, 26), 25),
new TimeSeriesSales(new DateTime(2017, 10, 3), 100),
new TimeSeriesSales(new DateTime(2017, 10, 10), 75),
];
*/
List<TimeSeriesSpend> timeSeriesSpendList = new List<TimeSeriesSpend>();
for (int i = 0; i < labels.length; i++) {
print(DateTime(labels[i]));
timeSeriesSpendList.add(new TimeSeriesSpend(data[i], DateTime(labels[i])));
}
return [
new charts.Series<TimeSeriesSpend, DateTime>(
id: 'Spend',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSpend spend, _) => spend.time,
measureFn: (TimeSeriesSpend spend, _) => spend.spend,
data: timeSeriesSpendList,
)
];
/*
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: data,
)*/
// print(labels[5]);
// print(data[5]);
} else {
final errorMessage = json.decode(response.body)['message'];
print("Error: " + errorMessage);
return null;
}
}
}
class TimeSeriesSpend {
final DateTime time;
final int spend;
TimeSeriesSpend(this.spend, this.time);
}

View file

@ -0,0 +1,60 @@
/// Timeseries chart example
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
class SimpleTimeSeriesChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SimpleTimeSeriesChart(this.seriesList, {this.animate});
/// Creates a [TimeSeriesChart] with sample data and no transition.
factory SimpleTimeSeriesChart.withSampleData() {
return new SimpleTimeSeriesChart(
_createSampleData(),
// Disable animations for image tests.
animate: true,
);
}
@override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(
seriesList,
animate: animate,
// Optionally pass in a [DateTimeFactory] used by the chart. The factory
// should create the same type of [DateTime] as the data provided. If none
// specified, the default creates local date time.
dateTimeFactory: const charts.LocalDateTimeFactory(),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
final data = [
new TimeSeriesSales(new DateTime(2017, 9, 19), 5),
new TimeSeriesSales(new DateTime(2017, 9, 26), 25),
new TimeSeriesSales(new DateTime(2017, 10, 3), 100),
new TimeSeriesSales(new DateTime(2017, 10, 10), 75),
];
return [
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: data,
)
];
}
}
/// Sample time series data type.
class TimeSeriesSales {
final DateTime time;
final int sales;
TimeSeriesSales(this.time, this.sales);
}

View file

@ -15,8 +15,8 @@ void main() {
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
GraphData gd = new GraphData();
gd.getGraphData('total_last_week');
// GraphData gd = new GraphData();
// gd.getGraphData('total_last_week');
//var config = ConfigWrapper.of(context);
return new MaterialApp(

View file

@ -204,7 +204,7 @@ class ReceiptPageState extends State<ReceiptPage> {
List<String> getRecurringOptions() {
var options = new List<String>(7);
options[0] = "None";
options[0] = "None"; // this should not be hardcoded and should be fetched from API instead
options[1] = "Daily";
options[2] = "Weekly";
options[3] = "Fortnightly";
@ -556,7 +556,7 @@ class ReceiptPageState extends State<ReceiptPage> {
value: value,
child: Text(value),
);
}).toList(),
}).toList(), // fix errors here by [items] being an empty container while _categoryDropDownItems is null
)
),
],

View file

@ -12,6 +12,9 @@ import 'package:local_spend/common/widgets/charts/grouped_bar_chart.dart';
import 'package:local_spend/common/widgets/charts/scatter_bucketingAxis_legend.dart';
import 'package:local_spend/common/widgets/charts/numeric_line_bar_combo.dart';
import 'package:local_spend/common/widgets/charts/series_legend_with_measures.dart';
import 'package:local_spend/common/widgets/charts/time_series_simple.dart';
import 'package:local_spend/common/apifunctions/get_graph_data.dart';
import 'package:charts_flutter/flutter.dart' as charts;
const URL = "https://flutter.io/";
const demonstration = false;
@ -25,6 +28,9 @@ class StatsPage extends StatefulWidget {
class StatsPageState extends State<StatsPage> {
GraphData graphData = new GraphData();
List<charts.Series> totalLastWeek;
@override
void initState() {
super.initState();
@ -43,6 +49,15 @@ class StatsPageState extends State<StatsPage> {
@override
Widget build(BuildContext context) {
if (graphData.data != null) {
graphData.getGraphData('total_last_week').then((val) {
totalLastWeek = val;
setState(() {
// update view
});
});
}
return PlatformScaffold(
appBar: AppBar(
backgroundColor: Colors.blue[400],
@ -63,30 +78,11 @@ class StatsPageState extends State<StatsPage> {
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
child: ListView(
children: <Widget>[
// some graphs and charts here etc
// Container(
// padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
// child : Text(
// "Really Cool Chart",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 22.0,
// color: Colors.black,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
//
// Container(
// height: 250,
//// width: 250,
// child: new DonutPieChart.withSampleData()
// ),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"GroupedBarChart",
"This Week's Spend",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
@ -100,127 +96,8 @@ class StatsPageState extends State<StatsPage> {
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new GroupedBarChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"BucketingAxisScatterPlotChart",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new BucketingAxisScatterPlotChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,20,0.0,0.0),
child : Text(
"PieOutsideLabelChart",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new PieOutsideLabelChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"DonutAutoLabelChart",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new DonutAutoLabelChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"DonutPieChart",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new DonutPieChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"NumericComboLineBarChart",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new NumericComboLineBarChart.withSampleData()
),
Container(
padding: EdgeInsets.fromLTRB(0.0,17,0.0,0.0),
child : Text(
"LegendWithMeasures",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 200,
// width: 250,
child: new LegendWithMeasures.withSampleData()
child: new SimpleTimeSeriesChart(totalLastWeek),//seriesList: List<charts.Series>
),
],