update invoice

This commit is contained in:
PhyoThandar
2020-10-16 21:38:39 +06:30
parent ad7d0039fc
commit 274c999959
18 changed files with 658 additions and 398 deletions

View File

@@ -209,6 +209,13 @@
"pm.update":"Update Payment Method", "pm.update":"Update Payment Method",
"pm.btn":"Payment methods", "pm.btn":"Payment methods",
"pm.name":"Name", "pm.name":"Name",
"pm.status":"Status",
"pm.pay":"Pay",
"pm.btn_confirm":"Confirm",
"pm.btn_cancel":"Cancel",
"pm.gallery":"Gallery",
"pm.camera":"Camera",
"pm.remove_photo":"Remove",
"pm.account.name":"Account name", "pm.account.name":"Account name",
"pm.account.no":"Account number", "pm.account.no":"Account number",
"pm.phone":"Phone number", "pm.phone":"Phone number",

View File

@@ -209,6 +209,13 @@
"pm.update":"ငွေပေးချေစနစ် ပြင်ဆင်ခြင်း", "pm.update":"ငွေပေးချေစနစ် ပြင်ဆင်ခြင်း",
"pm.btn":"ငွေပေးချေစနစ်များ", "pm.btn":"ငွေပေးချေစနစ်များ",
"pm.name":"အမည်", "pm.name":"အမည်",
"pm.status":"အခြေအနေ",
"pm.pay":"ပေးဆောင်ရန်",
"pm.btn_confirm":"အတည်ပြုရန်",
"pm.btn_cancel":"ပယ်ဖျက်ရန်",
"pm.gallery":"ပြခန်း",
"pm.camera":"ကင်မရာ",
"pm.remove_photo":"ဖယ်ရှားမည်",
"pm.account.name":"အကောင့် အမည်", "pm.account.name":"အကောင့် အမည်",
"pm.account.no":"အကောင့် နံပါတ်", "pm.account.no":"အကောင့် နံပါတ်",
"pm.phone":"ဖုန်း နံပါတ်", "pm.phone":"ဖုန်း နံပါတ်",

View File

@@ -6,6 +6,7 @@ const markets_collection = "markets";
const packages_collection = "packages"; const packages_collection = "packages";
const messages_collection = "messages"; const messages_collection = "messages";
const fcs_shipment_collection = "fcs_shipments"; const fcs_shipment_collection = "fcs_shipments";
const invoices_collection = "invoices";
const delivery_address_collection = "delivery_addresses"; const delivery_address_collection = "delivery_addresses";
const cargo_types_collection = "cargo_types"; const cargo_types_collection = "cargo_types";
const custom_duties_collection = "custom_duties"; const custom_duties_collection = "custom_duties";

View File

@@ -1,6 +1,11 @@
class Receipt { import 'package:flutter_local_notifications/flutter_local_notifications.dart';
int amount;
DateTime date;
Receipt({this.amount, this.date}); class Receipt {
String id;
int amount;
String date;
String status;
String fileUrl;
Receipt({this.id, this.amount, this.date, this.status, this.fileUrl});
} }

View File

@@ -16,13 +16,12 @@ import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'invoice_editor.dart';
import 'invoice_list_row.dart'; import 'invoice_list_row.dart';
class InvoiceList extends StatefulWidget { class InvoiceList extends StatefulWidget {
final bool onlyFcs; final bool forCustomer;
const InvoiceList({Key key, this.onlyFcs}) : super(key: key); const InvoiceList({Key key, this.forCustomer}) : super(key: key);
@override @override
_InvoiceListState createState() => _InvoiceListState(); _InvoiceListState createState() => _InvoiceListState();
} }
@@ -35,14 +34,13 @@ class _InvoiceListState extends State<InvoiceList> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Provider.of<InvoiceModel>(context, listen: false).initPaidInvoice(true); _controller.addListener(() async {
// _controller.addListener(() { if (_controller.position.pixels == _controller.position.maxScrollExtent) {
// if (_showPaid && Provider.of<InvoiceModel>(context, listen: false).loadMore(isCustomer: widget.forCustomer);
// _controller.position.pixels == _controller.position.maxScrollExtent) { }
// Provider.of<InvoiceModel>(context, listen: false) });
// .loadMorePaidInvoices();
// } Provider.of<InvoiceModel>(context, listen: false).initData(false);
// });
} }
@override @override
@@ -54,15 +52,17 @@ class _InvoiceListState extends State<InvoiceList> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var owner = true; var owner = true;
var invoiceModel = Provider.of<InvoiceModel>(context); var invoiceModel = Provider.of<InvoiceModel>(context);
bool onlyFcs = widget.onlyFcs;
var invoices =
_showPaid ? invoiceModel.paidInvoices : invoiceModel.invoices;
final popupMenu = LocalPopupMenuButton( final popupMenu = LocalPopupMenuButton(
popmenus: [ popmenus: [
LocalPopupMenu( LocalPopupMenu(
id: 1, textKey: "invoice.popupmenu.pending", selected: true), id: 1,
LocalPopupMenu(id: 2, textKey: "invoice.popupmenu.paid") textKey: "invoice.popupmenu.pending",
selected: invoiceModel.selectedIndex == 1),
LocalPopupMenu(
id: 2,
textKey: "invoice.popupmenu.paid",
selected: invoiceModel.selectedIndex == 2)
], ],
popupMenuCallback: (p) => this.setState(() { popupMenuCallback: (p) => this.setState(() {
_showPaid = p.id == 2; _showPaid = p.id == 2;
@@ -104,18 +104,38 @@ class _InvoiceListState extends State<InvoiceList> {
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new ListView.separated( child: RefreshIndicator(
child: ListView.separated(
physics: AlwaysScrollableScrollPhysics(),
controller: _controller,
separatorBuilder: (context, index) => Divider( separatorBuilder: (context, index) => Divider(
color: Colors.black, color: Colors.black,
), ),
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
padding: EdgeInsets.only(top: 15), padding: EdgeInsets.only(top: 15),
shrinkWrap: true, shrinkWrap: true,
itemCount: invoices.length, itemCount: invoiceModel.invoices.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return InvoiceListRow(invoice: invoices[index]); return InvoiceListRow(
key: ValueKey(invoiceModel.invoices[index].id),
invoice: invoiceModel.invoices[index]);
}), }),
onRefresh: () => invoiceModel.refresh(),
), ),
),
invoiceModel.isLoading
? Container(
padding: EdgeInsets.all(8),
color: primaryColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Loading...",
style: TextStyle(color: Colors.white)),
],
),
)
: Container(),
], ],
)), )),
), ),

