Handle quick changes in line items
This commit is contained in:
parent
bf569242c6
commit
3d34cfa06a
|
|
@ -264,8 +264,12 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
),
|
||||
),
|
||||
*/
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TypeAheadFormField<String>(
|
||||
key: ValueKey('__line_item_${index}_name__'),
|
||||
initialValue: lineItems[index].productKey,
|
||||
|
|
@ -308,8 +312,8 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
final product = productState.map[productId];
|
||||
final client =
|
||||
state.clientState.get(invoice.clientId);
|
||||
final currency = state
|
||||
.staticState.currencyMap[client.currencyId];
|
||||
final currency = state.staticState
|
||||
.currencyMap[client.currencyId];
|
||||
|
||||
double cost = product.price;
|
||||
if (company.convertProductExchangeRate &&
|
||||
|
|
@ -326,9 +330,11 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
..cost = item.isTask && item.cost != 0
|
||||
? item.cost
|
||||
: cost
|
||||
..quantity = item.isTask || item.quantity != 0
|
||||
..quantity =
|
||||
item.isTask || item.quantity != 0
|
||||
? item.quantity
|
||||
: viewModel.state.company.defaultQuantity
|
||||
: viewModel.state.company
|
||||
.defaultQuantity
|
||||
? 1
|
||||
: product.quantity
|
||||
..customValue1 = product.customValue1
|
||||
|
|
@ -341,7 +347,8 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
..taxName2 = product.taxName2
|
||||
..taxRate3 = product.taxRate3
|
||||
..taxName3 = product.taxName3);
|
||||
_onChanged(updatedItem, index, debounce: false);
|
||||
_onChanged(updatedItem, index,
|
||||
debounce: false);
|
||||
_updateTable();
|
||||
},
|
||||
);
|
||||
|
|
@ -370,7 +377,8 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
}
|
||||
final updatedItem = item.rebuild((b) => b
|
||||
..productKey = product.productKey
|
||||
..notes = item.isTask ? item.notes : product.notes
|
||||
..notes =
|
||||
item.isTask ? item.notes : product.notes
|
||||
..cost = item.isTask && item.cost != 0
|
||||
? item.cost
|
||||
: cost
|
||||
|
|
@ -403,7 +411,11 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
animationStart: 1,
|
||||
debounceDuration: Duration(seconds: 0),
|
||||
)),
|
||||
Padding(
|
||||
),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: GrowableFormField(
|
||||
key: ValueKey('__line_item_${index}_description__'),
|
||||
|
|
@ -414,9 +426,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.hasCustomField(customField1))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: CustomField(
|
||||
field: customField1,
|
||||
value: lineItems[index].customValue1,
|
||||
|
|
@ -428,9 +445,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.hasCustomField(customField2))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: CustomField(
|
||||
field: customField2,
|
||||
value: lineItems[index].customValue2,
|
||||
|
|
@ -442,9 +464,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.hasCustomField(CustomFieldType.product3))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: CustomField(
|
||||
field: CustomFieldType.product3,
|
||||
value: lineItems[index].customValue3,
|
||||
|
|
@ -456,9 +483,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.hasCustomField(customField4))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: CustomField(
|
||||
field: customField4,
|
||||
value: lineItems[index].customValue4,
|
||||
|
|
@ -470,9 +502,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasTax1)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TaxRateDropdown(
|
||||
onSelected: (taxRate) => _onChanged(
|
||||
lineItems[index].rebuild((b) => b
|
||||
|
|
@ -484,9 +521,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
initialTaxRate: lineItems[index].taxRate1,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasTax2)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TaxRateDropdown(
|
||||
onSelected: (taxRate) => _onChanged(
|
||||
lineItems[index].rebuild((b) => b
|
||||
|
|
@ -498,9 +540,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
initialTaxRate: lineItems[index].taxRate2,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasTax3)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TaxRateDropdown(
|
||||
onSelected: (taxRate) => _onChanged(
|
||||
lineItems[index].rebuild((b) => b
|
||||
|
|
@ -512,7 +559,11 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
initialTaxRate: lineItems[index].taxRate3,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DecoratedFormField(
|
||||
key: ValueKey('__line_item_${index}_cost__'),
|
||||
|
|
@ -530,9 +581,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.enableProductQuantity || widget.isTasks)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DecoratedFormField(
|
||||
key: ValueKey('__line_item_${index}_quantity__'),
|
||||
textAlign: TextAlign.right,
|
||||
|
|
@ -549,9 +605,14 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (company.enableProductDiscount)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
Focus(
|
||||
onFocusChange: (hasFocus) => Debouncer.complete(),
|
||||
skipTraversal: true,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: DecoratedFormField(
|
||||
key: ValueKey('__line_item_${index}_discount__'),
|
||||
textAlign: TextAlign.right,
|
||||
|
|
@ -568,6 +629,7 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
|
|||
onSavePressed: widget.entityViewModel.onSavePressed,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: kTableColumnGap),
|
||||
child: TextFormField(
|
||||
|
|
|
|||
|
|
@ -62,9 +62,14 @@ Completer<Null> errorCompleter(BuildContext context) {
|
|||
|
||||
// https://stackoverflow.com/a/55119208/497368
|
||||
class Debouncer {
|
||||
Debouncer({this.milliseconds = kMillisecondsToDebounceUpdate});
|
||||
Debouncer({
|
||||
this.milliseconds = kMillisecondsToDebounceUpdate,
|
||||
this.sendFirstAction = false,
|
||||
});
|
||||
|
||||
final int milliseconds;
|
||||
final bool sendFirstAction;
|
||||
|
||||
static VoidCallback action;
|
||||
static Timer timer;
|
||||
|
||||
|
|
@ -75,7 +80,11 @@ class Debouncer {
|
|||
}
|
||||
|
||||
if (timer == null) {
|
||||
if (sendFirstAction) {
|
||||
action();
|
||||
} else {
|
||||
Debouncer.action = action;
|
||||
}
|
||||
} else {
|
||||
timer.cancel();
|
||||
Debouncer.action = action;
|
||||
|
|
@ -93,6 +102,7 @@ class Debouncer {
|
|||
static void complete() {
|
||||
if (action != null) {
|
||||
action();
|
||||
action = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue