diff --git a/lib/redux/client/client_selectors.dart b/lib/redux/client/client_selectors.dart index e76178fe3..8ccb2c023 100644 --- a/lib/redux/client/client_selectors.dart +++ b/lib/redux/client/client_selectors.dart @@ -162,6 +162,40 @@ SettingsEntity getVendorSettings(AppState state, VendorEntity vendor) { ); } +var memoizedGetClientUnappliedPayments = memo2( + (String clientId, BuiltMap paymentMap) => + getClientUnappliedPayments(clientId: clientId, paymentMap: paymentMap)); + +double getClientUnappliedPayments( + {String clientId, BuiltMap paymentMap}) { + double amount = 0; + + paymentMap.forEach((paymentId, payment) { + if (payment.clientId == clientId) { + amount += payment.amount - payment.applied; + } + }); + + return amount; +} + +var memoizedGetClientAvailableCredits = memo2( + (String clientId, BuiltMap creditMap) => + getClientAvailableCredits(clientId: clientId, creditMap: creditMap)); + +double getClientAvailableCredits( + {String clientId, BuiltMap creditMap}) { + double amount = 0; + + creditMap.forEach((creditId, credit) { + if (credit.clientId == clientId) { + amount += credit.balance; + } + }); + + return amount; +} + bool hasClientChanges( ClientEntity client, BuiltMap clientMap) => client.isNew ? client.isChanged : client != clientMap[client.id]; diff --git a/lib/ui/client/view/client_view_fullwidth.dart b/lib/ui/client/view/client_view_fullwidth.dart index cf989810f..eece89c65 100644 --- a/lib/ui/client/view/client_view_fullwidth.dart +++ b/lib/ui/client/view/client_view_fullwidth.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; +import 'package:invoiceninja_flutter/redux/client/client_selectors.dart'; import 'package:invoiceninja_flutter/ui/app/copy_to_clipboard.dart'; import 'package:invoiceninja_flutter/ui/app/entity_header.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -70,6 +71,11 @@ class _ClientViewFullwidthState extends State !state.uiState.isEditing && state.prefState.isModuleTable; + final availableCredits = + memoizedGetClientAvailableCredits(client.id, state.creditState.map); + final unappliedPayments = + memoizedGetClientUnappliedPayments(client.id, state.paymentState.map); + return LayoutBuilder(builder: (context, layout) { final minHeight = layout.maxHeight - (kMobileDialogPadding * 2) - 43; return Row( @@ -94,6 +100,16 @@ class _ClientViewFullwidthState extends State style: Theme.of(context).textTheme.headline6, ), SizedBox(height: 8), + if (availableCredits != 0) + Text(localization.credit + + ': ' + + formatNumber(availableCredits, context, + clientId: client.id)), + if (unappliedPayments != 0) + Text(localization.payments + + ': ' + + formatNumber(unappliedPayments, context, + clientId: client.id)), if (client.idNumber.isNotEmpty) Padding( padding: const EdgeInsets.only(bottom: 1),