added comment for payment, changed intent and added amount ui in operations

This commit is contained in:
Arseni
2026-03-12 00:09:38 +03:00
parent ddc2f1facc
commit 13b84e1e0f
26 changed files with 271 additions and 298 deletions

View File

@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pweb/controllers/payments/comment_field.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class PaymentCommentField extends StatelessWidget {
const PaymentCommentField({super.key});
@override
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context)!;
final controller = context.watch<PaymentCommentFieldController>();
return TextField(
controller: controller.textController,
decoration: InputDecoration(
labelText: '${loc.comment} (${loc.optional})',
border: const OutlineInputBorder(),
),
onChanged: controller.handleChanged,
);
}
}

View File

@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pshared/provider/payment/amount.dart';
import 'package:pweb/controllers/payments/comment_field.dart';
import 'package:pweb/pages/dashboard/payouts/comment/field.dart';
class PaymentCommentWidget extends StatelessWidget {
const PaymentCommentWidget({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProxyProvider<
PaymentAmountProvider,
PaymentCommentFieldController
>(
create: (ctx) {
final initialComment = ctx.read<PaymentAmountProvider>().comment;
return PaymentCommentFieldController(initialComment: initialComment);
},
update: (ctx, amountProvider, controller) {
controller!.update(amountProvider);
return controller;
},
child: const PaymentCommentField(),
);
}
}

View File

@@ -5,6 +5,7 @@ import 'package:provider/provider.dart';
import 'package:pweb/controllers/payouts/quotation.dart';
import 'package:pweb/models/dashboard/quote_status_data.dart';
import 'package:pweb/pages/dashboard/payouts/amount/widget.dart';
import 'package:pweb/pages/dashboard/payouts/comment/widget.dart';
import 'package:pweb/pages/dashboard/payouts/fee_payer.dart';
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/card.dart';
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/refresh_section.dart';
@@ -23,7 +24,6 @@ class PaymentFormWidget extends StatelessWidget {
static const double _columnSpacing = 24;
static const double _narrowWidth = 560;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
@@ -66,6 +66,8 @@ class PaymentFormWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const PaymentAmountWidget(),
const SizedBox(height: _mediumSpacing),
const PaymentCommentWidget(),
const SizedBox(height: _smallSpacing),
FeePayerSwitch(
spacing: _smallSpacing,
@@ -104,12 +106,9 @@ class PaymentFormWidget extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
flex: 3,
child: const PaymentAmountWidget(),
),
Expanded(flex: 3, child: const PaymentAmountWidget()),
const SizedBox(width: _columnSpacing),
Expanded(flex: 2, child: quoteCard),
Expanded(flex: 2, child: PaymentCommentWidget()),
],
),
const SizedBox(height: _smallSpacing),
@@ -136,8 +135,9 @@ class PaymentFormWidget extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
autoRefreshSection,
],
quoteCard,
const SizedBox(height: _mediumSpacing),
autoRefreshSection],
),
),
],

View File

@@ -1,6 +1,5 @@
import 'package:pweb/models/payment/multiple_payouts/csv_row.dart';
const String sampleFileName = 'sample.csv';
final List<CsvPayoutRow> sampleRows = [
@@ -11,6 +10,7 @@ final List<CsvPayoutRow> sampleRows = [
expMonth: 12,
expYear: 27,
amount: "500",
comment: "Salary payout",
),
CsvPayoutRow(
pan: "9022****12",
@@ -27,16 +27,26 @@ final List<CsvPayoutRow> sampleRows = [
expMonth: 3,
expYear: 28,
amount: "120",
comment: "Refund",
),
];
String buildSampleCsvContent() {
final rows = <String>[
'pan,first_name,last_name,exp_month,exp_year,amount',
'pan,first_name,last_name,exp_month,exp_year,amount,comment',
...sampleRows.map(
(row) =>
'${row.pan},${row.firstName},${row.lastName},${row.expMonth},${row.expYear},${row.amount}',
'${row.pan},${row.firstName},${row.lastName},${row.expMonth},${row.expYear},${row.amount},${_escapeCsvCell(row.comment)}',
),
];
return rows.join('\n');
}
String _escapeCsvCell(String? value) {
if (value == null || value.isEmpty) return '';
if (!value.contains(',') && !value.contains('"') && !value.contains('\n')) {
return value;
}
final escaped = value.replaceAll('"', '""');
return '"$escaped"';
}

View File

@@ -6,10 +6,7 @@ import 'package:pweb/generated/i18n/app_localizations.dart';
class FileFormatSampleTable extends StatelessWidget {
const FileFormatSampleTable({
super.key,
required this.rows,
});
const FileFormatSampleTable({super.key, required this.rows});
final List<CsvPayoutRow> rows;
@@ -24,6 +21,7 @@ class FileFormatSampleTable extends StatelessWidget {
DataColumn(label: Text(l10n.lastName)),
DataColumn(label: Text(l10n.expiryDate)),
DataColumn(label: Text(l10n.amountColumn)),
DataColumn(label: Text(l10n.commentColumn)),
],
rows: rows.map((row) {
return DataRow(
@@ -35,6 +33,7 @@ class FileFormatSampleTable extends StatelessWidget {
Text('${row.expMonth.toString().padLeft(2, '0')}/${row.expYear}'),
),
DataCell(Text(row.amount)),
DataCell(Text(row.comment ?? '')),
],
);
}).toList(),

View File

@@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pshared/models/payment/type.dart';
import 'package:pshared/models/recipient/recipient.dart';
import 'package:pshared/provider/payment/amount.dart';
import 'package:pweb/widgets/sidebar/destinations.dart';
import 'package:pweb/controllers/payments/page_ui.dart';
@@ -46,6 +49,7 @@ class _PaymentPageState extends State<PaymentPage> {
@override
void dispose() {
context.read<PaymentAmountProvider>().setComment('');
_uiController.dispose();
super.dispose();
}

View File

@@ -4,6 +4,7 @@ import 'package:pshared/models/payment/execution_operation.dart';
import 'package:pweb/utils/report/operations/state_mapper.dart';
import 'package:pweb/pages/report/details/sections/operations/state_chip.dart';
import 'package:pweb/utils/money_display.dart';
import 'package:pweb/utils/report/operations/time_format.dart';
import 'package:pweb/utils/report/operations/title_mapper.dart';
@@ -30,6 +31,7 @@ class OperationHistoryTile extends StatelessWidget {
final operationLabel = operation.label?.trim();
final stateView = resolveStepStateView(context, operation.state);
final completedAt = formatCompletedAt(context, operation.completedAt);
final amount = formatMoneyUi(context, operation.amount);
final canDownload = canDownloadDocument && onDownloadDocument != null;
return Column(
@@ -67,7 +69,14 @@ class OperationHistoryTile extends StatelessWidget {
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
),
const SizedBox(height: 4),
Text(
'${loc.amountColumn}: $amount',
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
if (canDownload) ...[
const SizedBox(height: 8),
TextButton.icon(