WORKS!!!!!!!!
We did it boys, we uploaded a transaction
This commit is contained in:
parent
7dd00349a8
commit
e3ca987aa8
12 changed files with 87 additions and 274 deletions
Binary file not shown.
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
BIN
assets/zapsplat_sport_air_horn_2x_blasts_002_21151.mp3
Normal file
BIN
assets/zapsplat_sport_air_horn_2x_blasts_002_21151.mp3
Normal file
Binary file not shown.
|
@ -6,13 +6,13 @@ PODS:
|
|||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `.symlinks/flutter/ios`)
|
||||
- Flutter (from `.symlinks/flutter/ios-profile`)
|
||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: ".symlinks/flutter/ios"
|
||||
:path: ".symlinks/flutter/ios-profile"
|
||||
shared_preferences:
|
||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||
url_launcher:
|
||||
|
|
|
@ -281,7 +281,7 @@
|
|||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
|
||||
"${PODS_ROOT}/../.symlinks/flutter/ios-profile/Flutter.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
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 {
|
||||
|
@ -24,7 +25,7 @@ List<Organisation> jsonToOrganisations(String json) {
|
|||
Map decoded = jsonDecode(json);
|
||||
// print(decoded);
|
||||
|
||||
List<dynamic> validated = decoded['unvalidated'];
|
||||
List<dynamic> validated = decoded['validated'];
|
||||
// Map organisation = validated[0];
|
||||
//
|
||||
// print("");
|
||||
|
@ -101,4 +102,8 @@ Future<List<Organisation>> findOrganisations(String search) async {
|
|||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class OrganizationController extends TextEditingController {
|
||||
Organisation organisation;
|
||||
}
|
|
@ -59,6 +59,14 @@ Future<LoginModel> submitReceiptAPI(
|
|||
if (response.statusCode == 200) {
|
||||
final responseJson = json.decode(response.body);
|
||||
|
||||
print(responseJson[0]);
|
||||
|
||||
showDialogSingleButton(
|
||||
context,
|
||||
responseJson[0] == "" ? responseJson[0] : "Upload Successful",
|
||||
"Transaction successfully submitted to server",
|
||||
"OK"
|
||||
);
|
||||
return LoginModel.fromJson(responseJson);
|
||||
} else {
|
||||
final responseJson = json.decode(response.body);
|
||||
|
@ -68,7 +76,7 @@ Future<LoginModel> submitReceiptAPI(
|
|||
context,
|
||||
"Unable to Submit Receipt",
|
||||
// "You may have supplied an invalid 'Email' / 'Password' combination. Please try again or email an administrator.",
|
||||
responseJson.toString(),
|
||||
"Message from server: " + responseJson[1],
|
||||
"OK");
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ void showDialogTwoButtons(
|
|||
new FlatButton(
|
||||
child: new Text(buttonLabel2),
|
||||
onPressed: () {
|
||||
action(context);
|
||||
Navigator.of(context).pop();
|
||||
action(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -5,7 +5,7 @@ class PopupListView {
|
|||
Future<dynamic> dialog(context, List<String> options, String title) {
|
||||
return showDialog<dynamic>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
barrierDismissible: true,
|
||||
|
||||
builder: (BuildContext context) {
|
||||
return SimpleDialog(
|
||||
|
|
|
@ -84,8 +84,14 @@ class LoginPageState extends State<LoginPage> {
|
|||
// child: ListView(
|
||||
// children: <Widget>[
|
||||
body: Container(
|
||||
decoration: BoxDecoration(color: Colors.white),
|
||||
child: Container(
|
||||
decoration: new BoxDecoration(
|
||||
gradient: new LinearGradient(
|
||||
colors: [Colors.white, Colors.blue[50]],
|
||||
stops: [0,1],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
),
|
||||
), child: Container(
|
||||
margin: EdgeInsets.fromLTRB(60,30,60,0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
|
@ -143,50 +149,41 @@ class LoginPageState extends State<LoginPage> {
|
|||
},
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: EdgeInsets.fromLTRB(0.0, 25.0, 0.0, 100.0),
|
||||
// child: Container(
|
||||
// height: 45.0,
|
||||
// child: RaisedButton(
|
||||
//
|
||||
// onPressed: () {
|
||||
// login( _emailController.text,
|
||||
// _passwordController.text);
|
||||
// // showDialog(
|
||||
// // barrierDismissible: false,
|
||||
// // );
|
||||
// // print("pressed");
|
||||
// },
|
||||
// child: Text("GO",
|
||||
// style:
|
||||
// TextStyle(color: Colors.white, fontSize: 20.0)),
|
||||
// color: Colors.blue,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
|
||||
|
||||
child : Material(
|
||||
child : InkWell(
|
||||
child: new Container(
|
||||
child : InkWell(
|
||||
onTap: () => login( _emailController.text, _passwordController.text),
|
||||
child: new Container(
|
||||
width: 100,
|
||||
height: 50,
|
||||
decoration: new BoxDecoration(
|
||||
// color: Colors.lightBlueAccent,
|
||||
borderRadius: new BorderRadius.circular(0.0),
|
||||
),
|
||||
child: new Center(
|
||||
child: new Text(
|
||||
'GO', style: new TextStyle(fontSize: 18, color: Colors.white),),
|
||||
),
|
||||
),
|
||||
splashColor: Colors.lightBlueAccent,
|
||||
splashColor: Colors.lightBlueAccent,
|
||||
),
|
||||
color: Colors.blueAccent,
|
||||
|
||||
decoration: new BoxDecoration(
|
||||
border: new Border.all(color : Colors.transparent, width: 2),
|
||||
borderRadius: BorderRadius.all(Radius.circular(2)),
|
||||
gradient: new LinearGradient(
|
||||
colors: [
|
||||
Colors.blue[300],
|
||||
Colors.blue[600],
|
||||
],
|
||||
stops: [0,1],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0, 10, 0, 50),
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:local_spend/common/apifunctions/request_login_api.dart';
|
||||
import 'package:local_spend/common/functions/show_dialog_single_button.dart';
|
||||
import 'package:local_spend/common/platform/platform_scaffold.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
const URL = "https://flutter.io/";
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return new LoginPageState();
|
||||
}
|
||||
}
|
||||
|
||||
class LoginPageState extends State<LoginPage> {
|
||||
final TextEditingController _emailController = TextEditingController(text: 'test@example.com'); // remove
|
||||
final TextEditingController _passwordController = TextEditingController(text: 'abc123'); // remove
|
||||
|
||||
FocusNode focusNode; // added so focus can move automatically
|
||||
|
||||
Future launchURL(String url) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url, forceSafariVC: true, forceWebView: true);
|
||||
} else {
|
||||
showDialogSingleButton(
|
||||
context,
|
||||
"Unable to reach your website.",
|
||||
"Currently unable to reach the website $URL. Please try again at a later time.",
|
||||
"OK");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_saveCurrentRoute("/LoginPage");
|
||||
|
||||
focusNode = FocusNode();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
focusNode.dispose(); //disposes focus node when form disposed
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_saveCurrentRoute(String lastRoute) async {
|
||||
SharedPreferences preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString('LastPageRoute', lastRoute);
|
||||
}
|
||||
|
||||
void login(String username, String password) {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
requestLoginAPI(context, username,
|
||||
password);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
'/HomePage', (Route<dynamic> route) => false);
|
||||
} else {
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
}
|
||||
},
|
||||
child: PlatformScaffold(
|
||||
// drawer: BasicDrawer(),
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"LOGIN",
|
||||
style: TextStyle(
|
||||
fontSize: 30.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
body: Container(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 0.0),
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 15.0),
|
||||
child: Text(
|
||||
"Local Loop",
|
||||
style: TextStyle(fontSize: 40.0, color: Colors.black),
|
||||
),
|
||||
)),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 78.0),
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text:
|
||||
'This is the logon page.',
|
||||
style: new TextStyle(
|
||||
fontSize: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' It is currently in development.',
|
||||
style: new TextStyle(
|
||||
fontSize: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"EMAIL",
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 0.0),
|
||||
child: TextField(
|
||||
controller: _emailController,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Use your login email",
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
color: Colors.grey[800],
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
FocusScope.of(context).requestFocus(focusNode);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 35.0, 0.0, 0.0),
|
||||
child: Text(
|
||||
"PASSWORD",
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 0.0),
|
||||
child: TextField(
|
||||
controller: _passwordController,
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Your password, keep it secret, keep it safe.',
|
||||
),
|
||||
obscureText: true,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
color: Colors.grey[800],
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
login( _emailController.text,
|
||||
_passwordController.text);
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 70.0, 0.0, 0.0),
|
||||
child: Container(
|
||||
height: 65.0,
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
login( _emailController.text,
|
||||
_passwordController.text);
|
||||
// showDialog(
|
||||
// barrierDismissible: false,
|
||||
// );
|
||||
// print("pressed");
|
||||
},
|
||||
child: Text("LOGIN",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ import 'package:local_spend/common/widgets/popupListView.dart';
|
|||
import 'package:local_spend/common/widgets/labeled_checkbox.dart';
|
||||
|
||||
const URL = "https://flutter.io/";
|
||||
const demonstration = true;
|
||||
const demonstration = false;
|
||||
|
||||
class ReceiptPage extends StatefulWidget {
|
||||
@override
|
||||
|
@ -32,6 +32,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
final TextEditingController _recurringController = TextEditingController(text: "None");
|
||||
final TextEditingController _typeController = TextEditingController();
|
||||
final TextEditingController _orgController = TextEditingController();
|
||||
final OrganizationController _organizationController = OrganizationController();
|
||||
|
||||
FocusNode focusNode; // added so focus can move automatically
|
||||
|
||||
|
@ -71,7 +72,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
|
||||
// this file is getting really messy sorry everyone
|
||||
|
||||
void submitReceipt(String amount, String time, String orgName) async {
|
||||
void submitReceipt(String amount, String time, Organisation organisation) async {
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
|
||||
if (demonstration)
|
||||
|
@ -89,6 +90,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
child: new Text("OK"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
//TODO: Reset form after dialog exit
|
||||
},
|
||||
),
|
||||
|
@ -96,7 +98,6 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
);
|
||||
},
|
||||
).then((_) {
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
@ -105,16 +106,21 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
// setting up 'receipt'
|
||||
receipt.amount = amount;
|
||||
receipt.time = formatDate(time);
|
||||
receipt.organisationName = orgName;
|
||||
debugPrint(organisation.name + ", " + organisation.streetName + ", " + organisation.town + ", " + organisation.postcode);
|
||||
receipt.organisationName = organisation.name;
|
||||
receipt.street = organisation.streetName;
|
||||
receipt.town = organisation.town;
|
||||
receipt.postcode = organisation.postcode;
|
||||
|
||||
// receipt.essential = convertBoolToString(toConvert)
|
||||
|
||||
//TODO: initialise receipt with correct values from form
|
||||
// TODO: Categories
|
||||
|
||||
// receipt.category = category;
|
||||
// receipt.etc = etc;
|
||||
|
||||
submitReceiptAPI(context, receipt);
|
||||
Navigator.of(context).pushReplacementNamed('/HomePage');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +172,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
// know that before writing this and it's done now so I'm keeping it.
|
||||
}
|
||||
|
||||
String listOrganisations(List<Organisation> organisations, context) {
|
||||
Organisation listOrganisations(List<Organisation> organisations, context) {
|
||||
if (organisations.length == 0) {
|
||||
showDialogSingleButton(
|
||||
context,
|
||||
|
@ -189,7 +195,13 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
|
||||
// dialog.then((value) => debugPrint(value));
|
||||
|
||||
dialog.then((value) => _orgController.text = value);
|
||||
|
||||
dialog.then((value) {
|
||||
_orgController.text = value;
|
||||
_organizationController.organisation = organisations.where((thisOrg) => thisOrg.name == value).elementAt(0);
|
||||
// this may not work when two organisations have the same name,
|
||||
// then again the popupListView can't display two of the same names properly either
|
||||
});
|
||||
//can't return value as it is <future> and thus would block
|
||||
}
|
||||
|
||||
|
@ -305,15 +317,14 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
onPressed: () {
|
||||
if (_orgController.text != "") {
|
||||
var organisations = findOrganisations(
|
||||
_orgController.text);
|
||||
_orgController.text); // returns Future<List<Organisation>>
|
||||
|
||||
var choice = organisations.then((data) =>
|
||||
listOrganisations(data, context));
|
||||
|
||||
choice.then((value) => _orgController.text = value);
|
||||
setState(() {
|
||||
choice.then((value) => _orgController.text = value.name);
|
||||
choice.then((value) => _organizationController.organisation = value);
|
||||
|
||||
});
|
||||
} else {
|
||||
// no data entered
|
||||
|
||||
|
@ -354,7 +365,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
),
|
||||
onSubmitted: (_) {
|
||||
submitReceipt(_amountController.text,
|
||||
_timeController.text, _orgController.text);
|
||||
_timeController.text, _organizationController.organisation);
|
||||
// TODO: make sure organisation is valid
|
||||
// TODO: Add 'find organisation' button which displays a dialog to, well, find the organisation's address or manual entry
|
||||
},
|
||||
|
@ -452,7 +463,7 @@ class ReceiptPageState extends State<ReceiptPage> {
|
|||
height: 65.0,
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
submitReceipt(_amountController.text, _timeController.text, _orgController.text);
|
||||
submitReceipt(_amountController.text, _timeController.text, _organizationController.organisation);
|
||||
},
|
||||
child: Text("GO",
|
||||
style:
|
||||
|
|
|
@ -156,21 +156,22 @@ class SettingsPageState extends State<SettingsPage> {
|
|||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
|
||||
child: Container(
|
||||
height: 65.0,
|
||||
child: RaisedButton(
|
||||
onPressed: () {
|
||||
feedback(context);
|
||||
},
|
||||
child: Text("FEEDBACK",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
|
||||
// child: Container(
|
||||
// height: 65.0,
|
||||
// child: RaisedButton(
|
||||
// onPressed: () {
|
||||
// feedback(context);
|
||||
// },
|
||||
// child: Text("FEEDBACK",
|
||||
// style:
|
||||
// TextStyle(color: Colors.white, fontSize: 22.0)),
|
||||
// color: Colors.green,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
Reference in a new issue