Code is B-E-A-U-TIFUL! All complies to standards.
Complies to flutter/dart 'pedantic' coding standards (their name, not mine)
This commit is contained in:
parent
19021a9a09
commit
55310068ea
55 changed files with 915 additions and 785 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -236,3 +236,4 @@ fabric.properties
|
|||
|
||||
# End of https://www.gitignore.io/api/android,flutter,androidstudio
|
||||
lib/common/felixApiCreds.dart
|
||||
android/app/src/main/AndroidManifest.xml
|
||||
|
|
18
analysis_options.yaml
Normal file
18
analysis_options.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
include: package:pedantic/analysis_options.yaml
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
- lib/src/locations.g.dart
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- camel_case_types
|
||||
- empty_constructor_bodies
|
||||
- annotate_overrides
|
||||
- avoid_init_to_null
|
||||
- constant_identifier_names
|
||||
- one_member_abstracts
|
||||
- slash_for_doc_comments
|
||||
- sort_constructors_first
|
||||
- unnecessary_brace_in_string_interps
|
|
@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
|
|||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
compileSdkVersion 28
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
|
|
|
@ -14,8 +14,14 @@
|
|||
FlutterApplication and put your custom class here. -->
|
||||
<application
|
||||
android:name="io.flutter.app.FlutterApplication"
|
||||
android:label="local_spend"
|
||||
android:label="SpendTracker"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
|
||||
|
||||
<meta-data android:name="com.google.android.geo.API_KEY"
|
||||
android:value="AIzaSyDfCRFolRWvgfgSK0UCl5n5rNb5CS7O7KI"/>
|
||||
<!-- Please don't be stupid with the above key-->
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
|
@ -31,10 +37,6 @@
|
|||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||
android:value="true" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
android:value="API KEY HERE" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
platform :ios, '9.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- google_maps_flutter (0.0.1):
|
||||
- Flutter
|
||||
- GoogleMaps
|
||||
- GoogleMaps (3.3.0):
|
||||
- GoogleMaps/Maps (= 3.3.0)
|
||||
- GoogleMaps/Base (3.3.0)
|
||||
- GoogleMaps/Maps (3.3.0):
|
||||
- GoogleMaps/Base
|
||||
- shared_preferences (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher (0.0.1):
|
||||
|
@ -7,12 +15,19 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `.symlinks/flutter/ios`)
|
||||
- google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`)
|
||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- GoogleMaps
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: ".symlinks/flutter/ios"
|
||||
google_maps_flutter:
|
||||
:path: ".symlinks/plugins/google_maps_flutter/ios"
|
||||
shared_preferences:
|
||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||
url_launcher:
|
||||
|
@ -20,9 +35,11 @@ EXTERNAL SOURCES:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: 58dd7d1b27887414a370fcccb9e645c08ffd7a6a
|
||||
google_maps_flutter: 78a52114c898b42ea647919679a4c58b70abe876
|
||||
GoogleMaps: cfee83da305b9aaeccf92c24ac79df11c3003492
|
||||
shared_preferences: 1feebfa37bb57264736e16865e7ffae7fc99b523
|
||||
url_launcher: 0067ddb8f10d36786672aa0722a21717dba3a298
|
||||
|
||||
PODFILE CHECKSUM: aff02bfeed411c636180d6812254b2daeea14d09
|
||||
PODFILE CHECKSUM: 3389836f37640698630b8f0670315d626d5f1469
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
|
|
|
@ -163,6 +163,7 @@
|
|||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
ACE3DC71CDB8FA5537935604 /* [CP] Embed Pods Frameworks */,
|
||||
E6C2807EE928990FB790046F /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -292,6 +293,24 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E6C2807EE928990FB790046F /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
|
||||
"${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Resources/GoogleMaps.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMaps.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -390,6 +409,7 @@
|
|||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -519,6 +539,7 @@
|
|||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -546,6 +567,7 @@
|
|||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#include "AppDelegate.h"
|
||||
#include "GeneratedPluginRegistrant.h"
|
||||
#import "GoogleMaps/GoogleMaps.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[GMSServices provideAPIKey:@"AIzaSyDfCRFolRWvgfgSK0UCl5n5rNb5CS7O7KI"];
|
||||
[GeneratedPluginRegistrant registerWithRegistry:self];
|
||||
// Override point for customization after application launch.
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
|||
import 'dart:async';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:local_spend/common/functions/get_token.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Future<List<String>> getCategories() async {
|
||||
const url = "https://dev.localspend.co.uk/api/search/category";
|
||||
|
@ -38,7 +37,6 @@ Future<List<String>> getCategories() async {
|
|||
|
||||
int i = 1; // starts on 1. that was annoying to debug!
|
||||
while (true) {
|
||||
|
||||
if (categoriesJSON[i.toString()] != null) {
|
||||
// print("Iteration " + i.toString());
|
||||
// print(categoriesJSON[i.toString()]);
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/common/functions/get_token.dart';
|
||||
|
||||
class Organisation {
|
||||
var id = 0;
|
||||
var name = "";
|
||||
var postcode = "";
|
||||
var streetName = ""; //street_name
|
||||
var town = "";
|
||||
|
||||
Organisation(
|
||||
this.id,
|
||||
this.name,
|
||||
|
@ -18,22 +11,22 @@ class Organisation {
|
|||
this.streetName,
|
||||
this.town,
|
||||
);
|
||||
|
||||
var id = 0;
|
||||
var name = "";
|
||||
var postcode = "";
|
||||
var streetName = ""; //street_name
|
||||
var town = "";
|
||||
}
|
||||
|
||||
class Organisations {
|
||||
|
||||
List<Organisation> getTestData() {
|
||||
var numItems = 10;
|
||||
var itemsList = new List<Organisation>();
|
||||
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
itemsList.add(new Organisation(
|
||||
i,
|
||||
"Payee " + (i + 1).toString(),
|
||||
"tee hee hee",
|
||||
"yeet street",
|
||||
"Robloxia"
|
||||
));
|
||||
itemsList.add(new Organisation(i, "Payee " + (i + 1).toString(),
|
||||
"tee hee hee", "yeet street", "Robloxia"));
|
||||
}
|
||||
|
||||
return itemsList;
|
||||
|
@ -88,6 +81,5 @@ class Organisations {
|
|||
// not successful
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -5,13 +5,13 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GraphData {
|
||||
var chartType;
|
||||
List<charts.Series<dynamic, DateTime>> graph;
|
||||
|
||||
GraphData(
|
||||
this.chartType,
|
||||
);
|
||||
|
||||
var chartType;
|
||||
List<charts.Series<dynamic, DateTime>> graph;
|
||||
|
||||
List<TimeSeriesSpend> cachedData;
|
||||
bool loaded = false;
|
||||
|
||||
|
@ -49,7 +49,8 @@ class GraphData {
|
|||
List<TimeSeriesSpend> timeSeriesSpendList = new List<TimeSeriesSpend>();
|
||||
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
timeSeriesSpendList.add(new TimeSeriesSpend(data[i]*1.00, DateTime.parse(labels[i])));
|
||||
timeSeriesSpendList.add(
|
||||
new TimeSeriesSpend(data[i] * 1.00, DateTime.parse(labels[i])));
|
||||
// print(timeSeriesSpendList[i].time.toString() + " : " + timeSeriesSpendList[i].spend.toString());
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,8 @@ class GraphData {
|
|||
List<TimeSeriesSpend> timeSeriesSpendList = new List<TimeSeriesSpend>();
|
||||
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
timeSeriesSpendList.add(new TimeSeriesSpend(data[i]*1.00, DateTime.parse(labels[i])));
|
||||
timeSeriesSpendList.add(
|
||||
new TimeSeriesSpend(data[i] * 1.00, DateTime.parse(labels[i])));
|
||||
// print(timeSeriesSpendList[i].time.toString() + " : " + timeSeriesSpendList[i].spend.toString());
|
||||
}
|
||||
|
||||
|
@ -154,18 +156,16 @@ class GraphData {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class OrgGraphData {
|
||||
var chartType;
|
||||
List<charts.Series<dynamic, DateTime>> graph;
|
||||
|
||||
OrgGraphData(
|
||||
this.chartType,
|
||||
);
|
||||
|
||||
var chartType;
|
||||
List<charts.Series<dynamic, DateTime>> graph;
|
||||
|
||||
List<TimeSeriesSpend> cachedData;
|
||||
bool loaded = false;
|
||||
|
||||
|
@ -203,7 +203,8 @@ class OrgGraphData {
|
|||
List<TimeSeriesSpend> timeSeriesSpendList = new List<TimeSeriesSpend>();
|
||||
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
timeSeriesSpendList.add(new TimeSeriesSpend(data[i]*1.00, DateTime.parse(labels[i])));
|
||||
timeSeriesSpendList.add(
|
||||
new TimeSeriesSpend(data[i] * 1.00, DateTime.parse(labels[i])));
|
||||
// print(timeSeriesSpendList[i].time.toString() + " : " + timeSeriesSpendList[i].spend.toString());
|
||||
}
|
||||
|
||||
|
@ -285,7 +286,8 @@ class OrgGraphData {
|
|||
List<TimeSeriesSpend> timeSeriesSpendList = new List<TimeSeriesSpend>();
|
||||
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
timeSeriesSpendList.add(new TimeSeriesSpend(data[i]*1.00, DateTime.parse(labels[i])));
|
||||
timeSeriesSpendList.add(
|
||||
new TimeSeriesSpend(data[i] * 1.00, DateTime.parse(labels[i])));
|
||||
// print(timeSeriesSpendList[i].time.toString() + " : " + timeSeriesSpendList[i].spend.toString());
|
||||
}
|
||||
|
||||
|
@ -308,14 +310,11 @@ class OrgGraphData {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TimeSeriesSpend {
|
||||
TimeSeriesSpend(this.spend, this.time);
|
||||
|
||||
final DateTime time;
|
||||
final double spend;
|
||||
|
||||
TimeSeriesSpend(this.spend, this.time);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ Future<void> _incorrectDialog(BuildContext context, bool isLoginWrong) async {
|
|||
duration: Duration(seconds: 2),
|
||||
child: AlertDialog(
|
||||
title: Text("Uh-oh!"),
|
||||
content: Text(isLoginWrong ? "Incorrect login details. Please try again." : "Our servers are having issues at the moment; sorry for the inconvenience. Please try again later."),
|
||||
content: Text(isLoginWrong
|
||||
? "Incorrect login details. Please try again."
|
||||
: "Our servers are having issues at the moment; sorry for the inconvenience. Please try again later."),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('OK'),
|
||||
|
@ -30,7 +32,8 @@ Future<void> _incorrectDialog(BuildContext context, bool isLoginWrong) async {
|
|||
);
|
||||
}
|
||||
|
||||
Future<LoginModel> requestLoginAPI(BuildContext context, String email, String password) async {
|
||||
Future<LoginModel> requestLoginAPI(
|
||||
BuildContext context, String email, String password) async {
|
||||
final url = "https://dev.localspend.co.uk/api/login";
|
||||
|
||||
Map<String, String> body = {
|
||||
|
@ -38,19 +41,19 @@ Future<LoginModel> requestLoginAPI(BuildContext context, String email, String pa
|
|||
'password': password,
|
||||
};
|
||||
|
||||
// debugPrint('$body');
|
||||
|
||||
try {
|
||||
final response = await http.post(
|
||||
final response = await http
|
||||
.post(
|
||||
url,
|
||||
body: json.encode(body),
|
||||
).timeout(Duration(seconds: 5));
|
||||
)
|
||||
.timeout(Duration(seconds: 5));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseJson = json.decode(response.body);
|
||||
|
||||
saveCurrentLogin(responseJson, body["email"]);
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
await Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
|
||||
return LoginModel.fromJson(responseJson);
|
||||
} else {
|
||||
|
@ -58,15 +61,15 @@ Future<LoginModel> requestLoginAPI(BuildContext context, String email, String pa
|
|||
|
||||
saveCurrentLogin(responseJson, body["email"]);
|
||||
|
||||
_incorrectDialog(context, true);
|
||||
await _incorrectDialog(context, true);
|
||||
|
||||
return null;
|
||||
}
|
||||
} on TimeoutException catch (_) {
|
||||
_incorrectDialog(context, false);
|
||||
await _incorrectDialog(context, false);
|
||||
} catch (error) {
|
||||
debugPrint(error.toString());
|
||||
_incorrectDialog(context, false);
|
||||
await _incorrectDialog(context, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ Future<LoginModel> submitReceiptAPI(
|
|||
'street_name': receipt.street,
|
||||
'postcode': receipt.postcode,
|
||||
'town': receipt.town,
|
||||
|
||||
'session_key': preferences.get('LastToken'),
|
||||
};
|
||||
|
||||
|
@ -61,13 +60,11 @@ Future<LoginModel> submitReceiptAPI(
|
|||
context,
|
||||
responseJson[0] == "" ? responseJson[0] : "Upload Successful",
|
||||
"Transaction successfully submitted to server",
|
||||
"OK"
|
||||
);
|
||||
"OK");
|
||||
return LoginModel.fromJson(responseJson);
|
||||
} else {
|
||||
final responseJson = json.decode(response.body);
|
||||
|
||||
|
||||
showDialogSingleButton(
|
||||
context,
|
||||
"Unable to Submit Receipt",
|
||||
|
|
|
@ -103,7 +103,8 @@ class AboutListTile extends StatelessWidget {
|
|||
return ListTile(
|
||||
leading: icon,
|
||||
title: child ??
|
||||
Text(MaterialLocalizations.of(context).aboutListTileTitle(applicationName ?? _defaultApplicationName(context))),
|
||||
Text(MaterialLocalizations.of(context).aboutListTileTitle(
|
||||
applicationName ?? _defaultApplicationName(context))),
|
||||
onTap: () {
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
|
@ -178,13 +179,14 @@ void showLicensePage({
|
|||
String applicationLegalese,
|
||||
}) {
|
||||
assert(context != null);
|
||||
Navigator.push(context, MaterialPageRoute<void>(
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) => LicensePage(
|
||||
applicationName: applicationName,
|
||||
applicationVersion: applicationVersion,
|
||||
applicationLegalese: applicationLegalese,
|
||||
)
|
||||
));
|
||||
)));
|
||||
}
|
||||
|
||||
/// An about box. This is a dialog box with the application's icon, name,
|
||||
|
@ -256,15 +258,22 @@ class AboutDialog extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
final String name = applicationName ?? _defaultApplicationName(context);
|
||||
final String version = applicationVersion ?? _defaultApplicationVersion(context);
|
||||
final String version =
|
||||
applicationVersion ?? _defaultApplicationVersion(context);
|
||||
final Widget icon = applicationIcon ?? _defaultApplicationIcon(context);
|
||||
List<Widget> body = <Widget>[];
|
||||
if (icon != null)
|
||||
body.add(IconTheme(data: const IconThemeData(size: 45.0), child: icon));
|
||||
if (icon != null) {
|
||||
body.add(
|
||||
IconTheme(
|
||||
data: const IconThemeData(size: 45.0),
|
||||
child: icon
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
body.add(Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
|
@ -272,7 +281,8 @@ class AboutDialog extends StatelessWidget {
|
|||
child: Text(name, style: Theme.of(context).textTheme.title),
|
||||
),
|
||||
Text(version, style: Theme.of(context).textTheme.body1),
|
||||
Text(applicationLegalese ?? '', style: Theme.of(context).textTheme.caption),
|
||||
Text(applicationLegalese ?? '',
|
||||
style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -283,15 +293,15 @@ class AboutDialog extends StatelessWidget {
|
|||
children: body,
|
||||
),
|
||||
];
|
||||
if (children != null)
|
||||
body.addAll(children);
|
||||
if (children != null) body.addAll(children);
|
||||
return AlertDialog(
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(children: body),
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text(MaterialLocalizations.of(context).viewLicensesButtonLabel),
|
||||
child:
|
||||
Text(MaterialLocalizations.of(context).viewLicensesButtonLabel),
|
||||
onPressed: () {
|
||||
showLicensePage(
|
||||
context: context,
|
||||
|
@ -385,7 +395,8 @@ class _LicensePageState extends State<LicensePage> {
|
|||
return;
|
||||
}
|
||||
assert(() {
|
||||
dev.Timeline.timeSync('_initLicenses()', () { }, flow: dev.Flow.step(debugFlowId));
|
||||
dev.Timeline.timeSync('_initLicenses()', () {},
|
||||
flow: dev.Flow.step(debugFlowId));
|
||||
return true;
|
||||
}());
|
||||
final List<LicenseParagraph> paragraphs =
|
||||
|
@ -404,8 +415,7 @@ class _LicensePageState extends State<LicensePage> {
|
|||
));
|
||||
_licenses.add(Container(
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(bottom: BorderSide(width: 0.0))
|
||||
),
|
||||
border: Border(bottom: BorderSide(width: 0.0))),
|
||||
child: Text(
|
||||
license.packages.join(', '),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
|
@ -425,7 +435,8 @@ class _LicensePageState extends State<LicensePage> {
|
|||
} else {
|
||||
assert(paragraph.indent >= 0);
|
||||
_licenses.add(Padding(
|
||||
padding: EdgeInsetsDirectional.only(top: 8.0, start: 16.0 * paragraph.indent),
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
top: 8.0, start: 16.0 * paragraph.indent),
|
||||
child: Text(paragraph.text),
|
||||
));
|
||||
}
|
||||
|
@ -436,7 +447,8 @@ class _LicensePageState extends State<LicensePage> {
|
|||
_loaded = true;
|
||||
});
|
||||
assert(() {
|
||||
dev.Timeline.timeSync('Build scheduled', () { }, flow: dev.Flow.end(debugFlowId));
|
||||
dev.Timeline.timeSync('Build scheduled', () {},
|
||||
flow: dev.Flow.end(debugFlowId));
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
@ -444,16 +456,27 @@ class _LicensePageState extends State<LicensePage> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
final String name = widget.applicationName ?? _defaultApplicationName(context);
|
||||
final String version = widget.applicationVersion ?? _defaultApplicationVersion(context);
|
||||
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
||||
final String name =
|
||||
widget.applicationName ?? _defaultApplicationName(context);
|
||||
final String version =
|
||||
widget.applicationVersion ?? _defaultApplicationVersion(context);
|
||||
final MaterialLocalizations localizations =
|
||||
MaterialLocalizations.of(context);
|
||||
final List<Widget> contents = <Widget>[
|
||||
Text(name, style: Theme.of(context).textTheme.headline, textAlign: TextAlign.center),
|
||||
Text(version, style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
|
||||
Text(name,
|
||||
style: Theme.of(context).textTheme.headline,
|
||||
textAlign: TextAlign.center),
|
||||
Text(version,
|
||||
style: Theme.of(context).textTheme.body1,
|
||||
textAlign: TextAlign.center),
|
||||
Container(height: 18.0),
|
||||
Text(widget.applicationLegalese ?? '', style: Theme.of(context).textTheme.caption, textAlign: TextAlign.center),
|
||||
Text(widget.applicationLegalese ?? '',
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
textAlign: TextAlign.center),
|
||||
Container(height: 18.0),
|
||||
Text('Powered by Flutter', style: Theme.of(context).textTheme.body1, textAlign: TextAlign.center),
|
||||
Text('Powered by Flutter',
|
||||
style: Theme.of(context).textTheme.body1,
|
||||
textAlign: TextAlign.center),
|
||||
Container(height: 24.0),
|
||||
];
|
||||
contents.addAll(_licenses);
|
||||
|
@ -480,7 +503,8 @@ class _LicensePageState extends State<LicensePage> {
|
|||
bottom: false,
|
||||
child: Scrollbar(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
|
||||
children: contents,
|
||||
),
|
||||
),
|
||||
|
@ -499,7 +523,8 @@ String _defaultApplicationName(BuildContext context) {
|
|||
// can provide an explicit applicationName to the widgets defined in this
|
||||
// file, instead of relying on the default.
|
||||
final Title ancestorTitle = context.ancestorWidgetOfExactType(Title);
|
||||
return ancestorTitle?.title ?? Platform.resolvedExecutable.split(Platform.pathSeparator).last;
|
||||
return ancestorTitle?.title ??
|
||||
Platform.resolvedExecutable.split(Platform.pathSeparator).last;
|
||||
}
|
||||
|
||||
String _defaultApplicationVersion(BuildContext context) {
|
||||
|
|
|
@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
final TextEditingController _feedbackController = TextEditingController();
|
||||
|
||||
void feedback(
|
||||
BuildContext context) {
|
||||
void feedback(BuildContext context) {
|
||||
// flutter defined function
|
||||
showDialog(
|
||||
context: context,
|
||||
|
@ -15,12 +14,10 @@ void feedback(
|
|||
children: <Widget>[
|
||||
Text("We would love to hear your thoughts."),
|
||||
Text("\nThis section needs to be fixed."),
|
||||
|
||||
Container(
|
||||
margin: const EdgeInsets.fromLTRB(0, 20, 0, 0),
|
||||
width: 200,
|
||||
height: 70,
|
||||
|
||||
child: new TextField(
|
||||
controller: _feedbackController,
|
||||
decoration: InputDecoration(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'dart:async';
|
||||
|
||||
getToken() async {
|
||||
Future<String> getToken() async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
String getToken = preferences.getString("LastToken");
|
||||
|
|
|
@ -2,16 +2,16 @@ import 'package:flutter/material.dart';
|
|||
import 'package:local_spend/common/apifunctions/request_logout_api.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
logout(context) {
|
||||
void logout(context) {
|
||||
requestLogoutAPI(context);
|
||||
Navigator.of(context).pushReplacementNamed('/LoginPage');
|
||||
_clearLoginDetails();
|
||||
}
|
||||
|
||||
_clearLoginDetails() async {
|
||||
void _clearLoginDetails() async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
preferences.setString('username', "");
|
||||
preferences.setString('password', "");
|
||||
await preferences.setString('username', "");
|
||||
await preferences.setString('password', "");
|
||||
print("details cleared");
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:local_spend/model/json/login_model.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
saveCurrentLogin(Map responseJson, loginEmail) async {
|
||||
void saveCurrentLogin(Map responseJson, loginEmail) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
var user;
|
||||
|
@ -13,9 +13,7 @@ saveCurrentLogin(Map responseJson, loginEmail) async {
|
|||
var token = (responseJson != null && responseJson.isNotEmpty)
|
||||
? LoginModel.fromJson(responseJson).token
|
||||
: "";
|
||||
var email = (loginEmail != null)
|
||||
? loginEmail
|
||||
: "";
|
||||
var email = (loginEmail != null) ? loginEmail : "";
|
||||
var userType = (responseJson != null && responseJson.isNotEmpty)
|
||||
? LoginModel.fromJson(responseJson).userType
|
||||
: "";
|
||||
|
@ -23,9 +21,9 @@ saveCurrentLogin(Map responseJson, loginEmail) async {
|
|||
await preferences.setString(
|
||||
'LastUser', (user != null && user.length > 0) ? user : "");
|
||||
await preferences.setString(
|
||||
'LastToken', (token != null && token.length > 0) ? token : "");
|
||||
'LastToken', (token != null && token.isNotEmpty) ? token : "");
|
||||
await preferences.setString(
|
||||
'LastEmail', (email != null && email.length > 0) ? email : "");
|
||||
await preferences.setString(
|
||||
'LastUserType', (userType != null && userType.length > 0) ? userType : "");
|
||||
await preferences.setString('LastUserType',
|
||||
(userType != null && userType.isNotEmpty) ? userType : "");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
saveLogout() async {
|
||||
void saveLogout() async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
await preferences.setString('LastUser', "");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
void showDialogTwoButtons(
|
||||
BuildContext context, String title, String message, String buttonLabel1, String buttonLabel2, Function action) {
|
||||
void showDialogTwoButtons(BuildContext context, String title, String message,
|
||||
String buttonLabel1, String buttonLabel2, Function action) {
|
||||
// flutter defined function
|
||||
showDialog(
|
||||
context: context,
|
||||
|
|
|
@ -4,19 +4,6 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class PlatformScaffold extends StatelessWidget {
|
||||
final Key key;
|
||||
final PreferredSizeWidget appBar;
|
||||
final Widget body;
|
||||
final Widget floatingActionButton;
|
||||
final FloatingActionButtonLocation floatingActionButtonLocation;
|
||||
final FloatingActionButtonAnimator floatingActionButtonAnimator;
|
||||
final List<Widget> persistentFooterButtons;
|
||||
final Widget drawer;
|
||||
final Widget endDrawer;
|
||||
final Widget bottomNavigationBar;
|
||||
final Color backgroundColor;
|
||||
final bool resizeToAvoidBottomPadding;
|
||||
final bool primary;
|
||||
|
||||
PlatformScaffold(
|
||||
{this.key,
|
||||
|
@ -30,11 +17,26 @@ class PlatformScaffold extends StatelessWidget {
|
|||
this.endDrawer,
|
||||
this.bottomNavigationBar,
|
||||
this.backgroundColor,
|
||||
this.resizeToAvoidBottomPadding: true,
|
||||
this.primary: true})
|
||||
this.resizeToAvoidBottomPadding = true,
|
||||
this.primary = true})
|
||||
: assert(primary != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
final Key key;
|
||||
final PreferredSizeWidget appBar;
|
||||
final Widget body;
|
||||
final Widget floatingActionButton;
|
||||
final FloatingActionButtonLocation floatingActionButtonLocation;
|
||||
final FloatingActionButtonAnimator floatingActionButtonAnimator;
|
||||
final List<Widget> persistentFooterButtons;
|
||||
final Widget drawer;
|
||||
final Widget endDrawer;
|
||||
final Widget bottomNavigationBar;
|
||||
final Color backgroundColor;
|
||||
final bool resizeToAvoidBottomPadding;
|
||||
final bool primary;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Platform.isIOS
|
||||
|
|
|
@ -2,10 +2,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:simple_animations/simple_animations.dart';
|
||||
|
||||
class AnimatedBackground extends StatelessWidget {
|
||||
final List<Color> animateColors;
|
||||
final Color lastColor;
|
||||
final Alignment begin, end;
|
||||
final int duration;
|
||||
|
||||
AnimatedBackground(
|
||||
this.animateColors,
|
||||
|
@ -15,6 +11,11 @@ class AnimatedBackground extends StatelessWidget {
|
|||
this.duration,
|
||||
);
|
||||
|
||||
final List<Color> animateColors;
|
||||
final Color lastColor;
|
||||
final Alignment begin, end;
|
||||
final int duration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tween = MultiTrackTween([
|
||||
|
|
|
@ -4,9 +4,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DonutAutoLabelChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
DonutAutoLabelChart(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [PieChart] with sample data and no transition.
|
||||
|
@ -18,6 +15,8 @@ class DonutAutoLabelChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -67,8 +66,8 @@ class DonutAutoLabelChart extends StatelessWidget {
|
|||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
LinearSales(this.key, this.sales);
|
||||
|
||||
final String key;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.key, this.sales);
|
||||
}
|
|
@ -2,13 +2,12 @@ import 'package:flutter/material.dart';
|
|||
import 'package:local_spend/common/widgets/charts/time_series_simple.dart';
|
||||
|
||||
class TimeSeries extends StatelessWidget {
|
||||
|
||||
final String chartDataName;
|
||||
|
||||
TimeSeries({
|
||||
this.chartDataName,
|
||||
});
|
||||
|
||||
final String chartDataName;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Container(
|
||||
|
|
|
@ -3,9 +3,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DonutPieChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
DonutPieChart(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [PieChart] with sample data and no transition.
|
||||
|
@ -16,6 +13,8 @@ class DonutPieChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -46,11 +45,10 @@ class DonutPieChart extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
LinearSales(this.year, this.sales);
|
||||
|
||||
final int year;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.year, this.sales);
|
||||
}
|
|
@ -3,9 +3,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class GroupedBarChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
GroupedBarChart(this.seriesList, {this.animate});
|
||||
|
||||
factory GroupedBarChart.withSampleData() {
|
||||
|
@ -16,6 +13,8 @@ class GroupedBarChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -74,8 +73,8 @@ class GroupedBarChart extends StatelessWidget {
|
|||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
OrdinalSales(this.year, this.sales);
|
||||
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
|
@ -4,8 +4,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class NumericComboLineBarChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
NumericComboLineBarChart(this.seriesList, {this.animate});
|
||||
|
||||
|
@ -18,6 +16,8 @@ class NumericComboLineBarChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -88,8 +88,8 @@ class NumericComboLineBarChart extends StatelessWidget {
|
|||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
LinearSales(this.year, this.sales);
|
||||
|
||||
final int year;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.year, this.sales);
|
||||
}
|
|
@ -3,9 +3,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class PieOutsideLabelChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
PieOutsideLabelChart(this.seriesList, {this.animate});
|
||||
|
||||
/// Creates a [PieChart] with sample data and no transition.
|
||||
|
@ -17,6 +14,8 @@ class PieOutsideLabelChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -62,8 +61,8 @@ class PieOutsideLabelChart extends StatelessWidget {
|
|||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
LinearSales(this.year, this.sales);
|
||||
|
||||
final int year;
|
||||
final int sales;
|
||||
|
||||
LinearSales(this.year, this.sales);
|
||||
}
|
|
@ -8,8 +8,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class BucketingAxisScatterPlotChart extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
BucketingAxisScatterPlotChart(this.seriesList, {this.animate});
|
||||
|
||||
|
@ -22,6 +20,8 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -128,9 +128,9 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
|
||||
/// Sample linear data type.
|
||||
class LinearSales {
|
||||
LinearSales(this.year, this.revenueShare, this.radius);
|
||||
|
||||
final int year;
|
||||
final double revenueShare;
|
||||
final double radius;
|
||||
|
||||
LinearSales(this.year, this.revenueShare, this.radius);
|
||||
}
|
|
@ -11,9 +11,6 @@ import 'package:charts_flutter/flutter.dart' as charts;
|
|||
///
|
||||
/// Also shows the option to provide a custom measure formatter.
|
||||
class LegendWithMeasures extends StatelessWidget {
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
LegendWithMeasures(this.seriesList, {this.animate});
|
||||
|
||||
factory LegendWithMeasures.withSampleData() {
|
||||
|
@ -24,6 +21,8 @@ class LegendWithMeasures extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -122,8 +121,8 @@ class LegendWithMeasures extends StatelessWidget {
|
|||
|
||||
/// Sample ordinal data type.
|
||||
class OrdinalSales {
|
||||
OrdinalSales(this.year, this.sales);
|
||||
|
||||
final String year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
|
@ -3,9 +3,6 @@ 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.
|
||||
|
@ -17,6 +14,8 @@ class SimpleTimeSeriesChart extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
final List<charts.Series> seriesList;
|
||||
final bool animate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -53,8 +52,8 @@ class SimpleTimeSeriesChart extends StatelessWidget {
|
|||
|
||||
/// Sample time series data type.
|
||||
class TimeSeriesSales {
|
||||
TimeSeriesSales(this.time, this.sales);
|
||||
|
||||
final DateTime time;
|
||||
final int sales;
|
||||
|
||||
TimeSeriesSales(this.time, this.sales);
|
||||
}
|
|
@ -62,8 +62,6 @@ class CustomCheckbox extends StatefulWidget {
|
|||
assert(tristate || value != null),
|
||||
super(key: key);
|
||||
|
||||
|
||||
|
||||
final bool useTapTarget;
|
||||
|
||||
/// Whether this checkbox is checked.
|
||||
|
@ -138,7 +136,8 @@ class CustomCheckbox extends StatefulWidget {
|
|||
_CustomCheckboxState createState() => _CustomCheckboxState();
|
||||
}
|
||||
|
||||
class _CustomCheckboxState extends State<CustomCheckbox> with TickerProviderStateMixin {
|
||||
class _CustomCheckboxState extends State<CustomCheckbox>
|
||||
with TickerProviderStateMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
|
@ -147,25 +146,26 @@ class _CustomCheckboxState extends State<CustomCheckbox> with TickerProviderStat
|
|||
Size size;
|
||||
switch (widget.materialTapTargetSize ?? themeData.materialTapTargetSize) {
|
||||
case MaterialTapTargetSize.padded:
|
||||
size = const Size(2 * kRadialReactionRadius + 8.0, 2 * kRadialReactionRadius + 8.0);
|
||||
size = const Size(
|
||||
2 * kRadialReactionRadius + 8.0, 2 * kRadialReactionRadius + 8.0);
|
||||
break;
|
||||
case MaterialTapTargetSize.shrinkWrap:
|
||||
size = const Size(2 * kRadialReactionRadius, 2 * kRadialReactionRadius);
|
||||
break;
|
||||
}
|
||||
|
||||
Size noTapTargetSize = Size(CustomCheckbox.width,
|
||||
CustomCheckbox.width);
|
||||
Size noTapTargetSize = Size(CustomCheckbox.width, CustomCheckbox.width);
|
||||
final BoxConstraints additionalConstraints =
|
||||
BoxConstraints.tight(widget
|
||||
.useTapTarget? size : noTapTargetSize);
|
||||
BoxConstraints.tight(widget.useTapTarget ? size : noTapTargetSize);
|
||||
|
||||
return _CheckboxRenderObjectWidget(
|
||||
value: widget.value,
|
||||
tristate: widget.tristate,
|
||||
activeColor: widget.activeColor ?? themeData.toggleableActiveColor,
|
||||
checkColor: widget.checkColor ?? const Color(0xFFFFFFFF),
|
||||
inactiveColor: widget.onChanged != null ? themeData.unselectedWidgetColor : themeData.disabledColor,
|
||||
inactiveColor: widget.onChanged != null
|
||||
? themeData.unselectedWidgetColor
|
||||
: themeData.disabledColor,
|
||||
onChanged: widget.onChanged,
|
||||
additionalConstraints: additionalConstraints,
|
||||
vsync: this,
|
||||
|
@ -174,8 +174,8 @@ class _CustomCheckboxState extends State<CustomCheckbox> with TickerProviderStat
|
|||
}
|
||||
|
||||
class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
const _CheckboxRenderObjectWidget({
|
||||
Key key,
|
||||
const _CheckboxRenderObjectWidget(
|
||||
{Key key,
|
||||
@required this.value,
|
||||
@required this.tristate,
|
||||
@required this.activeColor,
|
||||
|
@ -184,9 +184,8 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
|
|||
@required this.onChanged,
|
||||
@required this.vsync,
|
||||
@required this.additionalConstraints,
|
||||
this.useTapTarget = true
|
||||
|
||||
}) : assert(tristate != null),
|
||||
this.useTapTarget = true})
|
||||
: assert(tristate != null),
|
||||
assert(tristate || value != null),
|
||||
assert(activeColor != null),
|
||||
assert(inactiveColor != null),
|
||||
|
@ -259,8 +258,7 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
|
||||
@override
|
||||
set value(bool newValue) {
|
||||
if (newValue == value)
|
||||
return;
|
||||
if (newValue == value) return;
|
||||
_oldValue = value;
|
||||
super.value = newValue;
|
||||
}
|
||||
|
@ -278,7 +276,8 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
RRect _outerRectAt(Offset origin, double t) {
|
||||
final double inset = 1.0 - (t - 0.5).abs() * 2.0;
|
||||
final double size = _kEdgeSize - inset * _kStrokeWidth;
|
||||
final Rect rect = Rect.fromLTWH(origin.dx + inset, origin.dy + inset, size, size);
|
||||
final Rect rect =
|
||||
Rect.fromLTWH(origin.dx + inset, origin.dy + inset, size, size);
|
||||
return RRect.fromRectAndRadius(rect, _kEdgeRadius);
|
||||
}
|
||||
|
||||
|
@ -288,7 +287,9 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
// As t goes from 0.0 to 0.25, animate from the inactiveColor to activeColor.
|
||||
return onChanged == null
|
||||
? inactiveColor
|
||||
: (t >= 0.25 ? activeColor : Color.lerp(inactiveColor, activeColor, t * 4.0));
|
||||
: (t >= 0.25
|
||||
? activeColor
|
||||
: Color.lerp(inactiveColor, activeColor, t * 4.0));
|
||||
}
|
||||
|
||||
// White stroke used to paint the check and dash.
|
||||
|
@ -303,7 +304,8 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
assert(t >= 0.0 && t <= 0.5);
|
||||
final double size = outer.width;
|
||||
// As t goes from 0.0 to 1.0, gradually fill the outer RRect.
|
||||
final RRect inner = outer.deflate(math.min(size / 2.0, _kStrokeWidth + size * t));
|
||||
final RRect inner =
|
||||
outer.deflate(math.min(size / 2.0, _kStrokeWidth + size * t));
|
||||
canvas.drawDRRect(outer, inner, paint);
|
||||
}
|
||||
|
||||
|
@ -347,9 +349,11 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
final Canvas canvas = context.canvas;
|
||||
paintRadialReaction(canvas, offset, size.center(Offset.zero));
|
||||
|
||||
final Offset origin = offset + (size / 2.0 - const Size.square(_kEdgeSize) / 2.0);
|
||||
final Offset origin =
|
||||
offset + (size / 2.0 - const Size.square(_kEdgeSize) / 2.0);
|
||||
final AnimationStatus status = position.status;
|
||||
final double tNormalized = status == AnimationStatus.forward || status == AnimationStatus.completed
|
||||
final double tNormalized =
|
||||
status == AnimationStatus.forward || status == AnimationStatus.completed
|
||||
? position.value
|
||||
: 1.0 - position.value;
|
||||
|
||||
|
@ -366,12 +370,15 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
|
||||
_initStrokePaint(paint);
|
||||
final double tShrink = (t - 0.5) * 2.0;
|
||||
if (_oldValue == null || value == null)
|
||||
if (_oldValue == null || value == null) {
|
||||
_drawDash(canvas, origin, tShrink, paint);
|
||||
else
|
||||
}
|
||||
else {
|
||||
_drawCheck(canvas, origin, tShrink, paint);
|
||||
}
|
||||
} else { // Two cases: null to true, true to null
|
||||
}
|
||||
} else {
|
||||
// Two cases: null to true, true to null
|
||||
final RRect outer = _outerRectAt(origin, 1.0);
|
||||
final Paint paint = Paint()..color = _colorAt(1.0);
|
||||
canvas.drawRRect(outer, paint);
|
||||
|
@ -379,17 +386,21 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
_initStrokePaint(paint);
|
||||
if (tNormalized <= 0.5) {
|
||||
final double tShrink = 1.0 - tNormalized * 2.0;
|
||||
if (_oldValue == true)
|
||||
if (_oldValue == true) {
|
||||
_drawCheck(canvas, origin, tShrink, paint);
|
||||
else
|
||||
}
|
||||
else {
|
||||
_drawDash(canvas, origin, tShrink, paint);
|
||||
}
|
||||
} else {
|
||||
final double tExpand = (tNormalized - 0.5) * 2.0;
|
||||
if (value == true)
|
||||
if (value == true) {
|
||||
_drawCheck(canvas, origin, tExpand, paint);
|
||||
else
|
||||
}
|
||||
else {
|
||||
_drawDash(canvas, origin, tExpand, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,8 @@ class LabeledCheckboxWithIcon extends StatelessWidget {
|
|||
onTap: () {
|
||||
onChanged(!value);
|
||||
},
|
||||
|
||||
|
||||
child: Padding(
|
||||
padding: padding,
|
||||
|
||||
child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.center, //doesn't do anything
|
||||
|
||||
|
@ -40,16 +37,18 @@ class LabeledCheckboxWithIcon extends StatelessWidget {
|
|||
Container(
|
||||
padding: EdgeInsets.all(0),
|
||||
width: iconSize,
|
||||
|
||||
child: Icon(
|
||||
icon,
|
||||
// size: iconSize,
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(child: Text(label, style: textStyle, textAlign: TextAlign.center,)),
|
||||
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: textStyle,
|
||||
textAlign: TextAlign.center,
|
||||
)),
|
||||
CustomCheckbox(
|
||||
//custom checkbox removes padding so the form looks nice
|
||||
|
||||
|
@ -89,11 +88,9 @@ class LabeledCheckbox extends StatelessWidget {
|
|||
},
|
||||
child: Padding(
|
||||
padding: padding,
|
||||
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(child: Text(label, style: textStyle)),
|
||||
|
||||
CustomCheckbox(
|
||||
//custom checkbox removes padding so the form looks nice
|
||||
|
||||
|
@ -110,7 +107,6 @@ class LabeledCheckbox extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//USAGE:
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:flutter/services.dart';
|
|||
import 'package:local_spend/common/apifunctions/find_organisations.dart';
|
||||
|
||||
class FindOrganisations {
|
||||
|
||||
TextField getSearchBar(TextEditingController controller, String hintText) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
|
@ -20,12 +19,12 @@ class FindOrganisations {
|
|||
|
||||
Future<dynamic> _moreInfoDialog(context, Organisation organisation) {
|
||||
TextStyle informationTitleStyle = new TextStyle(fontSize: 16);
|
||||
TextStyle informationStyle = new TextStyle(fontSize: 16, fontWeight: FontWeight.bold);
|
||||
TextStyle informationStyle =
|
||||
new TextStyle(fontSize: 16, fontWeight: FontWeight.bold);
|
||||
|
||||
return showDialog<Organisation>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
|
||||
builder: (BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
|
@ -39,12 +38,10 @@ class FindOrganisations {
|
|||
fontSize: 21, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Divider(),
|
||||
),
|
||||
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
|
@ -54,13 +51,15 @@ class FindOrganisations {
|
|||
TableRow(
|
||||
children: [
|
||||
Text("Street:", style: informationTitleStyle),
|
||||
Text(organisation.streetName, style: informationStyle),
|
||||
Text(organisation.streetName,
|
||||
style: informationStyle),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
Text("Postcode:", style: informationTitleStyle),
|
||||
Text(organisation.postcode.toUpperCase(), style: informationStyle),
|
||||
Text(organisation.postcode.toUpperCase(),
|
||||
style: informationStyle),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
|
@ -72,7 +71,6 @@ class FindOrganisations {
|
|||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -82,7 +80,6 @@ class FindOrganisations {
|
|||
}
|
||||
|
||||
Future<Organisation> dialog(context) {
|
||||
|
||||
bool _searchEnabled = false;
|
||||
bool _orgsFetched = false;
|
||||
TextEditingController searchBarText = new TextEditingController();
|
||||
|
@ -103,9 +100,7 @@ class FindOrganisations {
|
|||
return showDialog<Organisation>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
|
||||
builder: (BuildContext context) {
|
||||
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return SimpleDialog(
|
||||
|
@ -126,40 +121,45 @@ class FindOrganisations {
|
|||
hintText: "Payee Name",
|
||||
),
|
||||
onChanged: (value) {
|
||||
if (value.length > 0) {
|
||||
if (value.isNotEmpty) {
|
||||
_searchEnabled = true;
|
||||
} else {
|
||||
_searchEnabled = false;
|
||||
}
|
||||
setState(() => {_searchEnabled});
|
||||
},
|
||||
onSubmitted: _searchEnabled ? ((_) {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
var result = _submitSearch(searchBarText.text);
|
||||
onSubmitted: _searchEnabled
|
||||
? ((_) {
|
||||
SystemChannels.textInput
|
||||
.invokeMethod('TextInput.hide');
|
||||
var result =
|
||||
_submitSearch(searchBarText.text);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
});
|
||||
});
|
||||
}) : null,
|
||||
})
|
||||
: null,
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
width: 80,
|
||||
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
|
||||
|
||||
child: RaisedButton(
|
||||
onPressed: _searchEnabled ? (() {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
var result = _submitSearch(searchBarText.text);
|
||||
onPressed: _searchEnabled
|
||||
? (() {
|
||||
SystemChannels.textInput
|
||||
.invokeMethod('TextInput.hide');
|
||||
var result =
|
||||
_submitSearch(searchBarText.text);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
});
|
||||
});
|
||||
}) : null,
|
||||
|
||||
})
|
||||
: null,
|
||||
child: Icon(Icons.search, color: Colors.white),
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
@ -170,7 +170,8 @@ class FindOrganisations {
|
|||
),
|
||||
|
||||
Column(
|
||||
children: _orgsFetched ? [
|
||||
children: _orgsFetched
|
||||
? [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
|
||||
child: Text(
|
||||
|
@ -179,18 +180,10 @@ class FindOrganisations {
|
|||
fontSize: 23, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
|
||||
width: MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.width,
|
||||
height: MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.height * 0.67,
|
||||
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height * 0.67,
|
||||
child: Material(
|
||||
shadowColor: Colors.transparent,
|
||||
color: Colors.transparent,
|
||||
|
@ -200,16 +193,21 @@ class FindOrganisations {
|
|||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.person),
|
||||
title: Text(organisationsList[index].name, style: new TextStyle(fontSize: 18)),
|
||||
subtitle: Text(organisationsList[index].postcode.toUpperCase()),
|
||||
title: Text(organisationsList[index].name,
|
||||
style: new TextStyle(fontSize: 18)),
|
||||
subtitle: Text(organisationsList[index]
|
||||
.postcode
|
||||
.toUpperCase()),
|
||||
// trailing: Icon(Icons.arrow_forward_ios),
|
||||
// onTap: _chosenOrg(organisationsList[index]),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop(organisationsList[index]);
|
||||
Navigator.of(context)
|
||||
.pop(organisationsList[index]);
|
||||
},
|
||||
onLongPress: () {
|
||||
// show more details about the organisation in a new dialog
|
||||
var moreInfo = _moreInfoDialog(context, organisationsList[index]);
|
||||
var moreInfo = _moreInfoDialog(
|
||||
context, organisationsList[index]);
|
||||
moreInfo.whenComplete(null);
|
||||
},
|
||||
),
|
||||
|
@ -218,19 +216,20 @@ class FindOrganisations {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Center(
|
||||
child: Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||
child : Text("Long press a payee for more info", style: TextStyle(fontStyle: FontStyle.italic)),
|
||||
child: Text("Long press a payee for more info",
|
||||
style:
|
||||
TextStyle(fontStyle: FontStyle.italic)),
|
||||
),
|
||||
),
|
||||
] : [ Container() ],
|
||||
]
|
||||
: [Container()],
|
||||
),
|
||||
|
||||
// help button for if org not listed
|
||||
// cancel and ok buttons
|
||||
|
||||
],
|
||||
// ),
|
||||
);
|
||||
|
|
|
@ -6,7 +6,6 @@ class PopupListView {
|
|||
return showDialog<dynamic>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: Text(title),
|
||||
|
@ -16,7 +15,8 @@ class PopupListView {
|
|||
);
|
||||
}
|
||||
|
||||
List<Widget> getDialogOptions(context, List<String> options /*, Function onPressed*/) {
|
||||
List<Widget> getDialogOptions(
|
||||
context, List<String> options /*, Function onPressed*/) {
|
||||
var dialogOptionsList = new List<SimpleDialogOption>();
|
||||
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
|
|
|
@ -5,13 +5,13 @@ part 'config.g.dart';
|
|||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class Config {
|
||||
final String env;
|
||||
final bool production;
|
||||
final String apiKey;
|
||||
|
||||
Config({this.env, this.production, this.apiKey});
|
||||
|
||||
factory Config.fromJson(Map<String, dynamic> json) => _$ConfigFromJson(json);
|
||||
|
||||
final String env;
|
||||
final bool production;
|
||||
final String apiKey;
|
||||
}
|
||||
|
||||
class ConfigWrapper extends StatelessWidget {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/pages/home_page.dart';
|
||||
import 'package:local_spend/pages/login_page.dart';
|
||||
import 'package:local_spend/pages/map_page.dart';
|
||||
import 'package:local_spend/pages/receipt_page_2.dart';
|
||||
import 'package:local_spend/pages/spash_screen.dart';
|
||||
import 'package:local_spend/pages/more_page.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'package:local_spend/common/apifunctions/get_graph_data.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
@ -21,10 +20,7 @@ class MyApp extends StatelessWidget {
|
|||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: [
|
||||
Locale("en")
|
||||
],
|
||||
|
||||
supportedLocales: [Locale("en")],
|
||||
title: "Local Spend Tracker",
|
||||
theme: new ThemeData(
|
||||
primarySwatch: Colors.blueGrey,
|
||||
|
@ -32,6 +28,7 @@ class MyApp extends StatelessWidget {
|
|||
routes: <String, WidgetBuilder>{
|
||||
"/HomePage": (BuildContext context) => HomePage(),
|
||||
"/LoginPage": (BuildContext context) => LoginPage(),
|
||||
'/MapPage': (BuildContext context) => MapSample(),
|
||||
"/ReceiptPage": (BuildContext context) => ReceiptPage2(),
|
||||
"/MorePage": (BuildContext context) => MorePage(),
|
||||
},
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
class LoginModel {
|
||||
final String userName;
|
||||
final String token;
|
||||
final String userType;
|
||||
|
||||
LoginModel(this.userName, this.token, this.userType);
|
||||
|
||||
LoginModel.fromJson(Map<String, dynamic> json)
|
||||
|
@ -10,6 +6,10 @@ class LoginModel {
|
|||
userType = json['user_type'],
|
||||
token = json['session_key'];
|
||||
|
||||
final String userName;
|
||||
final String token;
|
||||
final String userType;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'name': userName,
|
||||
'user_type': userType,
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:local_spend/common/apifunctions/get_graph_data.dart';
|
||||
|
||||
class PresetChart extends StatefulWidget {
|
||||
PresetChart({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_PresetChartState createState() {
|
||||
return _PresetChartState();
|
||||
}
|
||||
}
|
||||
|
||||
class _PresetChartState extends State<PresetChart> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Container(
|
||||
|
||||
);
|
||||
}
|
||||
}
|
|
@ -56,7 +56,6 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
|
|||
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 17, 0.0, 0.0),
|
||||
child: Text(
|
||||
|
@ -69,16 +68,18 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Tooltip(
|
||||
message: "Graph of total spend last week",
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
height: 200,
|
||||
child: totalLastWeekGraph.graph != null ? new charts.TimeSeriesChart(totalLastWeekGraph.graph) : Center(child: Text("Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
child: totalLastWeekGraph.graph != null
|
||||
? new charts.TimeSeriesChart(totalLastWeekGraph.graph)
|
||||
: Center(
|
||||
child: Text(
|
||||
"Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 17, 0.0, 0.0),
|
||||
child: Text(
|
||||
|
@ -91,16 +92,18 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Tooltip(
|
||||
message: "Graph of average spend last week",
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
height: 200,
|
||||
child: avgSpendLastWeekGraph.graph != null ? new charts.TimeSeriesChart(avgSpendLastWeekGraph.graph) : Center(child: Text("Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
child: avgSpendLastWeekGraph.graph != null
|
||||
? new charts.TimeSeriesChart(avgSpendLastWeekGraph.graph)
|
||||
: Center(
|
||||
child: Text(
|
||||
"Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 17, 0.0, 0.0),
|
||||
child: Text(
|
||||
|
@ -113,16 +116,18 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Tooltip(
|
||||
message: "Graph of total spend last month",
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
height: 200,
|
||||
child: totalLastMonthGraph.graph != null ? new charts.TimeSeriesChart(totalLastMonthGraph.graph) : Center(child: Text("Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
child: totalLastMonthGraph.graph != null
|
||||
? new charts.TimeSeriesChart(totalLastMonthGraph.graph)
|
||||
: Center(
|
||||
child: Text(
|
||||
"Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 17, 0.0, 0.0),
|
||||
child: Text(
|
||||
|
@ -135,16 +140,18 @@ class _CustomerGraphsState extends State<CustomerGraphs> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Tooltip(
|
||||
message: "Graph of average spend last month",
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
height: 200,
|
||||
child: avgSpendLastMonth.graph != null ? new charts.TimeSeriesChart(avgSpendLastMonth.graph) : Center(child: Text("Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
child: avgSpendLastMonth.graph != null
|
||||
? new charts.TimeSeriesChart(avgSpendLastMonth.graph)
|
||||
: Center(
|
||||
child: Text(
|
||||
"Loading graph...")), //List<Series<dynamic, DateTime>>
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:local_spend/pages/stats_page.dart';
|
|||
import 'package:local_spend/pages/map_page.dart';
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
static String _title = 'Text here';
|
||||
static String _title = 'SpendTracker';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -31,7 +31,7 @@ class _HomePageState extends State<HomePageWidget> {
|
|||
static List<Widget> _widgetOptions = <Widget>[
|
||||
ReceiptPage2(),
|
||||
StatsPage(),
|
||||
MapPage(),
|
||||
MapSample(),
|
||||
MorePage()
|
||||
];
|
||||
|
||||
|
@ -43,7 +43,6 @@ class _HomePageState extends State<HomePageWidget> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _itemText = TextStyle(color: Colors.grey[400]);
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||
import 'package:local_spend/common/widgets/labeled_checkbox.dart';
|
||||
import 'package:local_spend/common/widgets/animatedGradientButton.dart';
|
||||
|
||||
const URL = "https://flutter.io/";
|
||||
const url = "https://flutter.io/";
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
@override
|
||||
|
@ -20,9 +20,12 @@ class LoginPage extends StatefulWidget {
|
|||
|
||||
class LoginPageState extends State<LoginPage> {
|
||||
bool _isLoggingIn = false;
|
||||
final TextEditingController _emailController = TextEditingController(/*text: 'test@example.com'*/); // remove
|
||||
final TextEditingController _passwordController = TextEditingController(/*text: 'abc123'*/); // remove
|
||||
bool _saveLoginDetails = true; // I am extremely sorry for the placement of this variable
|
||||
final TextEditingController _emailController =
|
||||
TextEditingController(/*text: 'test@example.com'*/); // remove
|
||||
final TextEditingController _passwordController =
|
||||
TextEditingController(/*text: 'abc123'*/); // remove
|
||||
bool _saveLoginDetails =
|
||||
true; // I am extremely sorry for the placement of this variable
|
||||
// it will be fixed soon I promise
|
||||
|
||||
FocusNode focusNode; // added so focus can move automatically
|
||||
|
@ -34,7 +37,7 @@ class LoginPageState extends State<LoginPage> {
|
|||
showDialogSingleButton(
|
||||
context,
|
||||
"Unable to reach your website.",
|
||||
"Currently unable to reach the website $URL. Please try again at a later time.",
|
||||
"Currently unable to reach the website $url. Please try again at a later time.",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +58,7 @@ class LoginPageState extends State<LoginPage> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
_fillLoginDetails() async {
|
||||
void _fillLoginDetails() async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
var username = await preferences.get('username');
|
||||
|
@ -65,14 +68,14 @@ class LoginPageState extends State<LoginPage> {
|
|||
_passwordController.text = await password;
|
||||
}
|
||||
|
||||
_saveCurrentRoute(String lastRoute) async {
|
||||
void _saveCurrentRoute(String lastRoute) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString('LastPageRoute', lastRoute);
|
||||
}
|
||||
|
||||
login(String username, String password) async {
|
||||
void login(String username, String password) async {
|
||||
_isLoggingIn = true;
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
await SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
if (_saveLoginDetails) {
|
||||
|
@ -85,7 +88,7 @@ class LoginPageState extends State<LoginPage> {
|
|||
print("details cleared");
|
||||
}
|
||||
|
||||
requestLoginAPI(context, username, password).then((value) {
|
||||
await requestLoginAPI(context, username, password).then((value) {
|
||||
_isLoggingIn = false;
|
||||
});
|
||||
}
|
||||
|
@ -100,12 +103,13 @@ class LoginPageState extends State<LoginPage> {
|
|||
} else {
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
child: PlatformScaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
AnimatedBackground([Colors.lightBlue[50], Colors.lightBlue[50]], Colors.white, Alignment.topRight, Alignment.bottomLeft, 3),
|
||||
|
||||
AnimatedBackground([Colors.lightBlue[50], Colors.lightBlue[50]],
|
||||
Colors.white, Alignment.topRight, Alignment.bottomLeft, 3),
|
||||
Container(
|
||||
margin: EdgeInsets.fromLTRB(60, 30, 60, 0),
|
||||
child: Column(
|
||||
|
@ -116,8 +120,8 @@ class LoginPageState extends State<LoginPage> {
|
|||
margin: EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/images/launch_image.png')
|
||||
),
|
||||
image:
|
||||
AssetImage('assets/images/launch_image.png')),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -159,12 +163,10 @@ class LoginPageState extends State<LoginPage> {
|
|||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
login( _emailController.text,
|
||||
_passwordController.text);
|
||||
login(_emailController.text, _passwordController.text);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
margin: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
|
||||
width: 100,
|
||||
|
@ -175,15 +177,25 @@ class LoginPageState extends State<LoginPage> {
|
|||
borderRadius: BorderRadius.circular(2),
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedBackground([Colors.blue, Colors.lightBlue[300]], Colors.lightBlue, Alignment.bottomRight, Alignment.topLeft, 3),
|
||||
AnimatedBackground(
|
||||
[Colors.blue, Colors.lightBlue[300]],
|
||||
Colors.lightBlue,
|
||||
Alignment.bottomRight,
|
||||
Alignment.topLeft,
|
||||
3),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: _isLoggingIn ? null : () => login( _emailController.text, _passwordController.text),
|
||||
|
||||
onTap: _isLoggingIn
|
||||
? null
|
||||
: () => login(_emailController.text,
|
||||
_passwordController.text),
|
||||
child: new Center(
|
||||
child: new Text(
|
||||
'GO', style: new TextStyle(fontSize: 18, color: Colors.white),),
|
||||
'GO',
|
||||
style: new TextStyle(
|
||||
fontSize: 18, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -192,16 +204,16 @@ class LoginPageState extends State<LoginPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0, 10, 0, 50),
|
||||
|
||||
child: LabeledCheckbox(
|
||||
label: "SAVE LOGIN",
|
||||
textStyle: TextStyle(fontSize: 18, color: Colors.black54, fontWeight: FontWeight.bold),
|
||||
textStyle: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.black54,
|
||||
fontWeight: FontWeight.bold),
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
value: _saveLoginDetails,
|
||||
|
||||
onChanged: (bool newValue) {
|
||||
setState(() {
|
||||
_saveLoginDetails = newValue;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_maps/flutter_maps.dart';
|
||||
import 'package:local_spend/common/felixApiCreds.dart';
|
||||
import 'dart:async';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:local_spend/common/platform/platform_scaffold.dart';
|
||||
|
||||
class MapPage extends StatefulWidget {
|
||||
MapPage({Key key}) : super(key: key);
|
||||
|
@ -13,20 +14,48 @@ class MapPage extends StatefulWidget {
|
|||
|
||||
class _MapPageState extends State<MapPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Widget build(BuildContext context) {
|
||||
return PlatformScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.blue[400],
|
||||
title: Text(
|
||||
"Submit Receipt",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
body: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MapSample extends StatefulWidget {
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
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) {
|
||||
var fac = new FelixApiCreds();
|
||||
|
||||
// TODO: implement build
|
||||
return Text(fac.mapsApiKey);
|
||||
return new Scaffold(
|
||||
body: GoogleMap(
|
||||
mapType: MapType.hybrid,
|
||||
initialCameraPosition: _kGooglePlex,
|
||||
onMapCreated: (GoogleMapController controller) {
|
||||
_controller.complete(controller);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/common/platform/platform_scaffold.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
@ -7,7 +6,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||
import 'package:local_spend/common/functions/customAbout.dart' as custom;
|
||||
import 'package:local_spend/common/functions/showDialogTwoButtons.dart';
|
||||
|
||||
const URL = "https://flutter.io/";
|
||||
const url = "https://flutter.io/";
|
||||
const demonstration = false;
|
||||
|
||||
class MorePage extends StatefulWidget {
|
||||
|
@ -37,7 +36,7 @@ class MorePageState extends State<MorePage> {
|
|||
focusNode.dispose(); //disposes focus node when form disposed
|
||||
}
|
||||
|
||||
_saveCurrentRoute(String lastRoute) async {
|
||||
void _saveCurrentRoute(String lastRoute) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString('LastPageRoute', lastRoute);
|
||||
}
|
||||
|
@ -52,9 +51,9 @@ class MorePageState extends State<MorePage> {
|
|||
} else {
|
||||
Navigator.of(context).pushReplacementNamed('/LoginPage');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
child: PlatformScaffold(
|
||||
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.blue[400],
|
||||
title: Text(
|
||||
|
@ -68,11 +67,9 @@ class MorePageState extends State<MorePage> {
|
|||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
|
||||
body: Container(
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(30.0, 25, 30.0, 0.0),
|
||||
child: Text(
|
||||
|
@ -92,52 +89,48 @@ class MorePageState extends State<MorePage> {
|
|||
height: 65.0,
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
|
||||
custom.showAboutDialog(
|
||||
context: context,
|
||||
applicationIcon: new Icon(Icons.receipt),
|
||||
applicationName: "Local Spend Tracker",
|
||||
children: <Widget>
|
||||
[
|
||||
Text("Pear Trading is a commerce company designed to register and monitor money circulating in the local economy.\n"),
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Pear Trading is a commerce company designed to register and monitor money circulating in the local economy.\n"),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
height: 35,
|
||||
child: RaisedButton(
|
||||
onPressed: () => {},
|
||||
child: Text("Contact us",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 18.0)),
|
||||
style: TextStyle(
|
||||
color: Colors.white, fontSize: 18.0)),
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
height: 35,
|
||||
margin: EdgeInsets.fromLTRB(10, 20, 10, 0),
|
||||
child: RaisedButton(
|
||||
child: Text
|
||||
('Pear Trading',
|
||||
child: Text(
|
||||
'Pear Trading',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18.0
|
||||
),
|
||||
color: Colors.white, fontSize: 18.0),
|
||||
),
|
||||
color: Colors.lightGreen,
|
||||
onPressed: () => launch('http://www.peartrade.org')
|
||||
onPressed: () =>
|
||||
launch('http://www.peartrade.org')),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
height: 35,
|
||||
margin: EdgeInsets.fromLTRB(10, 20, 10, 0),
|
||||
child: Material(
|
||||
child: OutlineButton(
|
||||
child: Text
|
||||
('Shadowcat Systems',
|
||||
child: Text(
|
||||
'Shadowcat Systems',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 18.0 /// I don't know what to do with this button
|
||||
color: Colors.black, fontSize: 18.0
|
||||
|
||||
/// I don't know what to do with this button
|
||||
),
|
||||
),
|
||||
onPressed: () => launch('https://shadow.cat/'),
|
||||
|
@ -146,14 +139,11 @@ class MorePageState extends State<MorePage> {
|
|||
shadowColor: Colors.transparent,
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
);
|
||||
|
||||
},
|
||||
child: Text("ABOUT",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
|
@ -171,12 +161,10 @@ class MorePageState extends State<MorePage> {
|
|||
"Are you sure you want to log out?",
|
||||
"Cancel",
|
||||
"Logout",
|
||||
logout
|
||||
);
|
||||
logout);
|
||||
},
|
||||
child: Text("LOGOUT",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
|
@ -197,7 +185,6 @@ class MorePageState extends State<MorePage> {
|
|||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/common/platform/platform_scaffold.dart';
|
||||
import 'package:shared_preferences/shared_preferences.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 url = "https://flutter.io/";
|
||||
const demonstration = false;
|
||||
|
||||
class NewStatsPage extends StatefulWidget {
|
||||
|
@ -15,7 +13,6 @@ class NewStatsPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class NewStatsPageState extends State<NewStatsPage> {
|
||||
|
||||
/// Graph types:
|
||||
/// - total_last_week
|
||||
/// - avg_spend_last_week
|
||||
|
@ -33,14 +30,13 @@ class NewStatsPageState extends State<NewStatsPage> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
_saveCurrentRoute(String lastRoute) async {
|
||||
void _saveCurrentRoute(String lastRoute) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString('LastPageRoute', lastRoute);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return PlatformScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.blue[400],
|
||||
|
@ -55,11 +51,7 @@ class NewStatsPageState extends State<NewStatsPage> {
|
|||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
|
||||
|
||||
body : Container(
|
||||
|
||||
),
|
||||
body: Container(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/common/apifunctions/get_graph_data.dart';
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
//import 'package:charts_flutter/flutter.dart' as charts;
|
||||
|
||||
class OrgGraphs extends StatefulWidget {
|
||||
OrgGraphs({Key key}) : super(key: key);
|
||||
|
@ -27,9 +27,7 @@ class _OrgGraphsState extends State<OrgGraphs> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
|
||||
],
|
||||
children: <Widget>[],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:local_spend/common/platform/platform_scaffold.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'dart:core';
|
||||
import 'dart:async';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:local_spend/common/widgets/animatedGradientButton.dart';
|
||||
import 'package:local_spend/common/apifunctions/find_organisations.dart';
|
||||
|
@ -10,13 +10,6 @@ import 'package:local_spend/common/apifunctions/submit_receipt_api.dart';
|
|||
import 'package:local_spend/common/apifunctions/categories.dart';
|
||||
|
||||
class Transaction {
|
||||
DateTime date;
|
||||
TextEditingController amount;
|
||||
Organisation organisation;
|
||||
String recurring;
|
||||
bool isEssential;
|
||||
String category;
|
||||
|
||||
Transaction(
|
||||
this.date,
|
||||
this.amount,
|
||||
|
@ -25,6 +18,13 @@ class Transaction {
|
|||
this.isEssential,
|
||||
this.category,
|
||||
);
|
||||
|
||||
DateTime date;
|
||||
TextEditingController amount;
|
||||
Organisation organisation;
|
||||
String recurring;
|
||||
bool isEssential;
|
||||
String category;
|
||||
}
|
||||
|
||||
class ReceiptPage2 extends StatefulWidget {
|
||||
|
@ -44,7 +44,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
"Uncategorised",
|
||||
);
|
||||
|
||||
_invalidDialog(context) {
|
||||
AlertDialog _invalidDialog(context) {
|
||||
return AlertDialog(
|
||||
title: new Text("Invalid data"),
|
||||
content: new Text(
|
||||
|
@ -64,9 +64,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
return await getCategories();
|
||||
}
|
||||
|
||||
_submitReceipt(Transaction transaction) {
|
||||
DateTime dt = new DateTime.now();
|
||||
|
||||
void _submitReceipt(Transaction transaction) {
|
||||
Receipt receipt = new Receipt();
|
||||
receipt.organisationName = transaction.organisation.name;
|
||||
receipt.street = transaction.organisation.streetName;
|
||||
|
@ -86,7 +84,9 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
}
|
||||
|
||||
receipt.amount = transaction.amount.text.toString();
|
||||
receipt.time = DateFormat("yyyy-MM-dd'T'hh:mm':00.000+01:00'").format(transaction.date).toString();
|
||||
receipt.time = DateFormat("yyyy-MM-dd'T'hh:mm':00.000+01:00'")
|
||||
.format(transaction.date)
|
||||
.toString();
|
||||
receipt.essential = transaction.isEssential.toString();
|
||||
|
||||
submitReceiptAPI(context, receipt);
|
||||
|
@ -97,10 +97,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _widgetHeight = MediaQuery.of(context).size.height * 0.06 < 40.0
|
||||
? 40.0
|
||||
: MediaQuery.of(context).size.height * 0.06;
|
||||
|
||||
var _widgetHeight = MediaQuery.of(context).size.height * 0.06 < 40.0 ? 40.0 : MediaQuery.of(context).size.height * 0.06;
|
||||
|
||||
if (_categories.length == 0) {
|
||||
if (_categories.isNotEmpty) {
|
||||
Future<List<String>> _futureCats = getCats();
|
||||
_categories.add("Fetching categories...");
|
||||
_futureCats.then((value) {
|
||||
|
@ -115,8 +116,8 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
_sampleRecurringOptions[3] = "Fortnightly";
|
||||
_sampleRecurringOptions[4] = "Monthly";
|
||||
_sampleRecurringOptions[5] = "Quarterly";
|
||||
_sampleRecurringOptions[6] = "Yearly"; // these will be difficult to fetch from server as they are coded into the site's rather than fetched
|
||||
|
||||
_sampleRecurringOptions[6] = "Yearly";
|
||||
// these will be difficult to fetch from server as they are coded into the site's HTML rather than fetched
|
||||
|
||||
return PlatformScaffold(
|
||||
appBar: AppBar(
|
||||
|
@ -131,14 +132,18 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
|
||||
body: ListView(
|
||||
children: <Widget>[
|
||||
// each CHILD has its own horizontal padding because if the listView has padding, Android's end-of-scroll animation
|
||||
// each CHILD has its own horizontal padding because if the listView
|
||||
// has padding, Android's end-of-scroll animation
|
||||
// doesn't fit the screen properly and looks weird
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.025,MediaQuery.of(context).size.height * 0.025,0,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.025,
|
||||
MediaQuery.of(context).size.height * 0.025,
|
||||
0,
|
||||
0.0),
|
||||
child: Text(
|
||||
"Receipt Details",
|
||||
style: TextStyle(
|
||||
|
@ -150,7 +155,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // "Receipt Details" title
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Tooltip(
|
||||
message: "Date and time of transaction",
|
||||
child: Row(
|
||||
|
@ -166,7 +175,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
height: _widgetHeight,
|
||||
|
@ -177,15 +185,21 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
context: context,
|
||||
builder: (BuildContext builder) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).copyWith().size.height / 3,
|
||||
height: MediaQuery.of(context)
|
||||
.copyWith()
|
||||
.size
|
||||
.height /
|
||||
3,
|
||||
child: CupertinoDatePicker(
|
||||
initialDateTime: transaction.date.isAfter(DateTime.now())
|
||||
initialDateTime:
|
||||
transaction.date.isAfter(DateTime.now())
|
||||
? DateTime.now()
|
||||
: transaction.date,
|
||||
onDateTimeChanged: (DateTime newDate) {
|
||||
setState(() => {
|
||||
newDate.isAfter(DateTime.now())
|
||||
? transaction.date = DateTime.now()
|
||||
? transaction.date =
|
||||
DateTime.now()
|
||||
: transaction.date = newDate,
|
||||
});
|
||||
},
|
||||
|
@ -199,12 +213,20 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
transaction.date == null
|
||||
? 'None set.'
|
||||
: transaction.date.year != DateTime.now().year
|
||||
? '${new DateFormat.MMMd().format(transaction.date)}' + " " + transaction.date.year.toString() + " at " + '${new DateFormat.Hm().format(transaction.date)}'
|
||||
: transaction.date.day == DateTime.now().day && transaction.date.month == DateTime.now().month
|
||||
? "Today at " + '${new DateFormat.Hm().format(transaction.date)}'
|
||||
: '${new DateFormat.MMMd().format(transaction.date)}' + " at " + '${new DateFormat.Hm().format(transaction.date)}',
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
? '${new DateFormat.MMMd().format(transaction.date)}' +
|
||||
" " +
|
||||
transaction.date.year.toString() +
|
||||
" at " +
|
||||
'${new DateFormat.Hm().format(transaction.date)}'
|
||||
: transaction.date.day == DateTime.now().day &&
|
||||
transaction.date.month ==
|
||||
DateTime.now().month
|
||||
? "Today at " +
|
||||
'${new DateFormat.Hm().format(transaction.date)}'
|
||||
: '${new DateFormat.MMMd().format(transaction.date)}' +
|
||||
" at " +
|
||||
'${new DateFormat.Hm().format(transaction.date)}',
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
),
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
@ -215,7 +237,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Date/Time picker
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Tooltip(
|
||||
message: "Transaction payee",
|
||||
child: Row(
|
||||
|
@ -231,7 +257,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
height: _widgetHeight,
|
||||
|
@ -255,10 +280,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
transaction.organisation.name == null
|
||||
? 'Find'
|
||||
: transaction.organisation.name.length > 14
|
||||
? transaction.organisation.name.substring(0,12) + "..."
|
||||
? transaction.organisation.name
|
||||
.substring(0, 12) +
|
||||
"..."
|
||||
: transaction.organisation.name,
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
),
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
@ -269,7 +295,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Organisation picker
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Tooltip(
|
||||
message: "Repeating?",
|
||||
child: Row(
|
||||
|
@ -285,7 +315,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
height: _widgetHeight,
|
||||
|
@ -296,12 +325,20 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
context: context,
|
||||
builder: (BuildContext builder) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).copyWith().size.height / 3,
|
||||
height: MediaQuery.of(context)
|
||||
.copyWith()
|
||||
.size
|
||||
.height /
|
||||
3,
|
||||
child: CupertinoPicker(
|
||||
backgroundColor: Colors.white,
|
||||
children: _sampleRecurringOptions.map((thisOption) => Text(thisOption, style: TextStyle(fontSize: 30))).toList(),
|
||||
children: _sampleRecurringOptions
|
||||
.map((thisOption) => Text(thisOption,
|
||||
style: TextStyle(fontSize: 30)))
|
||||
.toList(),
|
||||
onSelectedItemChanged: ((newValue) {
|
||||
transaction.recurring = _sampleRecurringOptions[newValue];
|
||||
transaction.recurring =
|
||||
_sampleRecurringOptions[newValue];
|
||||
setState(() {});
|
||||
}),
|
||||
magnification: 1.1,
|
||||
|
@ -309,15 +346,13 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
itemExtent: 36,
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
child: Text(
|
||||
transaction.recurring == null
|
||||
? 'None'
|
||||
: transaction.recurring,
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
),
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
@ -328,7 +363,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Recurring picker
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
|
@ -342,7 +381,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
height: _widgetHeight,
|
||||
|
@ -355,12 +393,22 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
context: context,
|
||||
builder: (BuildContext builder) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).copyWith().size.height / 3,
|
||||
height: MediaQuery.of(context)
|
||||
.copyWith()
|
||||
.size
|
||||
.height /
|
||||
3,
|
||||
child: CupertinoPicker(
|
||||
backgroundColor: Colors.white,
|
||||
children: _categories.map((thisOption) => Text(thisOption, style: TextStyle(fontSize: 30),)).toList(),
|
||||
children: _categories
|
||||
.map((thisOption) => Text(
|
||||
thisOption,
|
||||
style: TextStyle(fontSize: 30),
|
||||
))
|
||||
.toList(),
|
||||
onSelectedItemChanged: ((newValue) {
|
||||
transaction.category = _categories[newValue];
|
||||
transaction.category =
|
||||
_categories[newValue];
|
||||
setState(() {});
|
||||
}),
|
||||
magnification: 1.1,
|
||||
|
@ -374,8 +422,7 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
transaction.category == null
|
||||
? 'None'
|
||||
: transaction.category,
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
style: TextStyle(color: Colors.white, fontSize: 22.0),
|
||||
),
|
||||
color: Colors.blue,
|
||||
),
|
||||
|
@ -386,7 +433,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Category picker
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Tooltip(
|
||||
message: "Essential or not",
|
||||
child: Row(
|
||||
|
@ -402,7 +453,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
Container(
|
||||
height: _widgetHeight,
|
||||
width: MediaQuery.of(context).size.width * 0.6,
|
||||
|
@ -419,7 +469,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Essential
|
||||
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
0.0),
|
||||
child: Tooltip(
|
||||
message: "Transaction amount",
|
||||
child: Row(
|
||||
|
@ -435,8 +489,6 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
),
|
||||
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
height: _widgetHeight,
|
||||
|
@ -447,10 +499,9 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
),
|
||||
textAlign: TextAlign.center,
|
||||
controller: transaction.amount,
|
||||
decoration: InputDecoration(
|
||||
hintText: "0.00"
|
||||
),
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true, signed: true),
|
||||
decoration: InputDecoration(hintText: "0.00"),
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
decimal: true, signed: true),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -459,7 +510,11 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
), // Amount picker
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,MediaQuery.of(context).size.height * 0.03,MediaQuery.of(context).size.width * 0.05,15.0),
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
MediaQuery.of(context).size.height * 0.03,
|
||||
MediaQuery.of(context).size.width * 0.05,
|
||||
15.0),
|
||||
child: Tooltip(
|
||||
message: "Submit receipt",
|
||||
child: Container(
|
||||
|
@ -470,45 +525,52 @@ class ReceiptPage2State extends State<ReceiptPage2> {
|
|||
opacity: 1,
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedBackground([Colors.blue, Colors.lightBlue[300]], Colors.lightBlue, Alignment.topLeft, Alignment.bottomRight, 4),
|
||||
AnimatedBackground(
|
||||
[Colors.blue, Colors.lightBlue[300]],
|
||||
Colors.lightBlue,
|
||||
Alignment.topLeft,
|
||||
Alignment.bottomRight,
|
||||
4),
|
||||
Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
child: Center(
|
||||
child : Text("GO",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 30.0),
|
||||
child: Text(
|
||||
"GO",
|
||||
style: TextStyle(
|
||||
color: Colors.white, fontSize: 30.0),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
try {
|
||||
if (transaction.amount.text == "" || transaction.organisation.name == null) {
|
||||
if (transaction.amount.text == "" ||
|
||||
transaction.organisation.name == null) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return _invalidDialog(context);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
if (double.tryParse(transaction.amount.text) != null && double.tryParse(transaction.amount.text) > 0) {
|
||||
if (double.tryParse(
|
||||
transaction.amount.text) !=
|
||||
null &&
|
||||
double.tryParse(transaction.amount.text) >
|
||||
0) {
|
||||
_submitReceipt(transaction);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return _invalidDialog(context);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (_) {
|
||||
} catch (_) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return _invalidDialog(context);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
@ -12,7 +12,7 @@ class SplashScreen extends StatefulWidget {
|
|||
class _SplashScreenState extends State<SplashScreen> {
|
||||
final int splashDuration = 1;
|
||||
|
||||
startTime() async {
|
||||
Future<Timer> startTime() async {
|
||||
return Timer(Duration(seconds: splashDuration), () {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
Navigator.of(context).pushReplacementNamed('/LoginPage');
|
||||
|
@ -41,8 +41,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||
alignment: FractionalOffset(0.5, 0.3),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('assets/images/launch_image.png')
|
||||
),
|
||||
image: AssetImage('assets/images/launch_image.png')),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
import 'package:local_spend/pages/customerGraphs.dart';
|
||||
import 'package:local_spend/pages/orgGraphs.dart';
|
||||
|
||||
const URL = "https://flutter.io/";
|
||||
const url = "https://flutter.io/";
|
||||
const demonstration = false;
|
||||
|
||||
class StatsPage extends StatefulWidget {
|
||||
|
@ -28,7 +28,7 @@ class StatsPageState extends State<StatsPage> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
_saveCurrentRoute(String lastRoute) async {
|
||||
void _saveCurrentRoute(String lastRoute) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString('LastPageRoute', lastRoute);
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ class StatsPageState extends State<StatsPage> {
|
|||
if (userType == "-") {
|
||||
_getUserType().then((value) {
|
||||
print(value);
|
||||
userType = '${value[0].toUpperCase()}${value.substring(1)}'; // capitalises first letter
|
||||
userType =
|
||||
'${value[0].toUpperCase()}${value.substring(1)}'; // capitalises first letter
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
@ -62,10 +63,7 @@ class StatsPageState extends State<StatsPage> {
|
|||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4)
|
||||
),
|
||||
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 4)),
|
||||
Text(
|
||||
userType,
|
||||
style: TextStyle(
|
||||
|
@ -78,11 +76,13 @@ class StatsPageState extends State<StatsPage> {
|
|||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
|
||||
|
||||
body: Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
child: (userType == "-" ? null : (userType.toLowerCase() == "customer" ? CustomerGraphs() : OrgGraphs())),
|
||||
child: (userType == "-"
|
||||
? null
|
||||
: (userType.toLowerCase() == "customer"
|
||||
? CustomerGraphs()
|
||||
: OrgGraphs())),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
61
pubspec.lock
61
pubspec.lock
|
@ -35,42 +35,42 @@ packages:
|
|||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.4"
|
||||
version: "1.1.6"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
version: "0.4.1+1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "2.0.0"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
version: "1.0.7"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.1"
|
||||
version: "1.6.6"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
version: "3.0.9"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -84,7 +84,7 @@ packages:
|
|||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.6.0"
|
||||
version: "6.7.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -106,6 +106,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -133,14 +140,14 @@ packages:
|
|||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
version: "2.1.2"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
version: "0.16.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -154,7 +161,7 @@ packages:
|
|||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.7"
|
||||
version: "1.2.9"
|
||||
datetime_picker_formfield:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -193,13 +200,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_maps:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_maps
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
@ -219,6 +219,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.7"
|
||||
google_maps_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: google_maps_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.5.20+5"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -283,7 +290,7 @@ packages:
|
|||
source: hosted
|
||||
version: "2.3.0"
|
||||
json_serializable:
|
||||
dependency: "direct dev"
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: json_serializable
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -330,7 +337,7 @@ packages:
|
|||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
version: "1.1.0"
|
||||
package_resolver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -346,7 +353,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.6.2"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -372,7 +379,7 @@ packages:
|
|||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -419,7 +426,7 @@ packages:
|
|||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.4+2"
|
||||
version: "0.9.4+3"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -475,7 +482,7 @@ packages:
|
|||
name: timing
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.1+1"
|
||||
version: "0.1.1+2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -503,14 +510,14 @@ packages:
|
|||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.7+10"
|
||||
version: "0.9.7+12"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.13"
|
||||
version: "1.0.15"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -519,5 +526,5 @@ packages:
|
|||
source: hosted
|
||||
version: "2.1.16"
|
||||
sdks:
|
||||
dart: ">=2.3.0-dev.0.1 <3.0.0"
|
||||
flutter: ">=0.1.4 <2.0.0"
|
||||
dart: ">=2.3.0 <3.0.0"
|
||||
flutter: ">=1.5.0 <2.0.0"
|
||||
|
|
10
pubspec.yaml
10
pubspec.yaml
|
@ -10,7 +10,7 @@ description: Local Spend Tracker
|
|||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
sdk: ">=2.2.2 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
@ -26,7 +26,8 @@ dependencies:
|
|||
flutter_fadein: ^1.1.1
|
||||
charts_flutter: ^0.6.0
|
||||
simple_animations: ^1.3.3
|
||||
flutter_maps: ^0.1.0
|
||||
google_maps_flutter: ^0.5.20+5
|
||||
json_serializable: ^2.0.2
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^0.1.2
|
||||
|
@ -34,9 +35,8 @@ dependencies:
|
|||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
build_runner: ^1.1.3
|
||||
json_serializable: ^2.1.2
|
||||
|
||||
pedantic: ^1.4.0
|
||||
build_runner: ^1.2.7
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:flutter_test/flutter_test.dart';
|
|||
import 'package:local_spend/main.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
testWidgets('GO button repetition test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(MyApp());
|
||||
|
|
Reference in a new issue