diff --git a/To Do List.rtf b/To Do List.rtf index a7ad29b..c11d494 100644 --- a/To Do List.rtf +++ b/To Do List.rtf @@ -53,7 +53,6 @@ \ls6\ilvl1\cf0 \ulnone {\listtext \uc0\u8259 } \f1\b0 Categories\ {\listtext \uc0\u8259 }Recurring\ -{\listtext \uc0\u8259 }Sort out \'91essential purchase\'92 checkbox\'92s Y position\ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 \cf0 \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 diff --git a/lib/common/apifunctions/submit_receipt_api.dart b/lib/common/apifunctions/submit_receipt_api.dart index c25c5a6..b317542 100644 --- a/lib/common/apifunctions/submit_receipt_api.dart +++ b/lib/common/apifunctions/submit_receipt_api.dart @@ -31,6 +31,7 @@ Future submitReceiptAPI( SharedPreferences preferences = await SharedPreferences.getInstance(); Map body = { + 'transaction_type' : "3", 'transaction_value': receipt.amount, 'purchase_time': receipt.time, 'category': receipt.category, @@ -38,13 +39,15 @@ Future submitReceiptAPI( 'organisation_name': receipt.organisationName, 'recurring': receipt.recurring, 'street_name': receipt.street, - 'town': receipt.town, 'postcode': receipt.postcode, + 'town': receipt.town, + 'session_key': preferences.get('LastToken'), }; debugPrint('$body'); + debugPrint(json.encode(body)); final response = await http.post( url, @@ -64,7 +67,8 @@ Future submitReceiptAPI( showDialogSingleButton( context, "Unable to Submit Receipt", - "You may have supplied an invalid 'Email' / 'Password' combination. Please try again or email an administrator.", +// "You may have supplied an invalid 'Email' / 'Password' combination. Please try again or email an administrator.", + responseJson.toString(), "OK"); return null; } diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 07d925a..fb2dc19 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -21,7 +21,7 @@ class LoginPage extends StatefulWidget { class LoginPageState extends State { final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); - String _welcomeString = ""; + FocusNode focusNode; // added so focus can move automatically Future launchURL(String url) async { diff --git a/lib/pages/receipt_page.dart b/lib/pages/receipt_page.dart index 497ef99..5ca39da 100644 --- a/lib/pages/receipt_page.dart +++ b/lib/pages/receipt_page.dart @@ -12,7 +12,7 @@ import 'package:intl/intl.dart'; import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; const URL = "https://flutter.io/"; -const demonstration = true; +const demonstration = false; class ReceiptPage extends StatefulWidget { @override @@ -29,6 +29,8 @@ class ReceiptPageState extends State { final TextEditingController _typeController = TextEditingController(); final TextEditingController _orgController = TextEditingController(); + FocusNode focusNode; // added so focus can move automatically + DateTime date; Future launchURL(String url) async { @@ -47,6 +49,15 @@ class ReceiptPageState extends State { void initState() { super.initState(); _saveCurrentRoute("/ReceiptPageState"); + + focusNode = FocusNode(); + } + + @override + void dispose() { + super.dispose(); + + focusNode.dispose(); //disposes focus node when form disposed } _saveCurrentRoute(String lastRoute) async { @@ -54,7 +65,7 @@ class ReceiptPageState extends State { await preferences.setString('LastPageRoute', lastRoute); } - void submitReceipt(String amount, String time) async { + void submitReceipt(String amount, String time, String orgName) async { SystemChannels.textInput.invokeMethod('TextInput.hide'); if (demonstration) @@ -86,7 +97,10 @@ class ReceiptPageState extends State { // setting up 'receipt' receipt.amount = amount; - receipt.time = time; + receipt.time = formatDate(time); + receipt.organisationName = orgName; + +// receipt.essential = convertBoolToString(toConvert) //TODO: initialise receipt with correct values from form @@ -97,6 +111,40 @@ class ReceiptPageState extends State { } } + String convertBoolToString(bool toConvert) { + if (toConvert) + { + return "true"; + } + + return "false"; + } + + String formatDate(String date) { +// return ""; + // should be in format: + // yyyy-MM-ddThh:mm:00.000+01:00 + // eg 2019-07-05T10:24:00.000+01.00 (real life example, works) + + // current format = "dd/MM/yyyy 'at' hh:mm" + + var components = new List(5); + + components[0] = (date.substring(0,2)); // dd + components[1] = (date.substring(3,5)); // MM + components[2] = (date.substring(6,10)); // yyyy + components[3] = (date.substring(14,16)); // hh + components[4] = (date.substring(17,19)); // mm + + //print(components); + + return (components[2] + "-" + components[1] + "-" + components[0] + + "T" + components[3] + ":" + components[4] + ":00.000+01:00"); + + // Yes, there is probably a function to convert dates, but I didn't + // know that before writing this and it's done now so I'm keeping it. + } + @override Widget build(BuildContext context) { var drawer = Drawer(); @@ -127,26 +175,29 @@ class ReceiptPageState extends State { padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 0.0), child: ListView( children: [ - Container( - alignment: Alignment.topCenter, - child: Padding( - padding: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 15.0), - child: Text( - "Required Fields in bold", - style: TextStyle(fontSize: 20.0, color: Colors.black), - ), - )), - Text( - "Time of Transaction", - style: TextStyle( - fontSize: 18.0, - color: Colors.black, - fontWeight: FontWeight.bold, +// Container( +// alignment: Alignment.topCenter, +// child: Padding( +// padding: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 15.0), +// child: Text( +// "Required fields are in bold", +// style: TextStyle(fontSize: 20.0, color: Colors.black), +// ), +// )), + Padding( + padding: EdgeInsets.fromLTRB(0.0,25,0.0,0.0), + child : Text( + "Time of Transaction", + style: TextStyle( + fontSize: 18.0, + color: Colors.black, + fontWeight: FontWeight.bold, + ), ), ), DateTimePickerFormField( inputType: InputType.both, - format: DateFormat("EEEE, MMMM d, yyyy 'at' h:mma"), + format: DateFormat("dd/MM/yyyy 'at' hh:mm"), editable: true, controller: _timeController, decoration: InputDecoration( @@ -154,7 +205,7 @@ class ReceiptPageState extends State { onChanged: (dt) => setState(() => date = dt), ), Padding( - padding: EdgeInsets.fromLTRB(0.0, 35.0, 0.0, 0.0), + padding: EdgeInsets.fromLTRB(0.0,25,0.0,0.0), child: Text( "Amount", style: TextStyle( @@ -180,13 +231,83 @@ class ReceiptPageState extends State { fontWeight: FontWeight.bold, ), onSubmitted: (_) { - submitReceipt(_amountController.text, _timeController.text); + FocusScope.of(context).requestFocus(focusNode); +// submitReceipt(_amountController.text, _timeController.text); }, ), ), Padding( - padding: EdgeInsets.fromLTRB(0.0, 35.0, 0.0, 0.0), + padding: EdgeInsets.fromLTRB(0.0,25,0.0,0.0), + + child : Container ( + height: 22, // this should be the same height as text + + child : ListView( + scrollDirection: Axis.horizontal, + children: [ + + Container( + child: Text( + "Organization Name", + style: TextStyle( + fontSize: 18.0, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + + Container( + child : Padding( + padding: EdgeInsets.fromLTRB(5,0,0,4), + child: FlatButton( + onPressed: () { + debugPrint("TODO: 'find organisation' dialog"); + // Writing this before I forget tomorrow morning: + // Steps to fetch list of organisations with similar name: + // 1) record network activity (requests) of FoodLoop-Web webapp on Firefox + // 2) look at JSON files returned by server when 'organisation name' field's text updates/changes + // 3) look at requests sent to server when web textfield updates and send those from app + // 4) I'm tired + }, + child: Text("Find", + style: + TextStyle(color: Colors.blue, fontSize: 18.0)), + ), + ), + ) + + ], + ), + ), + ), + + Padding( + padding: EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 0.0), + child: TextField( + controller: _orgController, + focusNode: focusNode, + decoration: InputDecoration( + hintText: 'Eg. Pear Trading', + ), +// obscureText: true, + autocorrect: true, + style: TextStyle( + fontSize: 18.0, + color: Colors.grey[800], + fontWeight: FontWeight.bold, + ), + onSubmitted: (_) { + submitReceipt(_amountController.text, + _timeController.text, _orgController.text); + // TODO: Add 'find organisation' button which displays a dialog to, well, find the organisation's address or manual entry + }, + ), + ), + + Padding( + padding: EdgeInsets.fromLTRB(0.0,25,0.0,0.0), child : Container ( height: 18, @@ -209,16 +330,12 @@ class ReceiptPageState extends State { child : Padding( padding: EdgeInsets.fromLTRB(20.0, 0.0, 0, 0), - child: Checkbox(value: _essentialController.text.toLowerCase() == 'true', onChanged: (bool newValue) { + child: Checkbox(value: + _essentialController.text.toLowerCase() == 'true', + onChanged: (bool newValue) { setState(() { - var newValueString = "false"; - - if (newValue) - { - newValueString = "true"; - } - - _essentialController.text = newValueString; + _essentialController.text = + convertBoolToString(newValue); }); }), ), @@ -236,7 +353,7 @@ class ReceiptPageState extends State { height: 65.0, child: RaisedButton( onPressed: () { - submitReceipt(_amountController.text, _timeController.text); + submitReceipt(_amountController.text, _timeController.text, _orgController.text); }, child: Text("SUBMIT", style: