reports page
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
import 'package:pweb/widgets/sidebar/destinations.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -7,21 +10,30 @@ class UploadHistoryHeader extends StatelessWidget {
|
||||
const UploadHistoryHeader({
|
||||
super.key,
|
||||
required this.theme,
|
||||
required this.l10n,
|
||||
});
|
||||
|
||||
final ThemeData theme;
|
||||
final AppLocalizations l10n;
|
||||
|
||||
static const double _smallBox = 5;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10 = AppLocalizations.of(context)!;
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Icon(Icons.history),
|
||||
const SizedBox(width: _smallBox),
|
||||
Text(l10n.uploadHistory, style: theme.textTheme.bodyLarge),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.history),
|
||||
const SizedBox(width: _smallBox),
|
||||
Text(l10.uploadHistory, style: theme.textTheme.bodyLarge),
|
||||
],
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => context.goToPayout(PayoutDestination.reports),
|
||||
icon: const Icon(Icons.open_in_new, size: 16),
|
||||
label: Text(l10.viewWholeHistory),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class StatusView {
|
||||
final String label;
|
||||
final Color color;
|
||||
|
||||
const StatusView(this.label, this.color);
|
||||
}
|
||||
|
||||
StatusView statusView(AppLocalizations l10n, String? raw) {
|
||||
final trimmed = (raw ?? '').trim();
|
||||
final upper = trimmed.toUpperCase();
|
||||
final normalized = upper.startsWith('PAYMENT_STATE_')
|
||||
? upper.substring('PAYMENT_STATE_'.length)
|
||||
: upper;
|
||||
|
||||
switch (normalized) {
|
||||
case 'SETTLED':
|
||||
return StatusView(l10n.paymentStatusPending, Colors.yellow);
|
||||
case 'SUCCESS':
|
||||
return StatusView(l10n.paymentStatusSuccessful, Colors.green);
|
||||
case 'FUNDS_RESERVED':
|
||||
return StatusView(l10n.paymentStatusReserved, Colors.blue);
|
||||
case 'ACCEPTED':
|
||||
return StatusView(l10n.paymentStatusProcessing, Colors.yellow);
|
||||
case 'SUBMITTED':
|
||||
return StatusView(l10n.paymentStatusProcessing, Colors.blue);
|
||||
case 'FAILED':
|
||||
return StatusView(l10n.paymentStatusFailed, Colors.red);
|
||||
case 'CANCELLED':
|
||||
return StatusView(l10n.paymentStatusCancelled, Colors.grey);
|
||||
case 'UNSPECIFIED':
|
||||
case '':
|
||||
default:
|
||||
return StatusView(l10n.paymentStatusPending, Colors.grey);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/helpers.dart';
|
||||
|
||||
|
||||
class HistoryStatusBadge extends StatelessWidget {
|
||||
const HistoryStatusBadge({
|
||||
super.key,
|
||||
required this.statusView,
|
||||
});
|
||||
|
||||
final StatusView statusView;
|
||||
|
||||
static const double _radius = 6;
|
||||
static const double _statusBgOpacity = 0.12;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: statusView.color.withValues(alpha: _statusBgOpacity),
|
||||
borderRadius: BorderRadius.circular(_radius),
|
||||
),
|
||||
child: Text(
|
||||
statusView.label,
|
||||
style: TextStyle(
|
||||
color: statusView.color,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:pshared/models/payment/payment.dart';
|
||||
|
||||
import 'package:pweb/controllers/upload_history_table.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/helpers.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/status_badge.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class UploadHistoryTable extends StatelessWidget {
|
||||
const UploadHistoryTable({
|
||||
super.key,
|
||||
required this.items,
|
||||
required this.dateFormat,
|
||||
required this.l10n,
|
||||
});
|
||||
|
||||
final List<Payment> items;
|
||||
final DateFormat dateFormat;
|
||||
final AppLocalizations l10n;
|
||||
|
||||
static const int _maxVisibleItems = 10;
|
||||
static const UploadHistoryTableController _controller =
|
||||
UploadHistoryTableController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final visibleItems = items.take(_maxVisibleItems).toList(growable: false);
|
||||
|
||||
return DataTable(
|
||||
columns: [
|
||||
DataColumn(label: Text(l10n.fileNameColumn)),
|
||||
DataColumn(label: Text(l10n.rowsColumn)),
|
||||
DataColumn(label: Text(l10n.dateColumn)),
|
||||
DataColumn(label: Text(l10n.amountColumn)),
|
||||
DataColumn(label: Text(l10n.statusColumn)),
|
||||
],
|
||||
rows: visibleItems.map((payment) {
|
||||
final metadata = payment.metadata;
|
||||
final status = statusView(l10n, payment.state);
|
||||
final fileName = metadata?['upload_filename'];
|
||||
final fileNameText =
|
||||
(fileName == null || fileName.isEmpty) ? '-' : fileName;
|
||||
final rows = metadata?['upload_rows'];
|
||||
final rowsText = (rows == null || rows.isEmpty) ? '-' : rows;
|
||||
final createdAt = payment.createdAt;
|
||||
final dateText = createdAt == null
|
||||
? '-'
|
||||
: dateFormat.format(createdAt.toLocal());
|
||||
final amountText = _controller.amountText(payment);
|
||||
|
||||
return DataRow(
|
||||
cells: [
|
||||
DataCell(Text(fileNameText)),
|
||||
DataCell(Text(rowsText)),
|
||||
DataCell(Text(dateText)),
|
||||
DataCell(Text(amountText)),
|
||||
DataCell(HistoryStatusBadge(statusView: status)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/operation.dart';
|
||||
import 'package:pshared/provider/payment/payments.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/header.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/table.dart';
|
||||
import 'package:pweb/controllers/recent_payments.dart';
|
||||
import 'package:pweb/pages/report/cards/column.dart';
|
||||
import 'package:pweb/utils/report/payment_mapper.dart';
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
@@ -17,61 +19,49 @@ class UploadHistorySection extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final provider = context.watch<PaymentsProvider>();
|
||||
final theme = Theme.of(context);
|
||||
final l10 = AppLocalizations.of(context)!;
|
||||
final dateFormat = DateFormat.yMMMd().add_Hm();
|
||||
|
||||
if (provider.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (provider.error != null) {
|
||||
return Text(
|
||||
l10.notificationError(provider.error ?? l10.noErrorInformation),
|
||||
);
|
||||
}
|
||||
final items = List.of(provider.payments);
|
||||
items.sort((a, b) {
|
||||
final left = a.createdAt;
|
||||
final right = b.createdAt;
|
||||
if (left == null && right == null) return 0;
|
||||
if (left == null) return 1;
|
||||
if (right == null) return -1;
|
||||
return right.compareTo(left);
|
||||
});
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
UploadHistoryHeader(theme: theme, l10n: l10),
|
||||
const SizedBox(height: 8),
|
||||
if (items.isEmpty)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
l10.walletHistoryEmpty,
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
)
|
||||
else ...[
|
||||
UploadHistoryTable(
|
||||
items: items,
|
||||
dateFormat: dateFormat,
|
||||
l10n: l10,
|
||||
),
|
||||
//TODO redirect to Reports page
|
||||
// if (hasMore) ...[
|
||||
// const SizedBox(height: 8),
|
||||
// Align(
|
||||
// alignment: Alignment.centerLeft,
|
||||
// child: TextButton.icon(
|
||||
// onPressed: () => context.goNamed(PayoutRoutes.reports),
|
||||
// icon: const Icon(Icons.open_in_new, size: 16),
|
||||
// label: Text(l10.viewWholeHistory),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
],
|
||||
],
|
||||
return ChangeNotifierProxyProvider<PaymentsProvider, RecentPaymentsController>(
|
||||
create: (_) => RecentPaymentsController(),
|
||||
update: (_, payments, controller) => controller!..update(payments),
|
||||
child: const _RecentPaymentsView(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RecentPaymentsView extends StatelessWidget {
|
||||
const _RecentPaymentsView();
|
||||
|
||||
void _openPaymentDetails(BuildContext context, OperationItem operation) {
|
||||
final paymentId = paymentIdFromOperation(operation);
|
||||
if (paymentId == null) return;
|
||||
context.pushToReportPayment(paymentId);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l10 = AppLocalizations.of(context)!;
|
||||
return Consumer<RecentPaymentsController>(
|
||||
builder: (context, controller, child) {
|
||||
if (controller.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (controller.error != null) {
|
||||
return Text(
|
||||
l10.notificationError(controller.error ?? l10.noErrorInformation),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
UploadHistoryHeader(theme: theme),
|
||||
const SizedBox(height: 8),
|
||||
OperationsCardsColumn(
|
||||
operations: controller.recentOperations,
|
||||
onTap: (operation) => _openPaymentDetails(context, operation),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user