This repository has been archived on 2023-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
LocalSpend-Tracker/lib/pages/receipt_page_2.dart

521 lines
20 KiB
Dart
Raw Normal View History

2019-08-05 08:33:39 +00:00
import 'package:flutter/material.dart';
import 'package:local_spend/common/platform/platform_scaffold.dart';
import 'package:intl/intl.dart';
2019-08-12 11:09:04 +00:00
import 'dart:core';
import 'package:flutter/cupertino.dart';
2019-08-20 12:54:45 +00:00
import 'package:local_spend/common/widgets/animatedGradientButton.dart';
import 'package:local_spend/common/apifunctions/find_organisations.dart';
import 'package:local_spend/common/widgets/organisations_dialog.dart';
2019-08-12 10:37:59 +00:00
import 'package:local_spend/common/apifunctions/submit_receipt_api.dart';
2019-08-12 11:09:04 +00:00
import 'package:local_spend/common/apifunctions/categories.dart';
2019-08-05 08:33:39 +00:00
2019-08-05 11:24:40 +00:00
class Transaction {
DateTime date;
TextEditingController amount;
Organisation organisation;
2019-08-12 10:19:37 +00:00
String recurring;
bool isEssential;
String category;
2019-08-05 11:24:40 +00:00
Transaction(
this.date,
this.amount,
this.organisation,
2019-08-12 10:19:37 +00:00
this.recurring,
this.isEssential,
this.category,
2019-08-05 11:24:40 +00:00
);
}
2019-08-05 08:33:39 +00:00
class ReceiptPage2 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new ReceiptPage2State();
}
}
class ReceiptPage2State extends State<ReceiptPage2> {
Transaction transaction = new Transaction(
DateTime.now(),
new TextEditingController(),
new Organisation(null, null, null, null, null),
2019-08-12 10:19:37 +00:00
"None",
false,
"Uncategorised",
);
2019-08-12 11:29:49 +00:00
_invalidDialog(context) {
return AlertDialog(
title: new Text("Invalid data"),
content: new Text(
"We couldn't process your request because some of the data entered is invalid."),
actions: <Widget>[
new FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
2019-08-12 11:09:04 +00:00
Future<List<String>> getCats() async {
return await getCategories();
}
2019-08-12 10:19:37 +00:00
2019-08-12 10:37:59 +00:00
_submitReceipt(Transaction transaction) {
DateTime dt = new DateTime.now();
// sample transaction:
// {
// "transaction_type":1,
// "transaction_value":33,
// "purchase_time":"2019-08-12T11:06:00.000+01:00",
// "organisation_id":59661,
// "essential":false,
2019-08-20 12:54:45 +00:00
// "session_key":"C438440A-B775-11E9-8EE8-147589E69626"
2019-08-12 10:37:59 +00:00
// }
Receipt receipt = new Receipt();
receipt.organisationName = transaction.organisation.name;
receipt.street = transaction.organisation.streetName;
receipt.postcode = transaction.organisation.postcode;
receipt.town = transaction.organisation.town;
2019-08-12 11:29:49 +00:00
2019-08-12 10:37:59 +00:00
receipt.recurring = transaction.recurring;
2019-08-12 10:54:13 +00:00
if (transaction.recurring == "None") {
receipt.recurring = "";
}
2019-08-12 10:37:59 +00:00
receipt.category = transaction.category;
2019-08-12 11:29:49 +00:00
if (transaction.category == "Uncategorised") {
receipt.category = "";
}
2019-08-12 10:37:59 +00:00
receipt.amount = transaction.amount.text.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);
}
2019-08-12 10:19:37 +00:00
List<String> _sampleRecurringOptions = new List<String>(7);
2019-08-12 15:28:46 +00:00
List<String> _categories = new List<String>();
2019-08-12 10:19:37 +00:00
2019-08-05 08:33:39 +00:00
@override
Widget build(BuildContext context) {
2019-08-12 11:09:04 +00:00
2019-08-12 15:28:46 +00:00
if (_categories.length == 0) {
Future<List<String>> _futureCats = getCats();
_categories.add("Fetching categories...");
_futureCats.then((value) {
_categories = null;
_categories = value;
setState(() {});
});
}
2019-08-12 11:09:04 +00:00
2019-08-12 10:19:37 +00:00
_sampleRecurringOptions[0] = "None";
_sampleRecurringOptions[1] = "Daily";
_sampleRecurringOptions[2] = "Weekly";
_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
2019-08-05 08:33:39 +00:00
return PlatformScaffold(
appBar: AppBar(
2019-08-08 14:25:43 +00:00
backgroundColor: Colors.blue[400],
title: Text(
"Submit Receipt",
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
2019-08-05 08:33:39 +00:00
),
2019-08-08 14:25:43 +00:00
centerTitle: true,
iconTheme: IconThemeData(color: Colors.black),
2019-08-05 08:33:39 +00:00
),
body: ListView(
children: <Widget>[
// 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: const EdgeInsets.fromLTRB(15, 17, 0, 0),
child : Text(
"Receipt Details",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 26,
color: Colors.grey[700],
fontWeight: FontWeight.bold,
),
),
), // "Receipt Details" title
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Date and time of transaction",
child: Row(
children: <Widget> [
Container(
child : Text(
"Date/Time",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-19 11:36:12 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
2019-08-05 11:24:40 +00:00
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
),
2019-08-19 11:36:12 +00:00
Container(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: RaisedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height / 3,
child: CupertinoDatePicker(
initialDateTime: transaction.date.isAfter(DateTime.now())
? DateTime.now()
: transaction.date,
onDateTimeChanged: (DateTime newDate) {
setState(() => {
newDate.isAfter(DateTime.now())
? transaction.date = DateTime.now()
: transaction.date = newDate,
});
},
use24hFormat: true,
maximumDate: DateTime.now(),
),
);
});
},
child: Text(
transaction.date == null
? 'None set'
: transaction.date.year == DateTime.now().year
? '${new DateFormat.MMMd().format(transaction.date)}' + ", " + '${new DateFormat.Hm().format(transaction.date)}'
: '${new DateFormat.MMMd().format(transaction.date)}' + " " + transaction.date.year.toString() + ", " + '${new DateFormat.Hm().format(transaction.date)}',
style:
2019-08-20 12:54:45 +00:00
TextStyle(color: Colors.white, fontSize: 22.0),
2019-08-19 11:36:12 +00:00
),
color: Colors.blue,
),
),
2019-08-19 11:36:12 +00:00
],
),
),
), // Date/Time picker
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Transaction payee",
child: Row(
children: <Widget> [
Container(
child : Text(
"Payee",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-19 11:36:12 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
2019-08-05 11:24:40 +00:00
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
),
2019-08-19 11:36:12 +00:00
Container(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: RaisedButton(
onPressed: () {
var organisations = new FindOrganisations();
var orgDialog = organisations.dialog(context);
orgDialog.then((organisation) {
try {
organisation.name.length;
transaction.organisation = organisation;
// debugPrint(organisation.name);
setState(() {});
} catch(_) {
debugPrint("No organisation chosen.");
}
});
},
child: Text(
transaction.organisation.name == null
? 'Find'
: transaction.organisation.name.length > 14
? transaction.organisation.name.substring(0,12) + "..."
: transaction.organisation.name,
style:
2019-08-20 12:54:45 +00:00
TextStyle(color: Colors.white, fontSize: 22.0),
2019-08-19 11:36:12 +00:00
),
color: Colors.blue,
),
),
2019-08-19 11:36:12 +00:00
],
),
),
), // Organisation picker
2019-08-12 10:19:37 +00:00
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Transaction recrudescence",
child: Row(
children: <Widget> [
Container(
child : Text(
"Recurring",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-19 11:36:12 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
2019-08-12 10:19:37 +00:00
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
2019-08-12 10:19:37 +00:00
),
2019-08-19 11:36:12 +00:00
Container(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: RaisedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height / 3,
child: CupertinoPicker(
backgroundColor: Colors.white,
children: _sampleRecurringOptions.map((thisOption) => Text(thisOption)).toList(),
onSelectedItemChanged: ((newValue) {
transaction.recurring = _sampleRecurringOptions[newValue];
setState(() {});
}),
2019-08-20 12:54:45 +00:00
itemExtent: 40,
2019-08-19 11:36:12 +00:00
),
);
});
},
child: Text(
transaction.recurring == null
? 'None'
: transaction.recurring,
style:
2019-08-20 12:54:45 +00:00
TextStyle(color: Colors.white, fontSize: 22.0),
2019-08-19 11:36:12 +00:00
),
color: Colors.blue,
2019-08-12 10:19:37 +00:00
),
),
2019-08-19 11:36:12 +00:00
],
),
2019-08-12 10:19:37 +00:00
),
), // Recurring picker
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-12 10:19:37 +00:00
child: Row(
children: <Widget> [
Container(
child : Text(
"Category",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-12 10:19:37 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
2019-08-12 10:19:37 +00:00
),
Container(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Category of transaction",
child: RaisedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height / 3,
child: CupertinoPicker(
backgroundColor: Colors.white,
children: _categories.map((thisOption) => Text(thisOption)).toList(),
onSelectedItemChanged: ((newValue) {
transaction.category = _categories[newValue];
setState(() {});
}),
2019-08-20 12:54:45 +00:00
itemExtent: 40,
2019-08-19 11:36:12 +00:00
),
);
});
},
child: Text(
transaction.category == null
? 'None'
: transaction.category,
style:
2019-08-20 12:54:45 +00:00
TextStyle(color: Colors.white, fontSize: 22.0),
2019-08-19 11:36:12 +00:00
),
color: Colors.blue,
2019-08-12 10:19:37 +00:00
),
),
),
],
),
), // Category picker
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Essential or not",
child: Row(
children: <Widget> [
Container(
child : Text(
"Essential",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-19 11:36:12 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
2019-08-12 10:19:37 +00:00
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
2019-08-12 10:19:37 +00:00
),
2019-08-19 11:36:12 +00:00
Container(
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: Checkbox(
value: transaction.isEssential,
onChanged: ((value) {
setState(() => transaction.isEssential = value);
}),
),
2019-08-12 10:19:37 +00:00
),
2019-08-19 11:36:12 +00:00
],
),
2019-08-12 10:19:37 +00:00
),
), // Essential
Container(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Transaction amount",
child: Row(
children: <Widget> [
Container(
child : Text(
"Amount",
style: TextStyle(
2019-08-20 12:54:45 +00:00
fontSize: 22,
2019-08-19 11:36:12 +00:00
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
2019-08-20 12:54:45 +00:00
width: MediaQuery.of(context).size.width * 0.3,
),
2019-08-19 11:36:12 +00:00
Container(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
2019-08-20 12:54:45 +00:00
height: 40.0,
width: MediaQuery.of(context).size.width * 0.6,
2019-08-19 11:36:12 +00:00
child: TextField(
controller: transaction.amount,
decoration: InputDecoration(
hintText: "0.00"
),
keyboardType: TextInputType.numberWithOptions(decimal: true, signed: true),
),
),
2019-08-19 11:36:12 +00:00
],
),
),
2019-08-05 11:24:40 +00:00
), // Amount picker
2019-08-12 10:37:59 +00:00
Padding(
2019-08-20 13:04:31 +00:00
padding: EdgeInsets.fromLTRB(MediaQuery.of(context).size.width * 0.05,15,MediaQuery.of(context).size.width * 0.05,0.0),
2019-08-19 11:36:12 +00:00
child: Tooltip(
message: "Submit receipt",
child: Container(
2019-08-20 12:54:45 +00:00
height: 75.0,
2019-08-20 12:58:53 +00:00
child: ClipRRect(
borderRadius: BorderRadius.circular(2),
child: Stack(
children: [
AnimatedBackground(),
Material(
type: MaterialType.transparency,
child: InkWell(
child: Center(
child : Text("GO",
style:
TextStyle(color: Colors.white, fontSize: 30.0),
),
2019-08-20 12:54:45 +00:00
),
2019-08-20 12:58:53 +00:00
onTap: () {
try {
if (transaction.amount.text == "" || transaction.organisation.name == null) {
2019-08-20 12:54:45 +00:00
showDialog(
2019-08-20 12:58:53 +00:00
context: context,
builder: (BuildContext context) {
return _invalidDialog(context);
}
2019-08-20 12:54:45 +00:00
);
2019-08-20 12:58:53 +00:00
} else {
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);
}
);
}
2019-08-20 12:54:45 +00:00
}
2019-08-19 11:36:12 +00:00
}
2019-08-20 12:58:53 +00:00
catch (_) {
showDialog(
context: context,
builder: (BuildContext context) {
return _invalidDialog(context);
}
);
}
},
),
2019-08-20 12:54:45 +00:00
),
2019-08-20 12:58:53 +00:00
],
),
2019-08-19 11:36:12 +00:00
),
2019-08-12 10:37:59 +00:00
),
),
),
],
),
2019-08-05 08:33:39 +00:00
);
}
}