This commit is contained in:
unknown 2018-06-14 12:20:02 -07:00
parent 866e5dabb5
commit dd24008091
7 changed files with 345 additions and 91 deletions

View File

@ -4,11 +4,10 @@ import 'package:invoiceninja/data/models/models.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_details.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja/utils/localization.dart';
import '../../app/save_icon_button.dart';
import 'client_edit_billing_address.dart';
import 'client_edit_contacts.dart';
import 'client_edit_shipping_address.dart';
import 'package:invoiceninja/ui/app/save_icon_button.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_billing_address.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_contacts.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_shipping_address.dart';
class ClientEdit extends StatefulWidget {
final ClientEditVM viewModel;

View File

@ -4,8 +4,7 @@ import 'package:invoiceninja/data/models/models.dart';
import 'package:invoiceninja/ui/client/edit/client_edit.dart';
import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja/utils/localization.dart';
import '../../app/form_card.dart';
import 'package:invoiceninja/ui/app/form_card.dart';
class ClientEditDetails extends StatefulWidget {
ClientEditDetails({

View File

@ -3,10 +3,11 @@ import 'package:flutter/material.dart';
import 'package:invoiceninja/ui/app/actions_menu_button.dart';
import 'package:invoiceninja/ui/app/form_card.dart';
import 'package:invoiceninja/ui/app/progress_button.dart';
import 'package:invoiceninja/ui/invoice/edit/invoice_edit_details.dart';
import 'package:invoiceninja/ui/invoice/edit/invoice_edit_items.dart';
import 'package:invoiceninja/ui/invoice/edit/invoice_edit_vm.dart';
import 'package:invoiceninja/utils/localization.dart';
import '../../app/save_icon_button.dart';
import 'package:invoiceninja/ui/app/save_icon_button.dart';
class InvoiceEdit extends StatefulWidget {
final InvoiceEditVM viewModel;
@ -20,100 +21,89 @@ class InvoiceEdit extends StatefulWidget {
_InvoiceEditState createState() => _InvoiceEditState();
}
class _InvoiceEditState extends State<InvoiceEdit> {
class _InvoiceEditState extends State<InvoiceEdit>
with SingleTickerProviderStateMixin {
TabController _controller;
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
static final GlobalKey<InvoiceEditDetailsState> _detailsKey =
GlobalKey<InvoiceEditDetailsState>();
static final GlobalKey<InvoiceEditItemsState> _itemsKey =
GlobalKey<InvoiceEditItemsState>();
String _invoiceKey;
String _notes;
double _cost;
@override
void initState() {
super.initState();
_controller = new TabController(vsync: this, length: 2);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var viewModel = widget.viewModel;
var localization = AppLocalization.of(context);
var invoice = widget.viewModel.invoice;
List<Widget> editors = [
InvoiceEditDetails(
invoice: invoice,
key: _detailsKey,
),
InvoiceEditItems(
invoice: invoice,
key: _itemsKey,
),
];
return Scaffold(
appBar: AppBar(
title: Text(viewModel.invoice.isNew()
? AppLocalization.of(context).newInvoice
: viewModel.invoice.invoiceNumber),
title: Text(invoice.isNew()
? localization.newInvoice
: invoice.invoiceNumber),
actions: <Widget>[
Builder(builder: (BuildContext context) {
return SaveIconButton(
isLoading: viewModel.isLoading,
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
SaveIconButton(
isLoading: widget.viewModel.isLoading,
onPressed: () {
if (! _formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
/*
viewModel.onSaveClicked(
context,
viewModel.invoice.rebuild((b) => b
..invoiceNumber= _invoiceKey
..notes = _notes
..cost = _cost));
*/
},
);
}),
viewModel.invoice.isNew()
? Container()
: ActionMenuButton(
entity: viewModel.invoice,
onSelected: viewModel.onActionSelected,
)
_formKey.currentState.save();
var detailsState = _detailsKey.currentState;
var itemsState = _itemsKey.currentState;
/*
InvoiceEntity invoice = widget.viewModel.invoice.rebuild((b) => b
..items.replace(
itemState?.getItems() ?? widget.viewModel.invoice.items));
*/
widget.viewModel.onSaveClicked(context, invoice);
},
)
],
bottom: TabBar(
controller: _controller,
//isScrollable: true,
tabs: [
Tab(
text: localization.details,
),
Tab(
text: localization.items,
),
],
),
),
body: Form(
key: _formKey,
child: ListView(
children: <Widget>[
FormCard(
children: <Widget>[
/*
TextFormField(
autocorrect: false,
onSaved: (value) {
_invoiceKey = value;
},
initialValue: viewModel.invoice.invoiceKey,
decoration: InputDecoration(
//border: InputBorder.none,
labelText: AppLocalization.of(context).invoice,
),
validator: (val) => val.isEmpty || val.trim().length == 0
? AppLocalization.of(context).pleaseEnterAInvoiceKey
: null,
),
TextFormField(
initialValue: viewModel.invoice.notes,
onSaved: (value) {
_notes = value;
},
maxLines: 4,
decoration: InputDecoration(
labelText: AppLocalization.of(context).notes,
),
),
TextFormField(
initialValue: viewModel.invoice.cost == null ||
viewModel.invoice.cost == 0.0
? null
: viewModel.invoice.cost.toStringAsFixed(2),
onSaved: (value) {
_cost = double.tryParse(value) ?? 0.0;
},
keyboardType: TextInputType.number,
decoration: InputDecoration(
//border: InputBorder.none,
labelText: AppLocalization.of(context).cost,
),
),
*/
],
),
],
child: TabBarView(
controller: _controller,
children: editors,
),
),
);

View File

@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:invoiceninja/data/models/models.dart';
import 'package:invoiceninja/ui/app/form_card.dart';
import 'package:invoiceninja/utils/localization.dart';
class InvoiceEditDetails extends StatefulWidget {
InvoiceEditDetails({
Key key,
@required this.invoice,
}) : super(key: key);
final InvoiceEntity invoice;
@override
InvoiceEditDetailsState createState() => new InvoiceEditDetailsState();
}
class InvoiceEditDetailsState extends State<InvoiceEditDetails>
with AutomaticKeepAliveClientMixin {
int clientId;
String invoiceDate;
String dueDate;
double partial;
String partialDate;
String invoiceNumber;
String poNumber;
double discount;
bool isAmountDiscount;
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
var localization = AppLocalization.of(context);
var invoice = widget.invoice;
return ListView(
shrinkWrap: true,
children: <Widget>[
invoice.isNew()
? Container()
: TextFormField(
autocorrect: false,
onSaved: (value) => invoiceNumber = value.trim(),
initialValue: invoice.invoiceNumber,
decoration: InputDecoration(
labelText: localization.invoiceNumber,
),
),
TextFormField(
autocorrect: false,
onSaved: (value) => poNumber = value.trim(),
initialValue: invoice.poNumber,
decoration: InputDecoration(
labelText: localization.poNumber,
),
),
TextFormField(
autocorrect: false,
onSaved: (value) => discount = double.tryParse(value) ?? 0.0,
initialValue: invoice.discount.toStringAsFixed(2),
decoration: InputDecoration(
labelText: localization.discount,
),
),
TextFormField(
autocorrect: false,
onSaved: (value) => partial = double.tryParse(value) ?? 0.0,
initialValue: invoice.partial.toStringAsFixed(2),
decoration: InputDecoration(
labelText: localization.partial,
),
),
],
);
}
}

View File

@ -0,0 +1,184 @@
import 'package:flutter/material.dart';
import 'package:invoiceninja/data/models/models.dart';
import 'package:invoiceninja/utils/localization.dart';
import 'package:invoiceninja/ui/app/form_card.dart';
class InvoiceEditItems extends StatefulWidget {
InvoiceEditItems({
Key key,
@required this.invoice,
}) : super(key: key);
final InvoiceEntity invoice;
@override
InvoiceEditItemsState createState() => new InvoiceEditItemsState();
}
class InvoiceEditItemsState extends State<InvoiceEditItems>
with AutomaticKeepAliveClientMixin {
List<InvoiceItemEntity> invoiceItems;
List<GlobalKey<ItemEditDetailsState>> invoiceItemKeys;
@override
bool get wantKeepAlive => true;
@override
void initState() {
super.initState();
var invoice = widget.invoice;
invoiceItems = invoice.invoiceItems.toList();
invoiceItemKeys = invoice.invoiceItems
.map((invoiceItem) => GlobalKey<ItemEditDetailsState>())
.toList();
}
List<InvoiceItemEntity> getItems() {
List<InvoiceItemEntity> invoiceItems = [];
invoiceItemKeys.forEach((invoiceItemKey) {
if (invoiceItemKey.currentState != null) {
invoiceItems.add(invoiceItemKey.currentState.getItem());
}
});
return invoiceItems;
}
_onAddPressed() {
setState(() {
invoiceItems.add(InvoiceItemEntity());
invoiceItemKeys.add(GlobalKey<ItemEditDetailsState>());
});
}
_onRemovePressed(GlobalKey<ItemEditDetailsState> key) {
setState(() {
var index = invoiceItemKeys.indexOf(key);
invoiceItemKeys.removeAt(index);
invoiceItems.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
var localization = AppLocalization.of(context);
List<Widget> invoiceItems = [];
for (var i = 0; i < invoiceItems.length; i++) {
var invoiceItem = invoiceItems[i];
var invoiceItemKey = invoiceItemKeys[i];
invoiceItems.add(ItemEditDetails(
//invoiceItem: invoiceItem,
key: invoiceItemKey,
onRemovePressed: (key) => _onRemovePressed(key),
isRemoveVisible: invoiceItems.length > 1,
));
}
invoiceItems.add(Padding(
padding: const EdgeInsets.only(left: 16.0, right: 16.0, top: 4.0),
child: RaisedButton(
elevation: 4.0,
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).secondaryHeaderColor,
//child: Text(localization.addItem.toUpperCase()),
onPressed: _onAddPressed,
),
));
return ListView(
children: invoiceItems,
);
}
}
class ItemEditDetails extends StatefulWidget {
ItemEditDetails({
Key key,
@required this.invoiceItem,
@required this.onRemovePressed,
@required this.isRemoveVisible,
}) : super(key: key);
final InvoiceItemEntity invoiceItem;
final Function(GlobalKey<ItemEditDetailsState>) onRemovePressed;
final bool isRemoveVisible;
@override
ItemEditDetailsState createState() => ItemEditDetailsState();
}
class ItemEditDetailsState extends State<ItemEditDetails> {
String _firstName;
String _lastName;
String _email;
String _phone;
InvoiceItemEntity getItem() {
return widget.invoiceItem.rebuild((b) => b
//..phone = _phone
);
}
@override
Widget build(BuildContext context) {
var localization = AppLocalization.of(context);
_confirmDelete() {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
semanticLabel: localization.areYouSure,
title: Text(localization.areYouSure),
actions: <Widget>[
new FlatButton(
child: Text(localization.cancel.toUpperCase()),
onPressed: () {
Navigator.pop(context);
}),
new FlatButton(
child: Text(localization.ok.toUpperCase()),
onPressed: () {
widget.onRemovePressed(widget.key);
Navigator.pop(context);
})
],
),
);
}
return FormCard(
children: <Widget>[
/*
TextFormField(
autocorrect: false,
initialValue: widget.invoiceItem.firstName,
onSaved: (value) => _firstName = value.trim(),
decoration: InputDecoration(
labelText: localization.firstName,
),
),
*/
widget.isRemoveVisible
? Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 14.0),
child: FlatButton(
child: Text(
localization.remove,
style: TextStyle(
color: Colors.grey[600],
),
),
onPressed: _confirmDelete,
),
)
],
)
: Container(),
],
);
}
}

View File

@ -5,8 +5,7 @@ import 'package:invoiceninja/ui/app/form_card.dart';
import 'package:invoiceninja/ui/app/progress_button.dart';
import 'package:invoiceninja/ui/product/edit/product_edit_vm.dart';
import 'package:invoiceninja/utils/localization.dart';
import '../../app/save_icon_button.dart';
import 'package:invoiceninja/ui/app/save_icon_button.dart';
class ProductEdit extends StatefulWidget {
final ProductEditVM viewModel;

View File

@ -119,6 +119,8 @@ class AppLocalization {
'quote_number': 'Quote Number',
'quote_date': 'Quote Date',
'valid_until': 'Valid Until',
'items': 'Items',
'partial': 'Partial/Deposit',
'payment': 'Payment',
'payments': 'Payments',
@ -230,6 +232,9 @@ class AppLocalization {
String get quoteNumber => _localizedValues[locale.languageCode]['quote_number'];
String get quoteDate => _localizedValues[locale.languageCode]['quote_date'];
String get validUntil => _localizedValues[locale.languageCode]['valid_until'];
String get items => _localizedValues[locale.languageCode]['items'];
String get partial => _localizedValues[locale.languageCode]['partial'];
String get payment => _localizedValues[locale.languageCode]['payment'];
String get payments => _localizedValues[locale.languageCode]['payments'];