View File

@@ -35,8 +35,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'box_addition.dart';
class InvoiceEditor extends StatefulWidget { class InvoiceEditor extends StatefulWidget {
final Invoice invoice; final Invoice invoice;
final User customer; final User customer;
@@ -68,8 +66,8 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
List<Box> _boxes = []; List<Box> _boxes = [];
bool isSwitched = false; bool isSwitched = false;
int deliveryfee = 0; int deliveryfee = 0;
double customFee = 10; double customFee = 10.0;
int handlingFee = 0; double handlingFee = 10.0; // it will get from shipment
double total = 0; double total = 0;
Discount _discount; Discount _discount;
bool isNew = false; bool isNew = false;
@@ -124,7 +122,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
_balanceController.text = '0'; _balanceController.text = '0';
} }
if (widget.customer != null) { if (widget.customer != null && widget.invoice == null) {
user = widget.customer; user = widget.customer;
setState(() { setState(() {
isNew = true; isNew = true;
@@ -193,29 +191,17 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
final nameBox = DisplayText( final nameBox = DisplayText(
iconData: Feather.user, iconData: Feather.user,
labelTextKey: 'invoice.customer_name', labelTextKey: 'invoice.customer_name',
text: user != null ? user.name : ''); text: user != null ? user.name : 'Ko Nyi');
final statusBox = DisplayText( final statusBox = DisplayText(
text: _statusController.text, text: _statusController.text,
iconData: Icons.av_timer, iconData: Icons.av_timer,
labelTextKey: 'invoice.status'); labelTextKey: 'invoice.status');
final fcsIDBox = Row( final fcsIDBox = DisplayText(
children: <Widget>[ text: user != null ? user.fcsID : "FCS-KRUTUG",
Expanded(
child: DisplayText(
text: user != null ? user.fcsID : "",
labelTextKey: "box.fcs.id", labelTextKey: "box.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
)),
IconButton(
icon: Icon(Icons.search, color: primaryColor),
onPressed: () => searchUser(context, callbackUserSelect: (u) {
setState(() {
this.user = u;
});
})),
],
); );
return LocalProgress( return LocalProgress(
@@ -249,7 +235,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
text: _invoiceNumberController.text), text: _invoiceNumberController.text),
fcsIDBox, fcsIDBox,
nameBox, nameBox,
isNew ? statusBox : Container(), isNew ? Container() : statusBox,
SizedBox(height: 20), SizedBox(height: 20),
LocalTitle(textKey: "invoice.box_info"), LocalTitle(textKey: "invoice.box_info"),
Center(child: Column(children: getCartonRows(context))), Center(child: Column(children: getCartonRows(context))),
@@ -261,7 +247,8 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
onPressed: () async { onPressed: () async {
CustomDuty custom = await Navigator.of(context).push( CustomDuty custom = await Navigator.of(context).push(
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => CustomList())); builder: (context) =>
CustomList(selected: true)));
setState(() { setState(() {
if (custom != null) customs.add(custom); if (custom != null) customs.add(custom);
}); });
@@ -300,7 +287,9 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
), ),
), ),
SizedBox(height: 20), SizedBox(height: 20),
LocalTitle( isNew
? Container()
: LocalTitle(
textKey: "invoice.payment_attachment", textKey: "invoice.payment_attachment",
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.add_circle, color: primaryColor), icon: Icon(Icons.add_circle, color: primaryColor),
@@ -341,13 +330,21 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
child: Row( child: Row(
children: [ children: [
Container( Container(
width: 33, width: 35,
child: Checkbox( child: Checkbox(
value: true, onChanged: (v) {}, activeColor: primaryColor), value: true, onChanged: (v) {}, activeColor: primaryColor),
), ),
Expanded(flex: 1, child: Text(box.packageNumber)),
Expanded( Expanded(
flex: 1, flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(box.packageNumber),
Text(box.shipmentNumber),
],
)),
Expanded(
flex: 2,
child: Text( child: Text(
box.length == null box.length == null
? "" ? ""
@@ -387,7 +384,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
), ),
)), )),
Expanded( Expanded(
flex: 1, flex: 2,
child: Center( child: Center(
child: Text('L x W x H', child: Text('L x W x H',
style: TextStyle(color: Colors.grey)))), style: TextStyle(color: Colors.grey)))),
@@ -674,11 +671,9 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
), ),
), ),
), ),
new IconButton( SizedBox(width: 50),
icon: Icon(Icons.edit, color: primaryColor),
onPressed: () async {}),
Expanded( Expanded(
child: Text('\$ $handlingFee', child: Text('\$ ${handlingFee.toString()}',
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,

View File

@@ -36,11 +36,10 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'box_addition.dart';
class InvoiceInfoPage extends StatefulWidget { class InvoiceInfoPage extends StatefulWidget {
final Invoice invoice; final Invoice invoice;
InvoiceInfoPage({this.invoice}); final User customer;
InvoiceInfoPage({this.invoice, this.customer});
@override @override
_InvoiceInfoPageState createState() => _InvoiceInfoPageState(); _InvoiceInfoPageState createState() => _InvoiceInfoPageState();
@@ -57,7 +56,6 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
TextEditingController _discountController = new TextEditingController(); TextEditingController _discountController = new TextEditingController();
TextEditingController _amountController = new TextEditingController(); TextEditingController _amountController = new TextEditingController();
TextEditingController _statusController = new TextEditingController(); TextEditingController _statusController = new TextEditingController();
TextEditingController _handlingFeeController = new TextEditingController();
TextEditingController _customFeeController = new TextEditingController(); TextEditingController _customFeeController = new TextEditingController();
MultiImgController multiImgController = MultiImgController(); MultiImgController multiImgController = MultiImgController();
TextEditingController _descriptionController = new TextEditingController(); TextEditingController _descriptionController = new TextEditingController();
@@ -106,7 +104,6 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
// _amountController.text = _invoice.getAmount.toString(); // _amountController.text = _invoice.getAmount.toString();
_amountController.text = _invoice.amount.toString(); _amountController.text = _invoice.amount.toString();
_statusController.text = _invoice.status.toString(); _statusController.text = _invoice.status.toString();
_handlingFeeController.text = '0';
_customFeeController.text = '0'; _customFeeController.text = '0';
// multiImgController.setImageUrls = _receipts; // multiImgController.setImageUrls = _receipts;
_descriptionController.text = 'For Electronics goods'; _descriptionController.text = 'For Electronics goods';
@@ -116,7 +113,6 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
} else { } else {
_dateController.text = dateFormatter.format(DateTime.now()); _dateController.text = dateFormatter.format(DateTime.now());
_amountController.text = '0'; _amountController.text = '0';
_handlingFeeController.text = '0';
_customFeeController.text = '0'; _customFeeController.text = '0';
_descriptionController.text = ''; _descriptionController.text = '';
_balanceController.text = '0'; _balanceController.text = '0';
@@ -180,31 +176,15 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var mainModel = Provider.of<MainModel>(context);
var discountModel = Provider.of<DiscountModel>(context);
var paymentMethodModel = Provider.of<PaymentMethodModel>(context);
final nameBox = DisplayText( final nameBox = DisplayText(
iconData: Feather.user, iconData: Feather.user,
labelTextKey: 'invoice.customer_name', labelTextKey: 'invoice.customer_name',
text: user != null ? user.name : ''); text: user != null ? user.name : 'Ko Nyi');
final fcsIDBox = Row( final fcsIDBox = DisplayText(
children: <Widget>[ text: user != null ? user.fcsID : "FCS-KRUTUG",
Expanded(
child: DisplayText(
text: user != null ? user.fcsID : "",
labelTextKey: "box.fcs.id", labelTextKey: "box.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
)),
IconButton(
icon: Icon(Icons.search, color: primaryColor),
onPressed: () => searchUser(context, callbackUserSelect: (u) {
setState(() {
this.user = u;
});
})),
],
); );
final statusBox = DisplayText( final statusBox = DisplayText(
@@ -309,9 +289,17 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
child: Row( child: Row(
children: [ children: [
Expanded(flex: 2, child: Text(box.packageNumber)),
Expanded( Expanded(
flex: 1, flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(box.packageNumber),
Text(box.shipmentNumber),
],
)),
Expanded(
flex: 2,
child: Text( child: Text(
box.length == null box.length == null
? "" ? ""
@@ -341,22 +329,27 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 1,
child: Center(
child: LocalText( child: LocalText(
context, context,
"invoice.box.number", "invoice.box.number",
color: Colors.grey, color: Colors.grey,
),
)), )),
Expanded( Expanded(
flex: 1, flex: 2,
child: child: Center(
Text('L x W x H', style: TextStyle(color: Colors.grey))), child: Text('L x W x H',
style: TextStyle(color: Colors.grey)))),
Expanded( Expanded(
flex: 2, flex: 2,
child: Center(
child: LocalText( child: LocalText(
context, context,
"invoice.shipment_weight", "invoice.shipment_weight",
color: Colors.grey, color: Colors.grey,
),
)), )),
], ],
), ),
@@ -596,7 +589,7 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
dataRow.length, dataRow.length,
Container( Container(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: 5.0, right: 5.0, top: 20.0, bottom: 0.0), left: 5.0, right: 5.0, top: 20.0, bottom: 5.0),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
@@ -609,7 +602,7 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
), ),
)), )),
Expanded( Expanded(
child: Text('\$ $customFee', child: Text('\$ 10.0',
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,

View File

@@ -18,7 +18,7 @@ import 'payment_pdf_screen.dart';
class InvoiceListRow extends StatefulWidget { class InvoiceListRow extends StatefulWidget {
final Invoice invoice; final Invoice invoice;
const InvoiceListRow({this.invoice}); InvoiceListRow({Key key, this.invoice}) : super(key: key);
@override @override
_InvoiceListRowState createState() => _InvoiceListRowState(); _InvoiceListRowState createState() => _InvoiceListRowState();

View File

@@ -1,4 +1,5 @@
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart';
import 'package:fcs/pages/shipment/model/shipment_model.dart'; import 'package:fcs/pages/shipment/model/shipment_model.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
@@ -28,7 +29,7 @@ class _InvoiceShipmentListState extends State<InvoiceShipmentList> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ShipmentModel shipmentModel = Provider.of<ShipmentModel>(context); FcsShipmentModel fcsShipmentModel = Provider.of<FcsShipmentModel>(context);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: _isLoading,
child: DefaultTabController( child: DefaultTabController(
@@ -61,10 +62,10 @@ class _InvoiceShipmentListState extends State<InvoiceShipmentList> {
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
padding: EdgeInsets.only(top: 15), padding: EdgeInsets.only(top: 15),
shrinkWrap: true, shrinkWrap: true,
itemCount: shipmentModel.shipments.length, itemCount: fcsShipmentModel.fcsShipments.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return InvoiceShipmentListRow( return InvoiceShipmentListRow(
pickUp: shipmentModel.shipments[index]); fcsShipment: fcsShipmentModel.fcsShipments[index]);
}), }),
), ),
), ),

View File

@@ -1,15 +1,16 @@
import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_icons/flutter_icons.dart';
import 'package:intl/intl.dart';
import '../main/util.dart'; import '../main/util.dart';
import 'invoice_customer_list.dart'; import 'invoice_customer_list.dart';
class InvoiceShipmentListRow extends StatefulWidget { class InvoiceShipmentListRow extends StatefulWidget {
final Shipment pickUp; final FcsShipment fcsShipment;
const InvoiceShipmentListRow({this.pickUp}); const InvoiceShipmentListRow({this.fcsShipment});
@override @override
_InvoiceShipmentListRowState createState() => _InvoiceShipmentListRowState(); _InvoiceShipmentListRowState createState() => _InvoiceShipmentListRowState();
@@ -17,13 +18,14 @@ class InvoiceShipmentListRow extends StatefulWidget {
class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> { class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
final double dotSize = 15.0; final double dotSize = 15.0;
Shipment _pickUp = new Shipment(); final dateFormatter = new DateFormat('dd MMM yyyy');
FcsShipment _fcsShipment = new FcsShipment();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.pickUp != null) { if (widget.fcsShipment != null) {
_pickUp = widget.pickUp; _fcsShipment = widget.fcsShipment;
} }
} }
@@ -40,15 +42,17 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Padding( child: new Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0), padding: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row( child: new Row(
children: <Widget>[ children: <Widget>[
Padding( Container(
padding: EdgeInsets.all(5.0), padding: EdgeInsets.only(left: 5, right: 10),
child: Icon( child: Icon(
SimpleLineIcons.direction, Ionicons.ios_airplane,
color: primaryColor, color: primaryColor,
)), size: 30,
),
),
new Expanded( new Expanded(
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -56,7 +60,9 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: new Text( child: new Text(
_pickUp.id == null ? '' : _pickUp.id, _fcsShipment.shipmentNumber == null
? ''
: _fcsShipment.shipmentNumber,
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
@@ -64,9 +70,7 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
Padding( Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10), padding: const EdgeInsets.only(left: 10.0, top: 10),
child: new Text( child: new Text(
_pickUp.id == null dateFormatter.format(_fcsShipment.cutoffDate),
? ''
: "Last ${_pickUp.last} days",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),
@@ -78,35 +82,10 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
), ),
), ),
), ),
Column(
children: <Widget>[
Padding( Padding(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: getStatus(_pickUp.currentStatus), child: getStatus(_fcsShipment.status),
), ),
Padding(
padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5),
child: Row(
children: <Widget>[
new Text(
_pickUp.weight == null
? ''
: _pickUp.weight.toString() + 'lb - ',
style:
new TextStyle(fontSize: 15.0, color: Colors.grey),
),
new Text(
_pickUp.numberOfPackage == null
? ""
: _pickUp.numberOfPackage.toString() + ' packages',
style:
new TextStyle(fontSize: 15.0, color: Colors.grey),
),
],
),
),
],
)
], ],
), ),
), ),

View File

@@ -1,118 +1,22 @@
import 'dart:async'; import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/entities/invoice.dart'; import 'package:fcs/domain/entities/invoice.dart';
import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/domain/entities/receipt.dart'; import 'package:fcs/domain/entities/receipt.dart';
import 'package:fcs/helpers/pagination.dart'; import 'package:fcs/domain/vo/message.dart';
import 'package:fcs/helpers/paginator.dart';
import 'package:fcs/pages/main/model/base_model.dart'; import 'package:fcs/pages/main/model/base_model.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:fcs/domain/constants.dart';
class InvoiceModel extends BaseModel { class InvoiceModel extends BaseModel {
final log = Logger('InvoiceModel'); final log = Logger('InvoiceModel');
Pagination pagination;
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot> listener;
List<Invoice> invoices = [ List<Invoice> _invoices = [
Invoice(
invoiceNumber: 'A092(A)-30',
invoiceDate: DateTime(2020, 4, 5, 12, 30),
customerName: 'Ko Nyi',
customerPhoneNumber: '+959 888888888',
amount: 500,
status: 'Pending',
packages: [
Package(
shipmentNumber: "A202",
receiverNumber: "3",
boxNumber: "1",
rate: 7,
packageType: "General",
weight: 25,
status: "Received",
receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon',
arrivedDate: DateTime(2020, 6, 1),
),
Package(
shipmentNumber: "A202",
receiverNumber: "3",
boxNumber: "2",
rate: 7,
packageType: "General",
weight: 20,
status: "Received",
arrivedDate: DateTime(2020, 6, 1),
receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'),
],
receipts: [
Receipt(amount: 200, date: DateTime(2020, 6, 1)),
Receipt(amount: 100, date: DateTime(2020, 6, 16)),
]),
Invoice(
invoiceNumber: 'A092(A)-31',
invoiceDate: DateTime(2020, 4, 5, 9, 30),
customerName: 'Ko Aung Myo',
customerPhoneNumber: '+959 444444444',
amount: 300,
status: 'Paid',
packages: [
Package(
shipmentNumber: "A202",
receiverNumber: "3",
boxNumber: "3",
rate: 7,
packageType: "General",
weight: 15,
status: "Received",
arrivedDate: DateTime(2020, 6, 1),
receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'),
Package(
shipmentNumber: "A202",
receiverNumber: "2",
boxNumber: "1",
rate: 8,
packageType: "Medicine",
weight: 15,
status: "Processing",
arrivedDate: DateTime(2020, 6, 1),
receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'),
],
receipts: [
Receipt(amount: 200, date: DateTime(2020, 6, 1)),
]),
Invoice(
invoiceNumber: 'A092(A)-32',
invoiceDate: DateTime(2020, 4, 6, 10, 10),
customerName: 'Ko Zaw Thu',
customerPhoneNumber: '+959 777777777',
amount: 200,
status: 'Paid',
packages: [
Package(
shipmentNumber: "A202",
receiverNumber: "2",
boxNumber: "2",
rate: 7,
packageType: "General",
weight: 55,
status: "Ready to ship",
arrivedDate: DateTime(2020, 6, 1),
receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'),
Package(
shipmentNumber: "A201",
receiverNumber: "1",
boxNumber: "1",
rate: 9,
packageType: "Dangerous",
weight: 25,
status: "Delivered",
arrivedDate: DateTime(2020, 5, 21),
receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'),
],
receipts: [
Receipt(amount: 200, date: DateTime(2020, 6, 1)),
]),
Invoice( Invoice(
invoiceNumber: 'A092(A)-33', invoiceNumber: 'A092(A)-33',
invoiceDate: DateTime(2020, 4, 6, 12, 15), invoiceDate: DateTime(2020, 4, 6, 12, 15),
@@ -121,7 +25,7 @@ class InvoiceModel extends BaseModel {
amount: 300, amount: 300,
status: 'Pending', status: 'Pending',
receipts: [ receipts: [
Receipt(amount: 200, date: DateTime(2020, 6, 1)), Receipt(amount: 200, date: '1 Jun 2020'),
], ],
packages: [ packages: [
Package( Package(
@@ -147,29 +51,55 @@ class InvoiceModel extends BaseModel {
]) ])
]; ];
List<Invoice> paidInvoices = []; List<Invoice> get invoices =>
_selectedIndex == 1 ? _invoices : List<Invoice>.from(_paid.values);
Paginator _paid;
bool endOfPaidInvoices = false; bool endOfPaidInvoices = false;
bool isLoading = false; bool isLoading = false;
int _selectedIndex = 1;
set selectedIndex(int index) {
_selectedIndex = index;
notifyListeners();
}
get selectedIndex => _selectedIndex;
@override @override
void privilegeChanged() { void privilegeChanged() {
super.privilegeChanged(); super.privilegeChanged();
// _loadInvoices();
} }
Future<void> _loadInvoices() async { initData(bool forCustomer) {
if (user == null || !user.hasInvoices()) return; _selectedIndex = 1;
String path = "/$invoices/"; // _loadFcsInvoices(forCustomer);
if (_paid != null) _paid.close();
_paid = _getPaid(forCustomer);
}
Future<void> _loadFcsInvoices(bool forCustomer) async {
if (user == null) return;
if (!forCustomer && !user.hasInvoices()) return;
String path = "/$invoices_collection";
if (listener != null) listener.cancel(); if (listener != null) listener.cancel();
invoices = []; _invoices = [];
try { try {
listener = Firestore.instance var q = Firestore.instance
.collection("$path") .collection("$path")
.snapshots() .where("is_paid", isEqualTo: false)
.listen((QuerySnapshot snapshot) { .where("is_deleted", isEqualTo: false);
invoices.clear();
invoices = snapshot.documents.map((documentSnapshot) { if (forCustomer) {
q = q.where("user_id", isEqualTo: user.id);
}
listener = q.snapshots().listen((QuerySnapshot snapshot) {
_invoices.clear();
_invoices = snapshot.documents.map((documentSnapshot) {
var s = Invoice.fromMap( var s = Invoice.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data, documentSnapshot.documentID);
return s; return s;
@@ -181,75 +111,57 @@ class InvoiceModel extends BaseModel {
} }
} }
Future<void> initPaidInvoice(bool onlyFcs) { Paginator _getPaid(bool isCustomer) {
if (onlyFcs) { if (!isCustomer) {
if (user == null || if (user == null || !(user.hasInvoices())) throw "No privilege";
!((user.hasPackages() ||
user.hasReceiving() ||
user.hasProcessing()))) return null;
} }
if (pagination != null) pagination.close();
paidInvoices = [];
endOfPaidInvoices = false;
isLoading = false;
var pageQuery = Firestore.instance var pageQuery = Firestore.instance
.collection("/$invoices"); .collection("/$packages_collection")
// .collection( .where("is_delivered", isEqualTo: true)
// "/users/8OTfsbVvsUOn1SLxy1OrKk7Y_yNKkVoGalPcIlcHnAY/messages") .where("is_deleted", isEqualTo: false);
// .orderBy("date", descending: true); if (isCustomer) {
// .where("is_delivered", isEqualTo: true)
// .where("is_deleted", isEqualTo: false);
if (!onlyFcs) {
pageQuery = pageQuery.where("user_id", isEqualTo: user.id); pageQuery = pageQuery.where("user_id", isEqualTo: user.id);
} }
// pageQuery = pageQuery.orderBy("current_status_date", descending: true); pageQuery = pageQuery.orderBy("current_status_date", descending: true);
pagination = new Pagination(pageQuery, rowPerLoad: 20); var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) {
pagination.stream.listen((doc) { return Invoice.fromMap(data, id);
if (doc == null) {
endOfPaidInvoices = true;
} else {
paidInvoices.add(Invoice.fromMap(doc.data, doc.documentID));
// var m = Message.fromMap(doc.data, doc.documentID);
// deliveredPackages.add(Package(
// id: m.id,
// status: package_delivered_status,
// currentStatus: package_delivered_status,
// currentStatusDate: m.date,
// trackingID: (count++).toString(),
// market: m.message));
}
}); });
return null; return paginator;
} }
Future<bool> loadMorePaidInvoices() { Future<void> loadMore({bool isCustomer}) async {
if (pagination != null && !isLoading && !endOfPaidInvoices) { if (_selectedIndex == 1) return; // when paid menu is not selected return
if (_paid.ended) return;
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
pagination.load().then((value) { await _paid.load(onFinished: () {
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
}); });
} }
return null;
Future<void> refresh({bool isCustomer}) async {
if (_selectedIndex == 1) return; // when paid menu is not selected return
await _paid.refresh(onFinished: () {
notifyListeners();
});
} }
void initUser(user) { void initUser(user) {
super.initUser(user); super.initUser(user);
} }
@override
logout() async { logout() async {
if (_paid != null) _paid.close();
if (listener != null) await listener.cancel(); if (listener != null) await listener.cancel();
invoices = []; _invoices = [];
} }
Future<void> create(Invoice invoice) { Future<void> createInvoice(Invoice invoice) {
// return Services.instance.fcsShipmentService.createFcsShipment(fcsShipment); // return Services.instance.invoiceService.createInvoice(invoice);
} }
Future<void> update(Invoice invoice) { Future<void> updateInvoice(Invoice invoice) {
// return Services.instance.fcsShipmentService.updateFcsShipment(fcsShipment); // return Services.instance.invoiceService.updateInvoice(invoice);
} }
} }

View File

@@ -1,21 +1,19 @@
import 'dart:io';
import 'package:fcs/domain/entities/invoice.dart'; import 'package:fcs/domain/entities/invoice.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/invoice/payment_page_edit.dart';
import 'package:fcs/pages/widgets/image_file_picker.dart';
import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/local_title.dart'; import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/multi_img_controller.dart';
import 'package:fcs/pages/widgets/multi_img_file.dart';
import 'package:fcs/pages/widgets/my_data_table.dart';
import 'package:fcs/pages/widgets/number_cell.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:fcs/pages/widgets/show_img.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
class PaymentPage extends StatefulWidget { class PaymentPage extends StatefulWidget {
final Invoice invoice; final Invoice invoice;
@@ -33,6 +31,7 @@ class _PaymentPageState extends State<PaymentPage> {
bool _isLoading = false; bool _isLoading = false;
bool isNew; bool isNew;
File _file;
@override @override
void initState() { void initState() {
@@ -59,7 +58,25 @@ class _PaymentPageState extends State<PaymentPage> {
final receiptFileBox = Row(children: [ final receiptFileBox = Row(children: [
LocalText(context, 'pm.attachment', fontSize: 16, color: Colors.grey), LocalText(context, 'pm.attachment', fontSize: 16, color: Colors.grey),
IconButton( IconButton(
icon: Icon(Icons.attachment, color: primaryColor), onPressed: () {}) icon: Icon(Icons.attachment, color: primaryColor),
onPressed: () {
modelBottomSheet(context, onFile: (file) {
setState(() {
_file = file;
});
});
})
]);
final payBox = Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 50,
width: 100,
alignment: Alignment.center,
child: Text(AppTranslations.of(context).text("pm.pay"),
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 14)),
color: primaryColor)
]); ]);
return LocalProgress( return LocalProgress(
@@ -73,9 +90,6 @@ class _PaymentPageState extends State<PaymentPage> {
), ),
backgroundColor: primaryColor, backgroundColor: primaryColor,
title: Text(AppTranslations.of(context).text("pm_.title")), title: Text(AppTranslations.of(context).text("pm_.title")),
actions: [
IconButton(icon: Icon(Icons.cloud_upload), onPressed: () {})
],
), ),
body: ListView( body: ListView(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
@@ -84,6 +98,7 @@ class _PaymentPageState extends State<PaymentPage> {
SizedBox(height: 10), SizedBox(height: 10),
receiptFileBox, receiptFileBox,
SizedBox(height: 10), SizedBox(height: 10),
payBox,
Divider(), Divider(),
SizedBox(height: 10), SizedBox(height: 10),
LocalTitle(textKey: "pm.receipt"), LocalTitle(textKey: "pm.receipt"),
@@ -109,16 +124,32 @@ class _PaymentPageState extends State<PaymentPage> {
border: Border(bottom: BorderSide(color: Colors.grey))), border: Border(bottom: BorderSide(color: Colors.grey))),
padding: padding:
const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
child: InkWell(
onTap: () {
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => PaymentPageEdit(receipt: r)));
},
child: Row( child: Row(
children: [ children: [
Expanded(flex: 2, child: Text(dateFormatter.format(r.date))), Expanded(flex: 2, child: Text('${r.date}')),
Expanded( Expanded(
flex: 2, flex: 2,
child: Center(child: Text('receipt' + k.toString() + '.png'))), child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShowImage(
localImage: 'assets/logo.jpg',
url: null,
fileName: 'image')));
},
child: Icon(Icons.attachment, color: primaryColor))),
Expanded(flex: 1, child: Center(child: Text('pending'))), Expanded(flex: 1, child: Center(child: Text('pending'))),
Expanded(flex: 1, child: Center(child: Text('\$ ${r.amount}'))), Expanded(flex: 1, child: Center(child: Text('\$ ${r.amount}'))),
], ],
), ),
),
); );
}).toList(); }).toList();
@@ -133,7 +164,7 @@ class _PaymentPageState extends State<PaymentPage> {
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 2,
child: Text('Product', style: TextStyle(color: Colors.grey))), child: Text('Date', style: TextStyle(color: Colors.grey))),
Expanded( Expanded(
flex: 2, flex: 2,
child: Text('File', child: Text('File',

View File

@@ -0,0 +1,222 @@
import 'dart:io';
import 'package:fcs/domain/entities/invoice.dart';
import 'package:fcs/domain/entities/receipt.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/display_text.dart';
import 'package:fcs/pages/widgets/image_file_picker.dart';
import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:fcs/pages/widgets/show_img.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
class PaymentPageEdit extends StatefulWidget {
final Receipt receipt;
PaymentPageEdit({this.receipt});
@override
_PaymentPageEditState createState() => _PaymentPageEditState();
}
class _PaymentPageEditState extends State<PaymentPageEdit> {
TextEditingController _amountController = new TextEditingController();
var dateFormatter = new DateFormat('dd MMM yyyy');
Receipt _receipt = new Receipt();
bool _isLoading = false;
File _file;
bool isNew;
@override
void initState() {
if (widget.receipt != null) {
_receipt = widget.receipt;
}
super.initState();
}
@override
void dispose() {
super.dispose();
}
final DateFormat dateFormat = DateFormat("d MMM yyyy");
@override
Widget build(BuildContext context) {
var mainModel = Provider.of<MainModel>(context, listen: false);
bool customer = mainModel.isCustomer();
final amountBox = DisplayText(
labelTextKey: 'pm.amount',
iconData: FontAwesomeIcons.moneyBill,
text: _receipt.amount.toString());
final dateBox = DisplayText(
labelTextKey: 'pm.date',
iconData: Icons.date_range,
text: _receipt.date);
final statusBox = DisplayText(
labelTextKey: 'pm.status',
iconData: Icons.av_timer,
text: _receipt.status);
final receiptFileBox = Row(children: [
LocalText(context, 'pm.attachment', fontSize: 16, color: Colors.grey),
IconButton(
icon: Icon(Icons.attachment, color: primaryColor), onPressed: () {})
]);
final comfirmBox =
fcsButton(context, getLocalString(context, 'pm.btn_confirm'));
final cancelBox =
fcsButton(context, getLocalString(context, 'pm.btn_cancel'));
final fileBox = Container(
// padding: EdgeInsets.only(top: 20, left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocalText(
context,
"pm.attachment",
fontSize: 16,
color: labelColor,
),
Container(
padding: EdgeInsets.only(top: 15),
child: Stack(
children: <Widget>[
Container(
width: 200,
height: 200,
padding: const EdgeInsets.all(2.0),
decoration: BoxDecoration(
color: Colors.grey[300],
border: Border.all(
color: primaryColor,
width: 1.0,
),
),
child: _file == null
? checkImage(context)
: enableUpload(context),
),
customer
? Positioned(
bottom: -8,
right: -10,
child: IconButton(
color: primaryColor,
icon: CircleAvatar(
backgroundColor: primaryColor,
radius: 20,
child: Icon(
FontAwesomeIcons.camera,
size: 20,
color: Colors.white,
),
),
onPressed: () =>
modelBottomSheet(context, onFile: (file) {
setState(() {
_file = file;
});
}),
))
: Container()
],
),
),
],
),
);
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
leading: new IconButton(
icon: new Icon(CupertinoIcons.back),
onPressed: () => Navigator.of(context).pop(),
),
backgroundColor: primaryColor,
title: Text(AppTranslations.of(context).text("pm_.title")),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
dateBox,
SizedBox(height: 10),
amountBox,
SizedBox(height: 10),
statusBox,
SizedBox(height: 10),
fileBox,
SizedBox(height: 5),
Spacer(),
customer ? Container() : comfirmBox,
SizedBox(height: 5),
customer ? cancelBox : Container(),
SizedBox(height: 5),
],
),
),
),
);
}
Widget checkImage(BuildContext context) {
if (widget.receipt == null) {
return initialImage();
} else {
Widget _widget;
if (widget.receipt.fileUrl == null) {
_widget = initialImage();
} else {
_widget = InkWell(
child: Image.asset(widget.receipt.fileUrl, fit: BoxFit.cover),
onTap: () {},
);
}
return _widget;
}
}
Widget initialImage() {
return Center(
child: Icon(
Icons.insert_photo,
size: 45,
color: labelColor,
),
);
}
Widget enableUpload(BuildContext context) {
return InkWell(
child: Image.file(_file, fit: BoxFit.cover),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ShowImage(imageFile: _file, url: null, fileName: 'image')));
},
);
}
}

