invoice/lib/ui/payment/view/payment_view.dart

205 lines
8.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_selectors.dart';
import 'package:url_launcher/url_launcher.dart';
// Project imports:
import 'package:invoiceninja_flutter/colors.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/FieldGrid.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/bottom_buttons.dart';
import 'package:invoiceninja_flutter/ui/app/entities/entity_list_tile.dart';
import 'package:invoiceninja_flutter/ui/app/entity_header.dart';
import 'package:invoiceninja_flutter/ui/app/icon_message.dart';
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
import 'package:invoiceninja_flutter/ui/app/view_scaffold.dart';
import 'package:invoiceninja_flutter/ui/payment/view/payment_view_vm.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class PaymentView extends StatefulWidget {
const PaymentView({
Key key,
@required this.viewModel,
@required this.isFilter,
}) : super(key: key);
final PaymentViewVM viewModel;
final bool isFilter;
@override
_PaymentViewState createState() => new _PaymentViewState();
}
class _PaymentViewState extends State<PaymentView> {
@override
Widget build(BuildContext context) {
final viewModel = widget.viewModel;
final payment = viewModel.payment;
final state = StoreProvider.of<AppState>(context).state;
final client = state.clientState.map[payment.clientId] ??
ClientEntity(id: payment.clientId);
final transaction = state.transactionState.get(payment.transactionId);
final localization = AppLocalization.of(context);
final companyGateway =
state.companyGatewayState.get(payment.companyGatewayId);
final companyGatewayLink = GatewayEntity.getPaymentUrl(
gatewayId: companyGateway.gatewayId,
transactionReference: payment.transactionReference,
);
final fields = <String, String>{};
/*
fields[PaymentFields.paymentStatusId] =
localization.lookup('payment_status_${payment.statusId}');
*/
if (payment.date.isNotEmpty) {
fields[PaymentFields.date] = formatDate(payment.date, context);
}
if ((payment.typeId ?? '').isNotEmpty) {
final paymentType = state.staticState.paymentTypeMap[payment.typeId];
if (paymentType != null) {
fields[PaymentFields.typeId] = paymentType.name;
}
}
if (payment.transactionReference.isNotEmpty) {
fields[PaymentFields.transactionReference] = payment.transactionReference;
}
if (payment.refunded != 0) {
fields[PaymentFields.refunded] =
formatNumber(payment.refunded, context, clientId: client.id);
}
return ViewScaffold(
isFilter: widget.isFilter,
entity: payment,
body: Builder(
builder: (BuildContext context) {
return RefreshIndicator(
onRefresh: () => viewModel.onRefreshed(context),
child: Column(
children: <Widget>[
Expanded(
child: ScrollableListView(
children: <Widget>[
EntityHeader(
entity: payment,
statusColor:
PaymentStatusColors(state.prefState.colorThemeModel)
.colors[payment.statusId],
statusLabel: localization
.lookup('payment_status_${payment.statusId}'),
label: localization.amount,
value: formatNumber(
payment.amount - payment.refunded, context,
clientId: client.id),
secondLabel: localization.applied,
secondValue: formatNumber(payment.applied, context,
clientId: client.id),
),
ListDivider(),
EntityListTile(
isFilter: widget.isFilter,
entity: client,
subtitle: client.primaryContact.email,
),
for (final paymentable in payment.invoicePaymentables)
EntityListTile(
isFilter: widget.isFilter,
entity: state.invoiceState.map[paymentable.invoiceId],
subtitle: formatNumber(paymentable.amount, context,
clientId: payment.clientId) +
'' +
formatDate(
convertTimestampToDateString(
paymentable.createdAt),
context),
),
for (final paymentable in payment.creditPaymentables)
EntityListTile(
isFilter: widget.isFilter,
entity: state.creditState.map[paymentable.creditId],
subtitle: formatNumber(paymentable.amount, context,
clientId: payment.clientId) +
'' +
formatDate(
convertTimestampToDateString(
paymentable.createdAt),
context),
),
if ((payment.companyGatewayId ?? '').isNotEmpty) ...[
ListTile(
title: Text(
'${localization.gateway} ${companyGateway.label}'),
onTap: companyGatewayLink != null
? () => launchUrl(Uri.parse(companyGatewayLink))
: null,
leading: IgnorePointer(
child: IconButton(
icon: Icon(Icons.payment),
onPressed: () => null,
),
),
trailing: companyGatewayLink != null
? IgnorePointer(
child: IconButton(
icon: Icon(Icons.open_in_new),
onPressed: () => null,
),
)
: null,
),
ListDivider(),
],
if (payment.transactionId.isNotEmpty)
EntityListTile(
isFilter: widget.isFilter,
entity: transaction,
),
payment.privateNotes != null &&
payment.privateNotes.isNotEmpty
? Column(
children: <Widget>[
IconMessage(payment.privateNotes,
copyToClipboard: true),
Container(
color: Theme.of(context).cardColor,
height: 12.0,
),
],
)
: Container(),
FieldGrid(fields),
],
),
),
BottomButtons(
entity: payment,
action1: state.company.enableApplyingPayments
? EntityAction.applyPayment
: EntityAction.sendEmail,
action1Enabled: state.company.enableApplyingPayments
? payment.applied < payment.amount &&
memoizedHasActiveUnpaidInvoices(
payment.clientId,
state.invoiceState.map,
)
: true,
action2: EntityAction.refundPayment,
action2Enabled: payment.refunded < payment.amount,
),
],
),
);
},
),
);
}
}