diff --git a/lib/data/models/project_model.dart b/lib/data/models/project_model.dart index 0e03420437..9c30964b2a 100644 --- a/lib/data/models/project_model.dart +++ b/lib/data/models/project_model.dart @@ -338,8 +338,8 @@ abstract class ProjectEntity extends Object return response; } - bool matchesName(String filter) => - name.toLowerCase().contains(filter.toLowerCase()); + bool matchesName(String? filter) => + name.toLowerCase().contains((filter ?? '').toLowerCase()); @override bool matchesFilter(String? filter) { diff --git a/lib/data/models/task_model.dart b/lib/data/models/task_model.dart index 803231a398..986e25655b 100644 --- a/lib/data/models/task_model.dart +++ b/lib/data/models/task_model.dart @@ -810,6 +810,15 @@ abstract class TaskEntity extends Object .toLowerCase() .compareTo(userB.fullName.toLowerCase()); break; + case TaskFields.isInvoiced: + response = taskB.isInvoiced ? 1 : -1; + break; + case TaskFields.isDeleted: + response = taskB.isDeleted == true ? 1 : -1; + break; + case TaskFields.isRunning: + response = taskB.isRunning ? 1 : -1; + break; case TaskFields.status: final taskAStatus = taskA.isRunning ? -1 diff --git a/lib/redux/client/client_actions.dart b/lib/redux/client/client_actions.dart index 5537851320..5038997dfa 100644 --- a/lib/redux/client/client_actions.dart +++ b/lib/redux/client/client_actions.dart @@ -562,7 +562,7 @@ void handleClientAction(BuildContext? context, List clients, ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -570,6 +570,9 @@ void handleClientAction(BuildContext? context, List clients, entityId: client.id, ), ); + if (addedComment == true) { + store.dispatch(LoadClient(clientId: client.id)); + } break; default: print('## Error: action $action not handled in client_actions'); diff --git a/lib/redux/credit/credit_actions.dart b/lib/redux/credit/credit_actions.dart index 868c244a8d..83e7e2f51b 100644 --- a/lib/redux/credit/credit_actions.dart +++ b/lib/redux/credit/credit_actions.dart @@ -756,7 +756,7 @@ Future handleCreditAction(BuildContext context, List credits, } break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -764,6 +764,9 @@ Future handleCreditAction(BuildContext context, List credits, entityId: credit.id, ), ); + if (addedComment == true) { + store.dispatch(LoadCredit(creditId: credit.id)); + } break; default: print('## ERROR: unhandled action $action in credit_actions'); diff --git a/lib/redux/expense/expense_actions.dart b/lib/redux/expense/expense_actions.dart index 2861bcf00b..dd2f84838b 100644 --- a/lib/redux/expense/expense_actions.dart +++ b/lib/redux/expense/expense_actions.dart @@ -254,8 +254,8 @@ class FilterExpensesByCustom4 implements PersistUI { final String value; } -void handleExpenseAction( - BuildContext context, List expenses, EntityAction? action) { +void handleExpenseAction(BuildContext context, List expenses, + EntityAction? action) async { final store = StoreProvider.of(context); final state = store.state; final localization = AppLocalization.of(context); @@ -398,7 +398,7 @@ void handleExpenseAction( } break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -406,6 +406,9 @@ void handleExpenseAction( entityId: expense.id, ), ); + if (addedComment == true) { + store.dispatch(LoadExpense(expenseId: expense.id)); + } break; default: print('## ERROR: unhandled action $action in expense_actions'); diff --git a/lib/redux/invoice/invoice_actions.dart b/lib/redux/invoice/invoice_actions.dart index 5ee6ba5ea0..1d76a93085 100644 --- a/lib/redux/invoice/invoice_actions.dart +++ b/lib/redux/invoice/invoice_actions.dart @@ -884,7 +884,7 @@ void handleInvoiceAction(BuildContext? context, List invoices, ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -892,6 +892,9 @@ void handleInvoiceAction(BuildContext? context, List invoices, entityId: invoice.id, ), ); + if (addedComment == true) { + store.dispatch(LoadInvoice(invoiceId: invoice.id)); + } break; case EntityAction.more: showEntityActionsDialog( diff --git a/lib/redux/invoice/invoice_selectors.dart b/lib/redux/invoice/invoice_selectors.dart index d6d1ff4629..77b0f748ad 100644 --- a/lib/redux/invoice/invoice_selectors.dart +++ b/lib/redux/invoice/invoice_selectors.dart @@ -119,12 +119,13 @@ List dropdownInvoiceSelector( return list; } -var memoizedFilteredInvoiceList = memo9((SelectionState selectionState, +var memoizedFilteredInvoiceList = memo10((SelectionState selectionState, BuiltMap invoiceMap, BuiltList invoiceList, BuiltMap clientMap, BuiltMap vendorMap, BuiltMap paymentMap, + BuiltMap projectMap, ListUIState invoiceListState, BuiltMap userMap, String? recurringPrefix) => @@ -135,6 +136,7 @@ var memoizedFilteredInvoiceList = memo9((SelectionState selectionState, clientMap, vendorMap, paymentMap, + projectMap, invoiceListState, userMap, recurringPrefix, @@ -147,6 +149,7 @@ List filteredInvoicesSelector( BuiltMap clientMap, BuiltMap vendorMap, BuiltMap paymentMap, + BuiltMap projectMap, ListUIState invoiceListState, BuiltMap userMap, String? recurringPrefix, @@ -170,6 +173,8 @@ List filteredInvoicesSelector( final invoice = invoiceMap[invoiceId]!; final client = clientMap[invoice.clientId] ?? ClientEntity(id: invoice.clientId); + final project = + projectMap[invoice.projectId] ?? ProjectEntity(id: invoice.projectId); if (invoice.id == selectionState.selectedId) { return true; @@ -223,7 +228,8 @@ List filteredInvoicesSelector( return false; } if (!invoice.matchesFilter(invoiceListState.filter) && - !client.matchesNameOrEmail(invoiceListState.filter)) { + !client.matchesNameOrEmail(invoiceListState.filter) && + !project.matchesName(invoiceListState.filter)) { return false; } if (invoiceListState.custom1Filters.isNotEmpty && diff --git a/lib/redux/payment/payment_actions.dart b/lib/redux/payment/payment_actions.dart index c0a7ed6aca..205c59a5ab 100644 --- a/lib/redux/payment/payment_actions.dart +++ b/lib/redux/payment/payment_actions.dart @@ -350,8 +350,8 @@ class UpdatePaymentTab implements PersistUI { final int? tabIndex; } -void handlePaymentAction( - BuildContext? context, List payments, EntityAction? action) { +void handlePaymentAction(BuildContext? context, List payments, + EntityAction? action) async { if (payments.isEmpty) { return; } @@ -471,7 +471,7 @@ void handlePaymentAction( ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -479,6 +479,9 @@ void handlePaymentAction( entityId: payment.id, ), ); + if (addedComment == true) { + store.dispatch(LoadPayment(paymentId: payment.id)); + } break; default: print('## Error: action $action not handled in client_actions'); diff --git a/lib/redux/project/project_actions.dart b/lib/redux/project/project_actions.dart index 1912e3c42e..46cbf23034 100644 --- a/lib/redux/project/project_actions.dart +++ b/lib/redux/project/project_actions.dart @@ -252,8 +252,8 @@ class FilterProjectsByCustom4 implements PersistUI { final String value; } -void handleProjectAction( - BuildContext? context, List projects, EntityAction? action) { +void handleProjectAction(BuildContext? context, List projects, + EntityAction? action) async { if (projects.isEmpty) { return; } @@ -401,7 +401,7 @@ void handleProjectAction( ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -409,6 +409,9 @@ void handleProjectAction( entityId: project.id, ), ); + if (addedComment == true) { + store.dispatch(LoadProject(projectId: project.id)); + } break; default: print('## Error: action $action not handled in project_actions'); diff --git a/lib/redux/purchase_order/purchase_order_actions.dart b/lib/redux/purchase_order/purchase_order_actions.dart index 64ead888cb..d59afc59ed 100644 --- a/lib/redux/purchase_order/purchase_order_actions.dart +++ b/lib/redux/purchase_order/purchase_order_actions.dart @@ -880,7 +880,7 @@ void handlePurchaseOrderAction(BuildContext? context, ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -888,6 +888,9 @@ void handlePurchaseOrderAction(BuildContext? context, entityId: purchaseOrder.id, ), ); + if (addedComment == true) { + store.dispatch(LoadPurchaseOrder(purchaseOrderId: purchaseOrder.id)); + } break; default: print('## ERROR: unhandled action $action in purchase_order_actions'); diff --git a/lib/redux/quote/quote_actions.dart b/lib/redux/quote/quote_actions.dart index d22ec1f98d..1ff407c47a 100644 --- a/lib/redux/quote/quote_actions.dart +++ b/lib/redux/quote/quote_actions.dart @@ -810,7 +810,7 @@ Future handleQuoteAction( } break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -818,6 +818,10 @@ Future handleQuoteAction( entityId: quote.id, ), ); + if (addedComment == true) { + store.dispatch(LoadQuote(quoteId: quote.id)); + } + break; default: print('## ERROR: unhandled action $action in quote_actions'); diff --git a/lib/redux/recurring_expense/recurring_expense_actions.dart b/lib/redux/recurring_expense/recurring_expense_actions.dart index a4e09ddce6..40e3e00090 100644 --- a/lib/redux/recurring_expense/recurring_expense_actions.dart +++ b/lib/redux/recurring_expense/recurring_expense_actions.dart @@ -357,7 +357,7 @@ class SaveRecurringExpenseDocumentFailure implements StopSaving { } void handleRecurringExpenseAction(BuildContext? context, - List recurringExpenses, EntityAction? action) { + List recurringExpenses, EntityAction? action) async { if (recurringExpenses.isEmpty) { return; } @@ -461,7 +461,7 @@ void handleRecurringExpenseAction(BuildContext? context, } break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -469,6 +469,11 @@ void handleRecurringExpenseAction(BuildContext? context, entityId: recurringExpense.id, ), ); + if (addedComment == true) { + store.dispatch( + LoadRecurringExpense(recurringExpenseId: recurringExpense.id)); + } + break; default: print('## ERROR: unhandled action $action in recurring_expense_actions'); diff --git a/lib/redux/recurring_invoice/recurring_invoice_actions.dart b/lib/redux/recurring_invoice/recurring_invoice_actions.dart index 8ce147a42e..82afbe0b67 100644 --- a/lib/redux/recurring_invoice/recurring_invoice_actions.dart +++ b/lib/redux/recurring_invoice/recurring_invoice_actions.dart @@ -728,7 +728,7 @@ void handleRecurringInvoiceAction(BuildContext? context, )); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -736,6 +736,10 @@ void handleRecurringInvoiceAction(BuildContext? context, entityId: recurringInvoice.id, ), ); + if (addedComment == true) { + store.dispatch( + LoadRecurringInvoice(recurringInvoiceId: recurringInvoice.id)); + } break; default: print( diff --git a/lib/redux/task/task_actions.dart b/lib/redux/task/task_actions.dart index 68c46636f6..be9f469b85 100644 --- a/lib/redux/task/task_actions.dart +++ b/lib/redux/task/task_actions.dart @@ -353,7 +353,7 @@ class FilterTasksByCustom4 implements PersistUI { class UpdateKanban {} void handleTaskAction( - BuildContext? context, List tasks, EntityAction? action) { + BuildContext? context, List tasks, EntityAction? action) async { if (tasks.isEmpty) { return; } @@ -555,7 +555,7 @@ void handleTaskAction( ); break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -563,6 +563,9 @@ void handleTaskAction( entityId: task.id, ), ); + if (addedComment == true) { + store.dispatch(LoadTask(taskId: task.id)); + } break; default: print('## ERROR: unhandled action $action in task_actions'); diff --git a/lib/redux/vendor/vendor_actions.dart b/lib/redux/vendor/vendor_actions.dart index 3daacfa364..0c0b3f4bb8 100644 --- a/lib/redux/vendor/vendor_actions.dart +++ b/lib/redux/vendor/vendor_actions.dart @@ -283,8 +283,8 @@ class FilterVendorsByCustom4 implements PersistUI { final String value; } -void handleVendorAction( - BuildContext? context, List vendors, EntityAction? action) { +void handleVendorAction(BuildContext? context, List vendors, + EntityAction? action) async { if (vendors.isEmpty) { return; } @@ -397,7 +397,7 @@ void handleVendorAction( } break; case EntityAction.addComment: - showDialog( + final addedComment = await showDialog( context: navigatorKey.currentContext!, barrierDismissible: false, builder: (context) => AddCommentDialog( @@ -405,6 +405,9 @@ void handleVendorAction( entityId: vendor.id, ), ); + if (addedComment == true) { + store.dispatch(LoadVendor(vendorId: vendor.id)); + } break; default: print('## ERROR: unhandled action $action in vendor_actions'); diff --git a/lib/ui/client/client_presenter.dart b/lib/ui/client/client_presenter.dart index 32accb2517..ec23d384c6 100644 --- a/lib/ui/client/client_presenter.dart +++ b/lib/ui/client/client_presenter.dart @@ -31,6 +31,8 @@ class ClientPresenter extends EntityPresenter { return [ ...getDefaultTableFields(userCompany), ...EntityPresenter.getBaseFields(), + ClientFields.city, + ClientFields.postalCode, ClientFields.address1, ClientFields.address2, ClientFields.country, @@ -93,6 +95,10 @@ class ClientPresenter extends EntityPresenter { return Text(client!.number); case ClientFields.idNumber: return Text(client!.idNumber); + case ClientFields.city: + return Text(client!.city); + case ClientFields.postalCode: + return Text(client!.postalCode); case ClientFields.lastLoginAt: return Text(client!.lastLogin == 0 ? '' diff --git a/lib/ui/invoice/invoice_list_vm.dart b/lib/ui/invoice/invoice_list_vm.dart index 5166faabaa..3a665c328a 100644 --- a/lib/ui/invoice/invoice_list_vm.dart +++ b/lib/ui/invoice/invoice_list_vm.dart @@ -137,6 +137,7 @@ class InvoiceListVM extends EntityListVM { state.clientState.map, state.vendorState.map, state.paymentState.map, + state.projectState.map, state.invoiceListState, state.userState.map, state.company.settings.recurringNumberPrefix, diff --git a/lib/ui/invoice/invoice_screen_vm.dart b/lib/ui/invoice/invoice_screen_vm.dart index 84d1a498a9..26ac38c413 100644 --- a/lib/ui/invoice/invoice_screen_vm.dart +++ b/lib/ui/invoice/invoice_screen_vm.dart @@ -54,6 +54,7 @@ class InvoiceScreenVM { state.clientState.map, state.vendorState.map, state.paymentState.map, + state.projectState.map, state.invoiceListState, state.userState.map, state.company.settings.recurringNumberPrefix, diff --git a/lib/utils/dialogs.dart b/lib/utils/dialogs.dart index b8c28df611..4ba8a3cab2 100644 --- a/lib/utils/dialogs.dart +++ b/lib/utils/dialogs.dart @@ -1024,7 +1024,7 @@ class _AddCommentDialogState extends State { : [ TextButton( onPressed: () { - Navigator.of(context).pop(); + Navigator.of(context).pop(false); }, child: Text( localization.cancel.toUpperCase(), @@ -1049,7 +1049,7 @@ class _AddCommentDialogState extends State { .post(url, credentials.token, data: jsonEncode(data)) .then((response) async { - Navigator.of(navigatorKey.currentContext!).pop(); + Navigator.of(navigatorKey.currentContext!).pop(true); showToast(localization.addedComment); }).catchError((error) { showErrorDialog(message: error);