Files
sxchnge/frontend/app/lib/workspace/operation.dart

153 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:sxchnge_wallet/sxchnge_wallet.dart';
import 'copy.dart';
import 'summary.dart';
import '../generated/i18n/app_localizations.dart';
class OperationPage extends StatefulWidget {
const OperationPage({super.key, required this.id});
final String id;
@override
State<OperationPage> createState() => _OperationPageState();
}
class _OperationPageState extends State<OperationPage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) context.read<WalletProvider>().refresh();
});
}
@override
Widget build(BuildContext context) {
final p = context.watch<WalletProvider>();
final o = p.operation(widget.id);
final l = AppLocalizations.of(context)!;
final t = Theme.of(context);
final c = t.colorScheme;
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 640),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.centerLeft,
child: TextButton.icon(
onPressed: () => context.go('/activity'),
icon: const Icon(Icons.arrow_back),
label: Text(l.wActivity),
),
),
if (p.failed)
Text(l.wUnavailable, style: TextStyle(color: c.error)),
if (o == null) ...[
Text(p.loading ? l.wWorking : l.wNotFound),
TextButton(
onPressed: p.loading ? null : p.refresh,
child: Text(l.wRefresh),
),
] else ...[
Container(
padding: const EdgeInsets.all(28),
decoration: BoxDecoration(
color: o.status == OperationStatus.failed
? c.errorContainer
: c.primaryContainer,
borderRadius: BorderRadius.circular(28),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
o.status == OperationStatus.completed
? Icons.check_circle_outline
: o.status == OperationStatus.pending
? Icons.schedule
: Icons.info_outline,
size: 40,
color: o.status == OperationStatus.failed
? c.onErrorContainer
: c.onPrimaryContainer,
),
const SizedBox(height: 16),
Semantics(
header: true,
liveRegion: true,
child: Text(
statusText(l, o.status),
key: ValueKey('operation-${o.status.name}'),
style: t.textTheme.displaySmall?.copyWith(
color: o.status == OperationStatus.failed
? c.onErrorContainer
: c.onPrimaryContainer,
),
),
),
const SizedBox(height: 16),
Text(
fundsText(l, o),
style: TextStyle(
color: o.status == OperationStatus.failed
? c.onErrorContainer
: c.onPrimaryContainer,
),
),
],
),
),
const SizedBox(height: 20),
TransferSummary(quote: o.quote),
const SizedBox(height: 16),
Text('${l.wReference}: ${o.id}'),
if (o.status == OperationStatus.pending) ...[
const SizedBox(height: 12),
Text(l.wPendingHint),
TextButton(
onPressed: p.loading ? null : p.refresh,
child: Text(l.wRefresh),
),
],
const SizedBox(height: 24),
if (o.status == OperationStatus.completed &&
o.quote.request.kind != TransferKind.payout)
FilledButton(
onPressed: () => context.go(
o.quote.request.kind == TransferKind.topUp
? '/exchange'
: '/payout',
extra:
o.quote.request.destination ?? o.quote.request.source,
),
child: Text(
o.quote.request.kind == TransferKind.topUp
? l.wExchange
: l.wPayout,
),
),
TextButton(
onPressed: () => context.go(
'/accounts/${o.quote.request.destination ?? o.quote.request.source}',
),
child: Text(l.wViewAccount),
),
],
],
),
),
),
);
}
}