View File

@@ -1,11 +1,18 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart'; import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:image_downloader/image_downloader.dart'; import 'package:image_downloader/image_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:share/share.dart';
import 'package:http/http.dart' as http;
class PaymentPDFScreen extends StatefulWidget { class PaymentPDFScreen extends StatefulWidget {
final String path; final String path;
@@ -41,14 +48,13 @@ class _PaymentPDFScreenState extends State<PaymentPDFScreen>
IconButton( IconButton(
icon: Icon(Icons.file_download), icon: Icon(Icons.file_download),
onPressed: () async { onPressed: () async {
print('image path => ${widget.path}'); // var _dir = (await getApplicationDocumentsDirectory()).path;
await ImageDownloader.downloadImage(widget.path, // _downloadFile(widget.path, 'invoice.pdf', _dir);
destination: AndroidDestinationType.directoryDownloads);
}, },
), ),
IconButton( IconButton(
icon: Icon(Icons.share), icon: Icon(Icons.share),
onPressed: () {}, onPressed: () => _share(widget.path),
), ),
], ],
), ),
@@ -72,18 +78,6 @@ class _PaymentPDFScreenState extends State<PaymentPDFScreen>
isReady = true; isReady = true;
}); });
}, },
// onError: (error) {
// setState(() {
// errorMessage = error.toString();
// });
// print(error.toString());
// },
// onPageError: (page, error) {
// setState(() {
// errorMessage = '$page: ${error.toString()}';
// });
// print('$page: ${error.toString()}');
// },
onViewCreated: (PDFViewController pdfViewController) { onViewCreated: (PDFViewController pdfViewController) {
_controller.complete(pdfViewController); _controller.complete(pdfViewController);
}, },
@@ -97,32 +91,24 @@ class _PaymentPDFScreenState extends State<PaymentPDFScreen>
}); });
}, },
), ),
// errorMessage.isEmpty
// ? !isReady
// ? Center(
// child: CircularProgressIndicator(),
// )
// : Container()
// : Center(
// child: Text(errorMessage),
// )
], ],
), ),
// floatingActionButton: FutureBuilder<PDFViewController>(
// future: _controller.future,
// builder: (context, AsyncSnapshot<PDFViewController> snapshot) {
// if (snapshot.hasData) {
// return FloatingActionButton.extended(
// label: Text("Go to ${pages ~/ 2}"),
// onPressed: () async {
// await snapshot.data.setPage(pages ~/ 2);
// },
// );
// }
// return Container();
// },
// ),
); );
} }
Future<File> _downloadFile(String url, String filename, String dir) async {
var req = await http.Client().get(Uri.parse(url));
var file = File('$dir/$filename');
return file.writeAsBytes(req.bodyBytes);
}
_share(String url) async {
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
String appUrl = mainModel.setting.appUrl;
final RenderBox box = context.findRenderObject();
await Share.share(
"Join us on FCS Logistics App. Here is the link:\n $appUrl\n" + url,
subject: "Invitation to FCS Logistics App",
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
}
} }

