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
|
@ -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";
|
||||
|
@ -13,10 +12,10 @@ Future<List<String>> getCategories() async {
|
|||
});
|
||||
|
||||
Map<String, String> body = {
|
||||
"session_key":token,
|
||||
"session_key": token,
|
||||
};
|
||||
|
||||
final response = await http.post (
|
||||
final response = await http.post(
|
||||
url,
|
||||
body: json.encode(body),
|
||||
);
|
||||
|
@ -36,9 +35,8 @@ Future<List<String>> getCategories() async {
|
|||
|
||||
// print(categoriesJSON['11']); // prints "Banana"
|
||||
|
||||
int i = 1; // starts on 1. that was annoying to debug!
|
||||
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()]);
|
||||
|
@ -61,10 +59,10 @@ Future<List<String>> getCategories() async {
|
|||
|
||||
// print(categories[10].name.toString()); // prints "Banana"
|
||||
|
||||
return categories; // categories is List<Category>
|
||||
return categories; // categories is List<Category>
|
||||
// Category is defined at the top^^
|
||||
} else {
|
||||
// not successful
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,32 @@
|
|||
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,
|
||||
this.postcode,
|
||||
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;
|
||||
|
@ -72,11 +65,11 @@ class Organisations {
|
|||
});
|
||||
|
||||
Map<String, String> body = {
|
||||
"search_name":search,
|
||||
"session_key":token,
|
||||
"search_name": search,
|
||||
"session_key": token,
|
||||
};
|
||||
|
||||
final response = await http.post (
|
||||
final response = await http.post(
|
||||
url,
|
||||
body: json.encode(body),
|
||||
);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,11 @@ Future<void> _incorrectDialog(BuildContext context, bool isLoginWrong) async {
|
|||
builder: (BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
duration: Duration(seconds: 2),
|
||||
child : AlertDialog(
|
||||
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(
|
||||
url,
|
||||
body: json.encode(body),
|
||||
).timeout(Duration(seconds: 5));
|
||||
final response = await http
|
||||
.post(
|
||||
url,
|
||||
body: json.encode(body),
|
||||
)
|
||||
.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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ Future<LoginModel> requestLogoutAPI(BuildContext context) async {
|
|||
});
|
||||
|
||||
Map<String, String> body = {
|
||||
"Token":token,
|
||||
"Token": token,
|
||||
};
|
||||
|
||||
final response = await http.post(
|
||||
|
|
|
@ -28,7 +28,7 @@ Future<LoginModel> submitReceiptAPI(
|
|||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
|
||||
Map<String, String> body = {
|
||||
'transaction_type' : "3",
|
||||
'transaction_type': "3",
|
||||
'transaction_value': receipt.amount,
|
||||
'purchase_time': receipt.time,
|
||||
'category': receipt.category,
|
||||
|
@ -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>(
|
||||
builder: (BuildContext context) => LicensePage(
|
||||
applicationName: applicationName,
|
||||
applicationVersion: applicationVersion,
|
||||
applicationLegalese: applicationLegalese,
|
||||
)
|
||||
));
|
||||
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,
|
||||
|
@ -376,7 +386,7 @@ class _LicensePageState extends State<LicensePage> {
|
|||
int debugFlowId = -1;
|
||||
assert(() {
|
||||
final dev.Flow flow = dev.Flow.begin();
|
||||
dev.Timeline.timeSync('_initLicenses()', () { }, flow: flow);
|
||||
dev.Timeline.timeSync('_initLicenses()', () {}, flow: flow);
|
||||
debugFlowId = flow.id;
|
||||
return true;
|
||||
}());
|
||||
|
@ -385,11 +395,12 @@ 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 =
|
||||
await SchedulerBinding.instance.scheduleTask<List<LicenseParagraph>>(
|
||||
await SchedulerBinding.instance.scheduleTask<List<LicenseParagraph>>(
|
||||
license.paragraphs.toList,
|
||||
Priority.animation,
|
||||
debugLabel: 'License',
|
||||
|
@ -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,13 +14,11 @@ 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(
|
||||
child: new TextField(
|
||||
controller: _feedbackController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter your feedback here',
|
||||
|
@ -41,7 +38,7 @@ void feedback(
|
|||
),
|
||||
new Container(
|
||||
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||
child : new FlatButton(
|
||||
child: new FlatButton(
|
||||
child: new Text("Submit"),
|
||||
onPressed: () {
|
||||
submit(_feedbackController.text);
|
||||
|
@ -58,4 +55,4 @@ void feedback(
|
|||
|
||||
void submit(String feedback) {
|
||||
debugPrint(feedback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,6 +4,25 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class PlatformScaffold extends StatelessWidget {
|
||||
|
||||
PlatformScaffold(
|
||||
{this.key,
|
||||
this.appBar,
|
||||
this.body,
|
||||
this.floatingActionButton,
|
||||
this.floatingActionButtonLocation,
|
||||
this.floatingActionButtonAnimator,
|
||||
this.persistentFooterButtons,
|
||||
this.drawer,
|
||||
this.endDrawer,
|
||||
this.bottomNavigationBar,
|
||||
this.backgroundColor,
|
||||
this.resizeToAvoidBottomPadding = true,
|
||||
this.primary = true})
|
||||
: assert(primary != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
final Key key;
|
||||
final PreferredSizeWidget appBar;
|
||||
final Widget body;
|
||||
|
@ -18,23 +37,6 @@ class PlatformScaffold extends StatelessWidget {
|
|||
final bool resizeToAvoidBottomPadding;
|
||||
final bool primary;
|
||||
|
||||
PlatformScaffold(
|
||||
{this.key,
|
||||
this.appBar,
|
||||
this.body,
|
||||
this.floatingActionButton,
|
||||
this.floatingActionButtonLocation,
|
||||
this.floatingActionButtonAnimator,
|
||||
this.persistentFooterButtons,
|
||||
this.drawer,
|
||||
this.endDrawer,
|
||||
this.bottomNavigationBar,
|
||||
this.backgroundColor,
|
||||
this.resizeToAvoidBottomPadding: true,
|
||||
this.primary: true})
|
||||
: assert(primary != null),
|
||||
super(key: key);
|
||||
|
||||
@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([
|
||||
|
@ -37,4 +38,4 @@ class AnimatedBackground extends StatelessWidget {
|
|||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
@ -16,4 +15,4 @@ class TimeSeries extends StatelessWidget {
|
|||
child: SimpleTimeSeriesChart.withSampleData(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
@ -29,7 +29,7 @@ class NumericComboLineBarChart extends StatelessWidget {
|
|||
// Custom renderer configuration for the bar series.
|
||||
customSeriesRenderers: [
|
||||
new charts.BarRendererConfig(
|
||||
// ID used to link series to this renderer.
|
||||
// ID used to link series to this renderer.
|
||||
customRendererId: 'customBar')
|
||||
]);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class NumericComboLineBarChart extends StatelessWidget {
|
|||
measureFn: (LinearSales sales, _) => sales.sales,
|
||||
data: desktopSalesData,
|
||||
)
|
||||
// Configure our custom bar renderer for this series.
|
||||
// Configure our custom bar renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customBar'),
|
||||
new charts.Series<LinearSales, int>(
|
||||
id: 'Tablet',
|
||||
|
@ -74,7 +74,7 @@ class NumericComboLineBarChart extends StatelessWidget {
|
|||
measureFn: (LinearSales sales, _) => sales.sales,
|
||||
data: tableSalesData,
|
||||
)
|
||||
// Configure our custom bar renderer for this series.
|
||||
// Configure our custom bar renderer for this series.
|
||||
..setAttribute(charts.rendererIdKey, 'customBar'),
|
||||
new charts.Series<LinearSales, int>(
|
||||
id: 'Mobile',
|
||||
|
@ -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) {
|
||||
|
@ -77,7 +77,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Cheese',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.blue.shadeDefault,
|
||||
charts.MaterialPalette.blue.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -85,7 +85,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Carrots',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.red.shadeDefault,
|
||||
charts.MaterialPalette.red.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -93,7 +93,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Cucumbers',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.green.shadeDefault,
|
||||
charts.MaterialPalette.green.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -101,7 +101,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Crayons',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.purple.shadeDefault,
|
||||
charts.MaterialPalette.purple.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -109,7 +109,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Celery',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.indigo.shadeDefault,
|
||||
charts.MaterialPalette.indigo.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -117,7 +117,7 @@ class BucketingAxisScatterPlotChart extends StatelessWidget {
|
|||
new charts.Series<LinearSales, int>(
|
||||
id: 'Cauliflower',
|
||||
colorFn: (LinearSales sales, _) =>
|
||||
charts.MaterialPalette.gray.shadeDefault,
|
||||
charts.MaterialPalette.gray.shadeDefault,
|
||||
domainFn: (LinearSales sales, _) => sales.year,
|
||||
measureFn: (LinearSales sales, _) => sales.revenueShare,
|
||||
radiusPxFn: (LinearSales sales, _) => sales.radius,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,12 +58,10 @@ class CustomCheckbox extends StatefulWidget {
|
|||
this.checkColor,
|
||||
this.materialTapTargetSize,
|
||||
this.useTapTarget = true,
|
||||
}) : assert(tristate != null),
|
||||
}) : assert(tristate != null),
|
||||
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,19 +174,18 @@ class _CustomCheckboxState extends State<CustomCheckbox> with TickerProviderStat
|
|||
}
|
||||
|
||||
class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
const _CheckboxRenderObjectWidget({
|
||||
Key key,
|
||||
@required this.value,
|
||||
@required this.tristate,
|
||||
@required this.activeColor,
|
||||
@required this.checkColor,
|
||||
@required this.inactiveColor,
|
||||
@required this.onChanged,
|
||||
@required this.vsync,
|
||||
@required this.additionalConstraints,
|
||||
this.useTapTarget = true
|
||||
|
||||
}) : assert(tristate != null),
|
||||
const _CheckboxRenderObjectWidget(
|
||||
{Key key,
|
||||
@required this.value,
|
||||
@required this.tristate,
|
||||
@required this.activeColor,
|
||||
@required this.checkColor,
|
||||
@required this.inactiveColor,
|
||||
@required this.onChanged,
|
||||
@required this.vsync,
|
||||
@required this.additionalConstraints,
|
||||
this.useTapTarget = true})
|
||||
: assert(tristate != null),
|
||||
assert(tristate || value != null),
|
||||
assert(activeColor != null),
|
||||
assert(inactiveColor != null),
|
||||
|
@ -205,15 +204,15 @@ class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
|
|||
|
||||
@override
|
||||
_RenderCheckbox createRenderObject(BuildContext context) => _RenderCheckbox(
|
||||
value: value,
|
||||
tristate: tristate,
|
||||
activeColor: activeColor,
|
||||
checkColor: checkColor,
|
||||
inactiveColor: inactiveColor,
|
||||
onChanged: onChanged,
|
||||
vsync: vsync,
|
||||
additionalConstraints: additionalConstraints,
|
||||
);
|
||||
value: value,
|
||||
tristate: tristate,
|
||||
activeColor: activeColor,
|
||||
checkColor: checkColor,
|
||||
inactiveColor: inactiveColor,
|
||||
onChanged: onChanged,
|
||||
vsync: vsync,
|
||||
additionalConstraints: additionalConstraints,
|
||||
);
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, _RenderCheckbox renderObject) {
|
||||
|
@ -243,24 +242,23 @@ class _RenderCheckbox extends RenderToggleable {
|
|||
BoxConstraints additionalConstraints,
|
||||
ValueChanged<bool> onChanged,
|
||||
@required TickerProvider vsync,
|
||||
}) : _oldValue = value,
|
||||
}) : _oldValue = value,
|
||||
super(
|
||||
value: value,
|
||||
tristate: tristate,
|
||||
activeColor: activeColor,
|
||||
inactiveColor: inactiveColor,
|
||||
onChanged: onChanged,
|
||||
additionalConstraints: additionalConstraints,
|
||||
vsync: vsync,
|
||||
);
|
||||
value: value,
|
||||
tristate: tristate,
|
||||
activeColor: activeColor,
|
||||
inactiveColor: inactiveColor,
|
||||
onChanged: onChanged,
|
||||
additionalConstraints: additionalConstraints,
|
||||
vsync: vsync,
|
||||
);
|
||||
|
||||
bool _oldValue;
|
||||
Color checkColor;
|
||||
|
||||
@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,11 +349,13 @@ 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
|
||||
? position.value
|
||||
: 1.0 - position.value;
|
||||
final double tNormalized =
|
||||
status == AnimationStatus.forward || status == AnimationStatus.completed
|
||||
? position.value
|
||||
: 1.0 - position.value;
|
||||
|
||||
// Four cases: false to null, false to true, null to false, true to false
|
||||
if (_oldValue == false || value == false) {
|
||||
|
@ -366,29 +370,36 @@ 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);
|
||||
final Paint paint = Paint()..color = _colorAt(1.0);
|
||||
canvas.drawRRect(outer, paint);
|
||||
|
||||
_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(
|
||||
child: Icon(
|
||||
icon,
|
||||
// size: iconSize,
|
||||
// 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:
|
||||
|
||||
|
@ -134,4 +130,4 @@ Widget build(BuildContext context) {
|
|||
),
|
||||
);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
@ -95,148 +92,150 @@ class FindOrganisations {
|
|||
listTitle = "Results for \'" + search + "\'";
|
||||
|
||||
var futureOrgs = await organisations.findOrganisations(search);
|
||||
organisationsList = futureOrgs;
|
||||
_searchEnabled = true;
|
||||
return futureOrgs.length;
|
||||
organisationsList = futureOrgs;
|
||||
_searchEnabled = true;
|
||||
return futureOrgs.length;
|
||||
}
|
||||
|
||||
return showDialog<Organisation>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
|
||||
builder: (BuildContext context) {
|
||||
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
return SimpleDialog(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
|
||||
width: 150,
|
||||
height: 50,
|
||||
child: TextField(
|
||||
autofocus: true,
|
||||
controller: searchBarText,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Payee Name",
|
||||
),
|
||||
onChanged: (value) {
|
||||
if (value.length > 0) {
|
||||
_searchEnabled = true;
|
||||
} else {
|
||||
_searchEnabled = false;
|
||||
}
|
||||
setState(() => {_searchEnabled});
|
||||
},
|
||||
onSubmitted: _searchEnabled ? ((_) {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
var result = _submitSearch(searchBarText.text);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
});
|
||||
});
|
||||
}) : null,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
|
||||
width: 150,
|
||||
height: 50,
|
||||
child: TextField(
|
||||
autofocus: true,
|
||||
controller: searchBarText,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Payee Name",
|
||||
),
|
||||
|
||||
Container(
|
||||
width: 80,
|
||||
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
|
||||
|
||||
child: RaisedButton(
|
||||
onPressed: _searchEnabled ? (() {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
var result = _submitSearch(searchBarText.text);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
onChanged: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
_searchEnabled = true;
|
||||
} else {
|
||||
_searchEnabled = false;
|
||||
}
|
||||
setState(() => {_searchEnabled});
|
||||
},
|
||||
onSubmitted: _searchEnabled
|
||||
? ((_) {
|
||||
SystemChannels.textInput
|
||||
.invokeMethod('TextInput.hide');
|
||||
var result =
|
||||
_submitSearch(searchBarText.text);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
}) : null,
|
||||
|
||||
child: Icon(Icons.search, color: Colors.white),
|
||||
color : Colors.blue,
|
||||
),
|
||||
),
|
||||
],
|
||||
})
|
||||
: 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);
|
||||
result.then((_) {
|
||||
setState(() {
|
||||
_orgsFetched = true;
|
||||
});
|
||||
});
|
||||
})
|
||||
: null,
|
||||
child: Icon(Icons.search, color: Colors.white),
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Column(
|
||||
children: _orgsFetched ? [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
|
||||
child: Text(
|
||||
listTitle,
|
||||
style: new TextStyle(
|
||||
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,
|
||||
|
||||
child: Material(
|
||||
shadowColor: Colors.transparent,
|
||||
color: Colors.transparent,
|
||||
child: ListView.builder(
|
||||
itemCount: organisationsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.person),
|
||||
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]);
|
||||
},
|
||||
onLongPress: (){
|
||||
// show more details about the organisation in a new dialog
|
||||
var moreInfo = _moreInfoDialog(context, organisationsList[index]);
|
||||
moreInfo.whenComplete(null);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
Column(
|
||||
children: _orgsFetched
|
||||
? [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
|
||||
child: Text(
|
||||
listTitle,
|
||||
style: new TextStyle(
|
||||
fontSize: 23, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Center(
|
||||
child : Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||
child : Text("Long press a payee for more info", style: TextStyle(fontStyle: FontStyle.italic)),
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height * 0.67,
|
||||
child: Material(
|
||||
shadowColor: Colors.transparent,
|
||||
color: Colors.transparent,
|
||||
child: ListView.builder(
|
||||
itemCount: organisationsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.person),
|
||||
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]);
|
||||
},
|
||||
onLongPress: () {
|
||||
// show more details about the organisation in a new dialog
|
||||
var moreInfo = _moreInfoDialog(
|
||||
context, organisationsList[index]);
|
||||
moreInfo.whenComplete(null);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
] : [ Container() ],
|
||||
),
|
||||
Center(
|
||||
child: Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
|
||||
child: Text("Long press a payee for more info",
|
||||
style:
|
||||
TextStyle(fontStyle: FontStyle.italic)),
|
||||
),
|
||||
),
|
||||
]
|
||||
: [Container()],
|
||||
),
|
||||
|
||||
// help button for if org not listed
|
||||
// cancel and ok buttons
|
||||
|
||||
],
|
||||
// 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++) {
|
||||
|
@ -33,4 +33,4 @@ class PopupListView {
|
|||
|
||||
return dialogOptionsList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue