Maps, optimization, testing, code cleanup

This commit is contained in:
Felix 2019-09-02 12:57:14 +01:00
parent c6e69b037b
commit a512549778
29 changed files with 257 additions and 176 deletions

View File

@ -19,7 +19,7 @@
<meta-data android:name="com.google.android.geo.API_KEY" <meta-data android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyDfCRFolRWvgfgSK0UCl5n5rNb5CS7O7KI"/> android:value="AIzaSyD0vsoT6Omnn01hbUiCjAhiS47uFYWnEHE"/>
<!-- Please don't be stupid with the above key--> <!-- Please don't be stupid with the above key-->
<activity <activity

BIN
assets/Consolas.ttf Normal file

Binary file not shown.

BIN
assets/images/cat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
assets/images/text.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

View File

@ -14,7 +14,7 @@ PODS:
- Flutter - Flutter
DEPENDENCIES: DEPENDENCIES:
- Flutter (from `.symlinks/flutter/ios-profile`) - Flutter (from `.symlinks/flutter/ios`)
- google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`) - google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
@ -25,7 +25,7 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
Flutter: Flutter:
:path: ".symlinks/flutter/ios-profile" :path: ".symlinks/flutter/ios"
google_maps_flutter: google_maps_flutter:
:path: ".symlinks/plugins/google_maps_flutter/ios" :path: ".symlinks/plugins/google_maps_flutter/ios"
shared_preferences: shared_preferences:

View File

@ -282,7 +282,7 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-profile/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (

View File

@ -6,7 +6,7 @@
- (BOOL)application:(UIApplication *)application - (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:@"AIzaSyDfCRFolRWvgfgSK0UCl5n5rNb5CS7O7KI"]; [GMSServices provideAPIKey:@"AIzaSyBkVgDYRQoKjCWlGMyl3V6ROzmLEsa5a0w"];
[GeneratedPluginRegistrant registerWithRegistry:self]; [GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch. // Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions]; return [super application:application didFinishLaunchingWithOptions:launchOptions];

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
@ -47,7 +49,5 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@ -4,14 +4,12 @@ import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:charts_flutter/flutter.dart' as charts; import 'package:charts_flutter/flutter.dart' as charts;
/// Customer graph types: https://dev.localspend.co.uk/api/v1/customer/graphs /// Customer graph types: https://dev.localspend.co.uk/api/v1/customer/graphs
/// - total_last_week /// - total_last_week
/// - avg_spend_last_week /// - avg_spend_last_week
/// - total_last_month /// - total_last_month
/// - avg_spend_last_month /// - avg_spend_last_month
/// Organisations' graphs types: to fetch, POST to https://dev.localspend.co.uk/api/stats/[name] as {"session_key":"[boop beep]"} /// Organisations' graphs types: to fetch, POST to https://dev.localspend.co.uk/api/stats/[name] as {"session_key":"[boop beep]"}
/// - organisations_all : organisation /// - organisations_all : organisation
/// - pies : organisation/pies /// - pies : organisation/pies
@ -28,16 +26,13 @@ import 'package:charts_flutter/flutter.dart' as charts;
/// HTTP POST request sample: /// HTTP POST request sample:
/// {"graph":"total_last_week","session_key":"blahblahblah"} /// {"graph":"total_last_week","session_key":"blahblahblah"}
class OrganisationGraph { class OrganisationGraph {
OrganisationGraph( OrganisationGraph(this.chartType, {this.graphsType = ""});
this.chartType,
{this.graphsType = ""}
);
String graphsType = ""; // type of graph, eg customers_last_7_days, sales_last_30_days, purchases_last_30_days etc String graphsType =
String chartType; // type of chart, eg organisations_all, pies, snippets or graphs ""; // type of graph, eg customers_last_7_days, sales_last_30_days, purchases_last_30_days etc
String
chartType; // type of chart, eg organisations_all, pies, snippets or graphs
List<charts.Series<TimeSeriesCustomersOrSales, DateTime>> graph; List<charts.Series<TimeSeriesCustomersOrSales, DateTime>> graph;
@ -53,7 +48,7 @@ class OrganisationGraph {
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesCustomersOrSales spend, _) => spend.time, domainFn: (TimeSeriesCustomersOrSales spend, _) => spend.time,
measureFn: (TimeSeriesCustomersOrSales spend, _) => measureFn: (TimeSeriesCustomersOrSales spend, _) =>
spend.numberOfStuff, spend.numberOfStuff,
data: cachedData, data: cachedData,
) )
]; ];
@ -94,13 +89,12 @@ class OrganisationGraph {
final List<dynamic> labels = responseJson['graph']['labels']; final List<dynamic> labels = responseJson['graph']['labels'];
final List<dynamic> data = responseJson['graph']['data']; final List<dynamic> data = responseJson['graph']['data'];
List<TimeSeriesCustomersOrSales> graphDataList = new List< List<TimeSeriesCustomersOrSales> graphDataList =
TimeSeriesCustomersOrSales>(); new List<TimeSeriesCustomersOrSales>();
for (int i = 0; i < labels.length; i++) { for (int i = 0; i < labels.length; i++) {
graphDataList.add( graphDataList.add(new TimeSeriesCustomersOrSales(
new TimeSeriesCustomersOrSales( data[i] * 1.00, DateTime.parse(labels[i])));
data[i] * 1.00, DateTime.parse(labels[i])));
} }
this.cachedData = graphDataList; this.cachedData = graphDataList;
@ -112,7 +106,7 @@ class OrganisationGraph {
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesCustomersOrSales spend, _) => spend.time, domainFn: (TimeSeriesCustomersOrSales spend, _) => spend.time,
measureFn: (TimeSeriesCustomersOrSales spend, _) => measureFn: (TimeSeriesCustomersOrSales spend, _) =>
spend.numberOfStuff, spend.numberOfStuff,
data: graphDataList, data: graphDataList,
) )
]; ];
@ -125,9 +119,7 @@ class OrganisationGraph {
} catch (error) { } catch (error) {
print(error.toString()); print(error.toString());
} }
} }
} }
class GraphData { class GraphData {
@ -194,7 +186,6 @@ class GraphData {
) )
]; ];
return this.graph; return this.graph;
} else { } else {
final errorMessage = json.decode(response.body)['message']; final errorMessage = json.decode(response.body)['message'];
print("Error: " + errorMessage); print("Error: " + errorMessage);
@ -276,4 +267,4 @@ class TimeSeriesCustomersOrSales {
final DateTime time; final DateTime time;
final double numberOfStuff; final double numberOfStuff;
} }

View File

@ -0,0 +1,92 @@
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:json_annotation/json_annotation.dart';
import 'package:local_spend/common/apifunctions/find_organisations.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart' as gmaps;
// /v1/supplier/location
@JsonSerializable()
class LatLng {
LatLng({
this.lat,
this.lng
});
final double lat, lng;
}
@JsonSerializable()
class Region {
Region({
this.coords,
this.id,
this.name,
this.zoom
});
final LatLng coords;
final String id, name;
final double zoom;
}
@JsonSerializable()
class Location {
Location({
this.organisation,
this.lat,
this.lng
});
final Organisation organisation;
final double lat, lng;
}
@JsonSerializable()
class Locations {
Locations({
this.locations,
this.regions
});
final List<Location> locations;
final List<Region> regions;
}
Future<Locations> getLocations(gmaps.LatLng ne, gmaps.LatLng sw) async {
const pearLocationsURL = 'https://dev.localspend.co.uk/api/v1/supplier/location';
SharedPreferences preferences = await SharedPreferences.getInstance();
Map<String, String> body;
body = {
'session_key': preferences.get('LastToken'),
};
Map<String, Map<String, double>> mapData = {
'north_east': {
'latitude': ne.latitude,
'longitude': ne.longitude
},
'south_west': {
'latitude': sw.latitude,
'longitude': sw.longitude
},
};
final response = await http.post(
pearLocationsURL,
body: json.encode(body),
);
if (response.statusCode == 200) {
print(response.body.toString());
} else {
print(response.body.toString());
throw HttpException(
'Error - ' + response.reasonPhrase,
);
}
}

View File

@ -264,10 +264,7 @@ class AboutDialog extends StatelessWidget {
List<Widget> body = <Widget>[]; List<Widget> body = <Widget>[];
if (icon != null) { if (icon != null) {
body.add( body.add(
IconTheme( IconTheme(data: const IconThemeData(size: 45.0), child: icon),
data: const IconThemeData(size: 45.0),
child: icon
),
); );
} }
@ -277,7 +274,6 @@ class AboutDialog extends StatelessWidget {
child: ListBody( child: ListBody(
children: <Widget>[ children: <Widget>[
Container( Container(
padding: EdgeInsets.only(top: 10),
child: Text(name, style: Theme.of(context).textTheme.title), child: Text(name, style: Theme.of(context).textTheme.title),
), ),
Text(version, style: Theme.of(context).textTheme.body1), Text(version, style: Theme.of(context).textTheme.body1),

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:local_spend/common/apifunctions/request_logout_api.dart'; import 'package:local_spend/common/apifunctions/request_logout_api.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:local_spend/common/functions/save_logout.dart';
void logout(context) { void logout(context) {
_clearLoginDetails().then((_) { _clearLoginDetails().then((_) {

View File

@ -4,21 +4,20 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class PlatformScaffold extends StatelessWidget { class PlatformScaffold extends StatelessWidget {
PlatformScaffold( PlatformScaffold(
{this.key, {this.key,
this.appBar, this.appBar,
this.body, this.body,
this.floatingActionButton, this.floatingActionButton,
this.floatingActionButtonLocation, this.floatingActionButtonLocation,
this.floatingActionButtonAnimator, this.floatingActionButtonAnimator,
this.persistentFooterButtons, this.persistentFooterButtons,
this.drawer, this.drawer,
this.endDrawer, this.endDrawer,
this.bottomNavigationBar, this.bottomNavigationBar,
this.backgroundColor, this.backgroundColor,
this.resizeToAvoidBottomPadding = true, this.resizeToAvoidBottomPadding = true,
this.primary = true}) this.primary = true})
: assert(primary != null), : assert(primary != null),
super(key: key); super(key: key);

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart'; import 'package:simple_animations/simple_animations.dart';
class AnimatedBackground extends StatelessWidget { class AnimatedBackground extends StatelessWidget {
AnimatedBackground( AnimatedBackground(
this.animateColors, this.animateColors,
this.lastColor, this.lastColor,

View File

@ -4,7 +4,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class NumericComboLineBarChart extends StatelessWidget { class NumericComboLineBarChart extends StatelessWidget {
NumericComboLineBarChart(this.seriesList, {this.animate}); NumericComboLineBarChart(this.seriesList, {this.animate});
/// Creates a [LineChart] with sample data and no transition. /// Creates a [LineChart] with sample data and no transition.

View File

@ -8,7 +8,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class BucketingAxisScatterPlotChart extends StatelessWidget { class BucketingAxisScatterPlotChart extends StatelessWidget {
BucketingAxisScatterPlotChart(this.seriesList, {this.animate}); BucketingAxisScatterPlotChart(this.seriesList, {this.animate});
/// Creates a [ScatterPlotChart] with sample data and no transition. /// Creates a [ScatterPlotChart] with sample data and no transition.

View File

@ -372,8 +372,7 @@ class _RenderCheckbox extends RenderToggleable {
final double tShrink = (t - 0.5) * 2.0; final double tShrink = (t - 0.5) * 2.0;
if (_oldValue == null || value == null) { if (_oldValue == null || value == null) {
_drawDash(canvas, origin, tShrink, paint); _drawDash(canvas, origin, tShrink, paint);
} } else {
else {
_drawCheck(canvas, origin, tShrink, paint); _drawCheck(canvas, origin, tShrink, paint);
} }
} }
@ -388,16 +387,14 @@ class _RenderCheckbox extends RenderToggleable {
final double tShrink = 1.0 - tNormalized * 2.0; final double tShrink = 1.0 - tNormalized * 2.0;
if (_oldValue == true) { if (_oldValue == true) {
_drawCheck(canvas, origin, tShrink, paint); _drawCheck(canvas, origin, tShrink, paint);
} } else {
else {
_drawDash(canvas, origin, tShrink, paint); _drawDash(canvas, origin, tShrink, paint);
} }
} else { } else {
final double tExpand = (tNormalized - 0.5) * 2.0; final double tExpand = (tNormalized - 0.5) * 2.0;
if (value == true) { if (value == true) {
_drawCheck(canvas, origin, tExpand, paint); _drawCheck(canvas, origin, tExpand, paint);
} } else {
else {
_drawDash(canvas, origin, tExpand, paint); _drawDash(canvas, origin, tExpand, paint);
} }
} }

View File

@ -12,15 +12,10 @@ void main() {
runApp(MyApp()); runApp(MyApp());
} }
void loadGraphs() { void loadGraphs() {}
}
class GraphWithTitle { class GraphWithTitle {
GraphWithTitle({ GraphWithTitle({this.graph, this.title});
this.graph,
this.title
});
GraphData graph; GraphData graph;
String title; String title;
@ -29,7 +24,7 @@ class GraphWithTitle {
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var graphList = List<GraphWithTitle>(); // TODO: load graphs on app login and send to graph widgets
return new MaterialApp( return new MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
@ -45,7 +40,7 @@ class MyApp extends StatelessWidget {
routes: <String, WidgetBuilder>{ routes: <String, WidgetBuilder>{
"/HomePage": (BuildContext context) => HomePage(), "/HomePage": (BuildContext context) => HomePage(),
"/LoginPage": (BuildContext context) => LoginPage(), "/LoginPage": (BuildContext context) => LoginPage(),
'/MapPage': (BuildContext context) => MapSample(), '/MapPage': (BuildContext context) => MapPage(),
"/ReceiptPage": (BuildContext context) => ReceiptPage2(), "/ReceiptPage": (BuildContext context) => ReceiptPage2(),
"/MorePage": (BuildContext context) => MorePage(), "/MorePage": (BuildContext context) => MorePage(),
}, },

View File

@ -76,10 +76,10 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
child: totalLastWeekGraph.graph != null child: totalLastWeekGraph.graph != null
? new charts.TimeSeriesChart(totalLastWeekGraph.graph) ? new charts.TimeSeriesChart(totalLastWeekGraph.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.orange), valueColor:
) new AlwaysStoppedAnimation<Color>(Colors.orange),
), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>> )), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), ),
), ),
Container( Container(
@ -103,9 +103,8 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
? new charts.TimeSeriesChart(avgSpendLastWeekGraph.graph) ? new charts.TimeSeriesChart(avgSpendLastWeekGraph.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.blue), valueColor: new AlwaysStoppedAnimation<Color>(Colors.blue),
) )), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), ),
), ),
Container( Container(
@ -128,10 +127,9 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
child: totalLastMonthGraph.graph != null child: totalLastMonthGraph.graph != null
? new charts.TimeSeriesChart(totalLastMonthGraph.graph) ? new charts.TimeSeriesChart(totalLastMonthGraph.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.green), valueColor: new AlwaysStoppedAnimation<Color>(Colors.green),
) )), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), ),
), ),
Container( Container(
@ -154,10 +152,9 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
child: avgSpendLastMonth.graph != null child: avgSpendLastMonth.graph != null
? new charts.TimeSeriesChart(avgSpendLastMonth.graph) ? new charts.TimeSeriesChart(avgSpendLastMonth.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.red), valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
) )), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), //List<Series<dynamic, DateTime>>es<dynamic, DateTime>>
), ),
), ),
], ],

View File

@ -31,7 +31,7 @@ class _HomePageState extends State<HomePageWidget> {
static List<Widget> _widgetOptions = <Widget>[ static List<Widget> _widgetOptions = <Widget>[
ReceiptPage2(), ReceiptPage2(),
StatsPage(), StatsPage(),
MapSample(), MapPage(),
MorePage() MorePage()
]; ];
@ -43,7 +43,6 @@ class _HomePageState extends State<HomePageWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Center( body: Center(
child: _widgetOptions.elementAt(_selectedIndex), child: _widgetOptions.elementAt(_selectedIndex),

View File

@ -20,10 +20,8 @@ class LoginPage extends StatefulWidget {
class LoginPageState extends State<LoginPage> { class LoginPageState extends State<LoginPage> {
bool _isLoggingIn = false; bool _isLoggingIn = false;
final TextEditingController _emailController = final TextEditingController _emailController = TextEditingController();
TextEditingController(); final TextEditingController _passwordController = TextEditingController();
final TextEditingController _passwordController =
TextEditingController();
bool _saveLoginDetails = true; bool _saveLoginDetails = true;
FocusNode focusNode; // added so focus can move automatically FocusNode focusNode; // added so focus can move automatically

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:async'; import 'dart:async';
import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart' as gmaps;
import 'package:local_spend/common/apifunctions/get_map_data.dart' as mapData;
import 'package:local_spend/common/platform/platform_scaffold.dart'; import 'package:local_spend/common/platform/platform_scaffold.dart';
class MapPage extends StatefulWidget { class MapPage extends StatefulWidget {
@ -13,13 +14,32 @@ class MapPage extends StatefulWidget {
} }
class _MapPageState extends State<MapPage> { class _MapPageState extends State<MapPage> {
final Map<String, gmaps.Marker> _markers = {};
Future<void> _onMapCreated(gmaps.GoogleMapController controller) async {
final region = await controller.getVisibleRegion();
final locations = await mapData.getLocations(region.northeast, region.southwest);
setState(() {
_markers.clear();
for (final location in locations.locations) {
final marker = gmaps.Marker(
markerId: gmaps.MarkerId(location.organisation.name),
position: gmaps.LatLng(location.lat, location.lng),
infoWindow: gmaps.InfoWindow(
title: location.organisation.name,
snippet: location.organisation.postcode,
),
);
_markers[location.organisation.name] = marker;
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PlatformScaffold( return PlatformScaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.blue[400], backgroundColor: Colors.blue[400],
title: Text( title: Text(
"Submit Receipt", "Map",
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
color: Colors.white, color: Colors.white,
@ -28,34 +48,15 @@ class _MapPageState extends State<MapPage> {
centerTitle: true, centerTitle: true,
iconTheme: IconThemeData(color: Colors.black), iconTheme: IconThemeData(color: Colors.black),
), ),
body: null, body: gmaps.GoogleMap(
); myLocationButtonEnabled: false,
} mapType: gmaps.MapType.hybrid,
} onMapCreated: _onMapCreated,
initialCameraPosition: gmaps.CameraPosition(
class MapSample extends StatefulWidget { target: gmaps.LatLng(54.0411301, -2.8104042),
@override zoom: 15,
State<MapSample> createState() => MapSampleState(); ),
} ),
class MapSampleState extends State<MapSample> {
Completer<GoogleMapController> _controller = Completer();
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
@override
Widget build(BuildContext context) {
return new Scaffold(
// body: GoogleMap(
// mapType: MapType.hybrid,
// initialCameraPosition: _kGooglePlex,
// onMapCreated: (GoogleMapController controller) {
// _controller.complete(controller);
// },
// ),
); );
} }
} }

View File

@ -101,6 +101,7 @@ class MorePageState extends State<MorePage> {
height: 35, height: 35,
child: RaisedButton( child: RaisedButton(
onPressed: () => {}, onPressed: () => {},
// launch(- something -),
child: Text("Contact us", child: Text("Contact us",
style: TextStyle( style: TextStyle(
color: Colors.white, fontSize: 18.0)), color: Colors.white, fontSize: 18.0)),
@ -120,25 +121,6 @@ class MorePageState extends State<MorePage> {
onPressed: () => onPressed: () =>
launch('http://www.peartrade.org')), launch('http://www.peartrade.org')),
), ),
Container(
height: 35,
margin: EdgeInsets.fromLTRB(10, 20, 10, 0),
child: Material(
child: OutlineButton(
child: Text(
'Shadowcat Systems',
style: TextStyle(
color: Colors.black, fontSize: 18.0
/// I don't know what to do with this button
),
),
onPressed: () => launch('https://shadow.cat/'),
),
color: Colors.lightGreenAccent,
shadowColor: Colors.transparent,
),
),
], ],
); );
}, },
@ -170,6 +152,33 @@ class MorePageState extends State<MorePage> {
), ),
), ),
Padding(
padding: EdgeInsets.fromLTRB(30.0, 20.0, 30.0, 0.0),
child: Container(
height: 75.0,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(3),
onTap: () => launch('https://shadow.cat'),
child: Column(
children: [
Align(
child: Text("Developed by"),
alignment: Alignment.centerLeft),
FittedBox(
fit: BoxFit.fitHeight,
child: Image(
image: ExactAssetImage('assets/images/text.png'),
),
),
],
),
),
),
),
),
// Padding( // Padding(
// padding: EdgeInsets.fromLTRB(30.0, 20.0, 30.0, 0.0), // padding: EdgeInsets.fromLTRB(30.0, 20.0, 30.0, 0.0),
// child: Container( // child: Container(

View File

@ -12,7 +12,6 @@ class OrgGraphs extends StatefulWidget {
} }
class _OrgGraphsState extends State<OrgGraphs> { class _OrgGraphsState extends State<OrgGraphs> {
/// Organisations' graphs types: to fetch, POST to https://dev.localspend.co.uk/api/stats/[graph_type] as {"session_key":"[boop beep]"} /// Organisations' graphs types: to fetch, POST to https://dev.localspend.co.uk/api/stats/[graph_type] as {"session_key":"[boop beep]"}
/// - organisations_all : organisation /// - organisations_all : organisation
/// - pies : organisation/pies /// - pies : organisation/pies
@ -30,9 +29,12 @@ class _OrgGraphsState extends State<OrgGraphs> {
/// {"graph":"total_last_week","session_key":"blahblahblah"} /// {"graph":"total_last_week","session_key":"blahblahblah"}
// OrganisationGraph customersLastWeek = new OrganisationGraph("graphs", graphsType: "customers_last_7_days"); // OrganisationGraph customersLastWeek = new OrganisationGraph("graphs", graphsType: "customers_last_7_days");
OrganisationGraph customersLastMonth = new OrganisationGraph("graphs", graphsType: "customers_last_30_days"); OrganisationGraph customersLastMonth =
OrganisationGraph salesLastMonth = new OrganisationGraph("graphs", graphsType: "sales_last_30_days"); new OrganisationGraph("graphs", graphsType: "customers_last_30_days");
OrganisationGraph purchasesLastMonth = new OrganisationGraph("graphs", graphsType: "purchases_last_30_days"); //purchases_last_30_days OrganisationGraph salesLastMonth =
new OrganisationGraph("graphs", graphsType: "sales_last_30_days");
OrganisationGraph purchasesLastMonth = new OrganisationGraph("graphs",
graphsType: "purchases_last_30_days"); //purchases_last_30_days
@override @override
void initState() { void initState() {
@ -114,7 +116,8 @@ class _OrgGraphsState extends State<OrgGraphs> {
child: customersLastMonth.graph != null child: customersLastMonth.graph != null
? new charts.TimeSeriesChart(customersLastMonth.graph) ? new charts.TimeSeriesChart(customersLastMonth.graph)
: Center( : Center(
child: CircularProgressIndicator()), //List<Series<dynamic, DateTime>> child:
CircularProgressIndicator()), //List<Series<dynamic, DateTime>>
), ),
), ),
@ -138,9 +141,9 @@ class _OrgGraphsState extends State<OrgGraphs> {
child: salesLastMonth.graph != null child: salesLastMonth.graph != null
? new charts.TimeSeriesChart(salesLastMonth.graph) ? new charts.TimeSeriesChart(salesLastMonth.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.green), valueColor: new AlwaysStoppedAnimation<Color>(Colors.green),
)), //List<Series<dynamic, DateTime>> )), //List<Series<dynamic, DateTime>>
), ),
), ),
@ -164,13 +167,11 @@ class _OrgGraphsState extends State<OrgGraphs> {
child: purchasesLastMonth.graph != null child: purchasesLastMonth.graph != null
? new charts.TimeSeriesChart(purchasesLastMonth.graph) ? new charts.TimeSeriesChart(purchasesLastMonth.graph)
: Center( : Center(
child: CircularProgressIndicator( child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.red), valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
) )), //List<Series<dynamic, DateTime>>
), //List<Series<dynamic, DateTime>>
), ),
), ),
], ],
); );
} }

View File

@ -92,7 +92,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
submitReceiptAPI(context, receipt); submitReceiptAPI(context, receipt);
} }
List<String> _sampleRecurringOptions = new List<String>(7); List<String> _recurringOptions = new List<String>(7);
List<String> _categories = new List<String>(); List<String> _categories = new List<String>();
@override @override
@ -100,13 +100,15 @@ class ReceiptPage2State extends State<ReceiptPage2> {
super.initState(); super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var _widgetHeight = MediaQuery.of(context).size.height * 0.06 < 40.0 var _widgetHeight = MediaQuery.of(context).size.height * 0.06 < 40.0
? 40.0 ? 40.0
: MediaQuery.of(context).size.height * 0.06; : MediaQuery.of(context).size.height * 0.06;
var _fontSize = _widgetHeight * 0.45;
var _fontSizeButton = _widgetHeight * 0.5;
if (_categories.isEmpty) { if (_categories.isEmpty) {
Future<List<String>> _futureCats = getCats(); Future<List<String>> _futureCats = getCats();
_categories.add("Fetching categories..."); _categories.add("Fetching categories...");
@ -117,13 +119,13 @@ class ReceiptPage2State extends State<ReceiptPage2> {
}); });
} }
_sampleRecurringOptions[0] = "None"; _recurringOptions[0] = "None";
_sampleRecurringOptions[1] = "Daily"; _recurringOptions[1] = "Daily";
_sampleRecurringOptions[2] = "Weekly"; _recurringOptions[2] = "Weekly";
_sampleRecurringOptions[3] = "Fortnightly"; _recurringOptions[3] = "Fortnightly";
_sampleRecurringOptions[4] = "Monthly"; _recurringOptions[4] = "Monthly";
_sampleRecurringOptions[5] = "Quarterly"; _recurringOptions[5] = "Quarterly";
_sampleRecurringOptions[6] = "Yearly"; _recurringOptions[6] = "Yearly";
// these will be difficult to fetch from server as they are coded into the site's HTML rather than fetched // these will be difficult to fetch from server as they are coded into the site's HTML rather than fetched
return PlatformScaffold( return PlatformScaffold(
@ -175,7 +177,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Date/Time", "Date/Time",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -233,7 +235,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
: '${new DateFormat.MMMd().format(transaction.date)}' + : '${new DateFormat.MMMd().format(transaction.date)}' +
" at " + " at " +
'${new DateFormat.Hm().format(transaction.date)}', '${new DateFormat.Hm().format(transaction.date)}',
style: TextStyle(color: Colors.white, fontSize: 22.0), style: TextStyle(
color: Colors.white, fontSize: _fontSizeButton),
), ),
color: Colors.blue, color: Colors.blue,
), ),
@ -257,7 +260,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Payee", "Payee",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -291,7 +294,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
.substring(0, 12) + .substring(0, 12) +
"..." "..."
: transaction.organisation.name, : transaction.organisation.name,
style: TextStyle(color: Colors.white, fontSize: 22.0), style: TextStyle(
color: Colors.white, fontSize: _fontSizeButton),
), ),
color: Colors.blue, color: Colors.blue,
), ),
@ -315,7 +319,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Recurring", "Recurring",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -328,7 +332,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
width: MediaQuery.of(context).size.width * 0.6, width: MediaQuery.of(context).size.width * 0.6,
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
transaction.recurring = _sampleRecurringOptions[0]; transaction.recurring = _recurringOptions[0];
setState(() {}); setState(() {});
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
@ -341,13 +345,13 @@ class ReceiptPage2State extends State<ReceiptPage2> {
3, 3,
child: CupertinoPicker( child: CupertinoPicker(
backgroundColor: Colors.white, backgroundColor: Colors.white,
children: _sampleRecurringOptions children: _recurringOptions
.map((thisOption) => Text(thisOption, .map((thisOption) => Text(thisOption,
style: TextStyle(fontSize: 30))) style: TextStyle(fontSize: 30)))
.toList(), .toList(),
onSelectedItemChanged: ((newValue) { onSelectedItemChanged: ((newValue) {
transaction.recurring = transaction.recurring =
_sampleRecurringOptions[newValue]; _recurringOptions[newValue];
setState(() {}); setState(() {});
}), }),
magnification: 1.1, magnification: 1.1,
@ -361,7 +365,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
transaction.recurring == null transaction.recurring == null
? 'None' ? 'None'
: transaction.recurring, : transaction.recurring,
style: TextStyle(color: Colors.white, fontSize: 22.0), style: TextStyle(
color: Colors.white, fontSize: _fontSizeButton),
), ),
color: Colors.blue, color: Colors.blue,
), ),
@ -383,7 +388,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Category", "Category",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -407,7 +412,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
height: MediaQuery.of(context) height: MediaQuery.of(context)
.copyWith() .copyWith()
.size .size
.height / 3, .height /
3,
child: CupertinoPicker( child: CupertinoPicker(
backgroundColor: Colors.white, backgroundColor: Colors.white,
children: _categories children: _categories
@ -432,7 +438,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
transaction.category == null transaction.category == null
? 'None' ? 'None'
: transaction.category, : transaction.category,
style: TextStyle(color: Colors.white, fontSize: 22.0), style: TextStyle(
color: Colors.white, fontSize: _fontSizeButton),
), ),
color: Colors.blue, color: Colors.blue,
), ),
@ -456,7 +463,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Essential", "Essential",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -492,7 +499,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
child: Text( child: Text(
"Amount", "Amount",
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: _fontSize,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@ -505,7 +512,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
width: MediaQuery.of(context).size.width * 0.6, width: MediaQuery.of(context).size.width * 0.6,
child: TextField( child: TextField(
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: _fontSize,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: transaction.amount, controller: transaction.amount,

View File

@ -27,10 +27,7 @@ class _SplashScreenState extends State<SplashScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var drawer = Drawer();
return PlatformScaffold( return PlatformScaffold(
drawer: drawer,
body: Container( body: Container(
decoration: BoxDecoration(color: Colors.white), decoration: BoxDecoration(color: Colors.white),
child: Column( child: Column(
@ -38,7 +35,6 @@ class _SplashScreenState extends State<SplashScreen> {
Expanded( Expanded(
child: Container( child: Container(
margin: EdgeInsets.all(15), margin: EdgeInsets.all(15),
alignment: FractionalOffset(0.5, 0.3),
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage('assets/images/launch_image.png'), image: AssetImage('assets/images/launch_image.png'),

View File

@ -10,8 +10,10 @@ const demonstration = false;
class StatsPage extends StatefulWidget { class StatsPage extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
print("TODO: The 'stats' page should be loaded on login and cached rather than reloading on every opening of the page."); print(
print("Create new List<GraphData> in instantiated MyApp() and pass that or load it from this class' child with (graphs = super.graphList) or something."); "TODO: The 'stats' page should be loaded on login and cached rather than reloading on every opening of the page.");
print(
"Create new List<GraphData> in instantiated MyApp() and pass that or load it from this class' child with (graphs = super.graphList) or something.");
return new StatsPageState(); return new StatsPageState();
} }
} }

View File

@ -57,6 +57,11 @@ flutter:
- assets/ - assets/
- assets/images/ - assets/images/
- assets/images/launch_image.png - assets/images/launch_image.png
fonts:
- family: Consolas
fonts:
- asset: assets/Consolas.ttf
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware. # https://flutter.io/assets-and-images/#resolution-aware.