import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pshared/models/payment/operation.dart'; import 'package:pshared/provider/payment/payments.dart'; import 'package:pweb/pages/report/cards/list.dart'; import 'package:pweb/pages/report/charts/payout_volumes/chart.dart'; import 'package:pweb/pages/report/charts/status.dart'; import 'package:pweb/controllers/report_operations.dart'; import 'package:pweb/pages/report/table/filters.dart'; import 'package:pweb/utils/report/payment_mapper.dart'; import 'package:pweb/app/router/payout_routes.dart'; import 'package:pweb/models/load_more_state.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; class OperationHistoryPage extends StatelessWidget { const OperationHistoryPage({super.key}); @override Widget build(BuildContext context) { return ChangeNotifierProxyProvider( create: (_) => ReportOperationsController(), update: (_, payments, controller) => controller!..update(payments), child: const _OperationHistoryView(), ); } } class _OperationHistoryView extends StatelessWidget { const _OperationHistoryView(); Future _pickRange( BuildContext context, ReportOperationsController controller, ) async { final now = DateTime.now(); final initial = controller.selectedRange ?? DateTimeRange( start: now.subtract(const Duration(days: 30)), end: now, ); final picked = await showDateRangePicker( context: context, firstDate: DateTime(2000), lastDate: now.add(const Duration(days: 1)), initialDateRange: initial, ); if (picked != null) { controller.setRange(picked); } } void _openPaymentDetails(BuildContext context, OperationItem operation) { final paymentId = paymentIdFromOperation(operation); if (paymentId == null) return; context.pushToReportPayment(paymentId); } @override Widget build(BuildContext context) { final loc = AppLocalizations.of(context)!; return Consumer( builder: (context, controller, child) { if (controller.isLoading) { return const Center(child: CircularProgressIndicator()); } if (controller.error != null) { final message = controller.error?.toString() ?? loc.noErrorInformation; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(loc.notificationError(message)), ElevatedButton( onPressed: () => controller.refresh(), child: Text(loc.retry), ), ], ), ); } final operations = controller.operations; final filteredOperations = controller.filteredOperations; return Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, spacing: 16, children: [ //TODO Make charts more useful and re-enable SizedBox( height: 200, child: Row( spacing: 16, children: [ Expanded( child: StatusChart(operations: operations), ), Expanded( child: PayoutVolumesChart( operations: operations, ), ), ], ), ), OperationFilters( selectedRange: controller.selectedRange, selectedStatuses: controller.selectedStatuses, onPickRange: () => _pickRange(context, controller), onToggleStatus: controller.toggleStatus, onClear: controller.clearFilters, ), OperationsCardsList( operations: filteredOperations, onTap: (operation) => _openPaymentDetails(context, operation), loadMoreState: controller.loadMoreState, onLoadMore: controller.loadMoreState == LoadMoreState.available ? () => controller.loadMore() : null, ), ], ), ); }, ); } }