diff --git a/lib/redux/payment/payment_selectors.dart b/lib/redux/payment/payment_selectors.dart index 053fef603..2181a861f 100644 --- a/lib/redux/payment/payment_selectors.dart +++ b/lib/redux/payment/payment_selectors.dart @@ -1,15 +1,16 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:memoize/memoize.dart'; import 'package:built_collection/built_collection.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart'; -ClientEntity paymentClientSelector(int paymentId, BuildContext context) { - final state = StoreProvider.of(context).state; +InvoiceEntity paymentInvoiceSelector(int paymentId, AppState state) { final payment = state.paymentState.map[paymentId]; - final invoice = state.invoiceState.map[payment.invoiceId]; + return state.invoiceState.map[payment.invoiceId]; +} + +ClientEntity paymentClientSelector(int paymentId, AppState state) { + final invoice = paymentInvoiceSelector(paymentId, state); return state.clientState.map[invoice.clientId]; } diff --git a/lib/ui/payment/edit/payment_edit_vm.dart b/lib/ui/payment/edit/payment_edit_vm.dart index 13d774d70..8da77deb9 100644 --- a/lib/ui/payment/edit/payment_edit_vm.dart +++ b/lib/ui/payment/edit/payment_edit_vm.dart @@ -26,9 +26,9 @@ class PaymentEditScreen extends StatelessWidget { converter: (Store store) { return PaymentEditVM.fromStore(store); }, - builder: (context, vm) { + builder: (context, viewModel) { return PaymentEdit( - viewModel: vm, + viewModel: viewModel, ); }, ); diff --git a/lib/ui/payment/view/payment_view.dart b/lib/ui/payment/view/payment_view.dart index 08c39c8f1..8da97539c 100644 --- a/lib/ui/payment/view/payment_view.dart +++ b/lib/ui/payment/view/payment_view.dart @@ -1,5 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart'; import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart'; import 'package:invoiceninja_flutter/ui/app/icon_message.dart'; @@ -26,6 +29,9 @@ class _PaymentViewState extends State { Widget build(BuildContext context) { final viewModel = widget.viewModel; final payment = viewModel.payment; + final state = StoreProvider.of(context).state; + final client = paymentClientSelector(payment.id, state); + final invoice = paymentInvoiceSelector(payment.id, state); final localization = AppLocalization.of(context); return Scaffold( @@ -54,19 +60,42 @@ class _PaymentViewState extends State { ? TwoValueHeader( label1: localization.amount, value1: formatNumber(payment.amount, context, - clientId: - paymentClientSelector(payment.id, context).id), + clientId: client.id), label2: localization.refunded, value2: formatNumber(payment.refunded, context, - clientId: - paymentClientSelector(payment.id, context).id), + clientId: client.id), ) : OneValueHeader( label: localization.amount, value: formatNumber(payment.amount, context, - clientId: - paymentClientSelector(payment.id, context).id), + clientId: client.id), ), + Material( + color: Theme.of(context).canvasColor, + child: ListTile( + title: Text(client.displayName ?? ''), + leading: Icon(FontAwesomeIcons.users, size: 18.0), + trailing: Icon(Icons.navigate_next), + onTap: () => viewModel.onTapClient(context), + ), + ), + Container( + color: Theme.of(context).backgroundColor, + height: 12.0, + ), + Material( + color: Theme.of(context).canvasColor, + child: ListTile( + title: Text('${localization.invoice} ${invoice.invoiceNumber}'), + leading: Icon(FontAwesomeIcons.filePdfO, size: 18.0), + trailing: Icon(Icons.navigate_next), + onTap: () => viewModel.onTapInvoice(context), + ), + ), + Container( + color: Theme.of(context).backgroundColor, + height: 12.0, + ), payment.privateNotes != null && payment.privateNotes.isNotEmpty ? IconMessage(payment.privateNotes) : Container(), diff --git a/lib/ui/payment/view/payment_view_vm.dart b/lib/ui/payment/view/payment_view_vm.dart index 63470787f..507b96450 100644 --- a/lib/ui/payment/view/payment_view_vm.dart +++ b/lib/ui/payment/view/payment_view_vm.dart @@ -1,5 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/redux/client/client_actions.dart'; +import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart'; +import 'package:invoiceninja_flutter/redux/payment/payment_selectors.dart'; import 'package:invoiceninja_flutter/utils/completers.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:redux/redux.dart'; @@ -35,6 +38,8 @@ class PaymentViewVM { final CompanyEntity company; final Function(BuildContext, EntityAction) onActionSelected; final Function(BuildContext) onEditPressed; + final Function(BuildContext) onTapInvoice; + final Function(BuildContext) onTapClient; final bool isSaving; final bool isLoading; final bool isDirty; @@ -44,6 +49,8 @@ class PaymentViewVM { @required this.company, @required this.onActionSelected, @required this.onEditPressed, + @required this.onTapClient, + @required this.onTapInvoice, @required this.isSaving, @required this.isLoading, @required this.isDirty, @@ -52,6 +59,7 @@ class PaymentViewVM { factory PaymentViewVM.fromStore(Store store) { final state = store.state; final payment = state.paymentState.map[state.paymentUIState.selectedId]; + final client = paymentClientSelector(payment.id, state); return PaymentViewVM( company: state.selectedCompany, @@ -62,6 +70,10 @@ class PaymentViewVM { onEditPressed: (BuildContext context) { store.dispatch(EditPayment(payment: payment, context: context)); }, + onTapClient: (context) => + store.dispatch(ViewClient(clientId: client.id, context: context)), + onTapInvoice: (context) => store.dispatch( + ViewInvoice(invoiceId: payment.invoiceId, context: context)), onActionSelected: (BuildContext context, EntityAction action) { final localization = AppLocalization.of(context); switch (action) { diff --git a/stubs/ui/stub/edit/stub_edit_vm b/stubs/ui/stub/edit/stub_edit_vm index 3e50ae559..b5f30c4f4 100644 --- a/stubs/ui/stub/edit/stub_edit_vm +++ b/stubs/ui/stub/edit/stub_edit_vm @@ -21,9 +21,9 @@ class StubEditScreen extends StatelessWidget { converter: (Store store) { return StubEditVM.fromStore(store); }, - builder: (context, vm) { + builder: (context, viewModel) { return StubEdit( - viewModel: vm, + viewModel: viewModel, ); }, );