View File

@@ -295,12 +295,12 @@ class _HomePageState extends State<HomePage> {
final invoicesBtn = TaskButton("invoices.btn", final invoicesBtn = TaskButton("invoices.btn",
icon: FontAwesomeIcons.fileInvoice, icon: FontAwesomeIcons.fileInvoice,
btnCallback: () => Navigator.of(context).push<void>( btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
CupertinoPageRoute(builder: (context) => InvoiceList()))); builder: (context) => InvoiceList(forCustomer: false))));
final invoicesBtnFcs = TaskButton("invoices.btn", final invoicesBtnFcs = TaskButton("invoices.btn",
icon: FontAwesomeIcons.fileInvoice, icon: FontAwesomeIcons.fileInvoice,
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute( btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
builder: (context) => InvoiceList(onlyFcs: true)))); builder: (context) => InvoiceList(forCustomer: true))));
final discountBtn = TaskButton("discount.btn", final discountBtn = TaskButton("discount.btn",
icon: Entypo.price_ribbon, icon: Entypo.price_ribbon,

View File

@@ -15,17 +15,22 @@ import 'custom_row.dart';
import 'model/shipment_rate_model.dart'; import 'model/shipment_rate_model.dart';
class CustomList extends StatefulWidget { class CustomList extends StatefulWidget {
const CustomList({Key key}) : super(key: key); final bool selected;
const CustomList({Key key, this.selected}) : super(key: key);
@override @override
_CustomListState createState() => _CustomListState(); _CustomListState createState() => _CustomListState();
} }
class _CustomListState extends State<CustomList> { class _CustomListState extends State<CustomList> {
bool _isLoading = false; bool _isLoading = false;
bool _selected = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.selected != null) {
_selected = widget.selected;
}
} }
@override @override
@@ -75,8 +80,11 @@ class _CustomListState extends State<CustomList> {
shipmentRateModel.rate.customDuties[index]; shipmentRateModel.rate.customDuties[index];
return InkWell( return InkWell(
onTap: () { onTap: () {
Navigator.of(context).push(CupertinoPageRoute( _selected
builder: (context) => CustomEditor(custom: custom))); ? Navigator.pop(context, custom)
: Navigator.of(context).push(CupertinoPageRoute(
builder: (context) =>
CustomEditor(custom: custom)));
}, },
child: Container( child: Container(
child: _row( child: _row(

View File

@@ -0,0 +1,90 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:image_picker/image_picker.dart';
import 'local_text.dart';
typedef OnFile = void Function(File);
modelBottomSheet(BuildContext context, {final OnFile onFile}) {
showModalBottomSheet(
elevation: 10,
backgroundColor: Colors.white,
context: context,
builder: (BuildContext context) {
return ImageFile(onFile: onFile);
});
}
class ImageFile extends StatefulWidget {
final OnFile onFile;
const ImageFile({Key key, this.onFile}) : super(key: key);
@override
_ImageFileState createState() => _ImageFileState();
}
class _ImageFileState extends State<ImageFile> {
File selectedFile;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(bottom: 20, top: 20),
child: new Wrap(
children: <Widget>[
new ListTile(
leading: CircleAvatar(
radius: 20,
backgroundColor: Colors.green,
child: Icon(MaterialIcons.insert_photo, color: Colors.white),
),
title: LocalText(context, "profile.gallery",
color: Colors.black87, fontSize: 15),
onTap: () async {
Navigator.pop(context);
selectedFile = await pickImage(ImageSource.gallery);
if (widget.onFile != null) widget.onFile(selectedFile);
}),
new ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blue,
radius: 20,
child: Center(child: Icon(AntDesign.camera, color: Colors.white)),
),
title: LocalText(context, "profile.camera",
color: Colors.black87, fontSize: 15),
onTap: () async {
Navigator.pop(context);
selectedFile = await pickImage(ImageSource.camera);
if (widget.onFile != null) widget.onFile(selectedFile);
},
),
new ListTile(
leading: CircleAvatar(
backgroundColor: Colors.red,
radius: 20,
child: Icon(Icons.delete, color: Colors.white),
),
title: LocalText(context, "profile.remove_photo",
color: Colors.black87, fontSize: 15),
onTap: () {
Navigator.pop(context);
setState(() {
selectedFile = null;
});
if (widget.onFile != null) widget.onFile(selectedFile);
},
),
],
),
);
}
pickImage(ImageSource source) async {
var tempImage = await ImagePicker.pickImage(source: source);
return tempImage;
}
}

View File

@@ -8,7 +8,9 @@ class ShowImage extends StatefulWidget {
final String url; final String url;
final File imageFile; final File imageFile;
final String fileName; final String fileName;
const ShowImage({Key key, this.imageFile, this.fileName, this.url}) final String localImage;
const ShowImage(
{Key key, this.imageFile, this.fileName, this.url, this.localImage})
: super(key: key); : super(key: key);
@override @override
_ShowImageState createState() => _ShowImageState(); _ShowImageState createState() => _ShowImageState();
@@ -20,16 +22,17 @@ class _ShowImageState extends State<ShowImage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: primaryColor, backgroundColor: primaryColor,
title: Text(widget.fileName), title: Text(widget.fileName, style: TextStyle(color: Colors.white)),
iconTheme: new IconThemeData(color: Colors.white),
), ),
body: Center( body: Center(
child: widget.url != null || widget.imageFile != null child: PhotoView(
? PhotoView(
imageProvider: widget.url != null imageProvider: widget.url != null
? NetworkImage(widget.url) ? NetworkImage(widget.url)
: FileImage(widget.imageFile), : widget.imageFile != null
minScale: PhotoViewComputedScale.contained * 1) ? FileImage(widget.imageFile)
: Container()), : AssetImage(widget.localImage),
minScale: PhotoViewComputedScale.contained * 1)),
); );
} }
} }