Files

197 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:sxchnge_wallet/sxchnge_wallet.dart';
import 'copy.dart';
import '../generated/i18n/app_localizations.dart';
class ActivityPage extends StatefulWidget {
const ActivityPage({super.key});
@override
State<ActivityPage> createState() => _ActivityPageState();
}
class _ActivityPageState extends State<ActivityPage> {
TransferKind? _kind;
OperationStatus? _status;
String _search = '';
String? _currency;
@override
Widget build(BuildContext context) {
final p = context.watch<WalletProvider>();
final l = AppLocalizations.of(context)!;
final list =
p.data?.operations
.where(
(o) =>
(_kind == null || o.quote.request.kind == _kind) &&
(_status == null || o.status == _status) &&
(_currency == null ||
o.quote.request.source == _currency ||
o.quote.request.destination == _currency) &&
o.id.toLowerCase().contains(_search.toLowerCase()),
)
.toList() ??
[];
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 1000),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Expanded(
child: Text(
l.wActivity,
style: Theme.of(context).textTheme.displaySmall,
),
),
IconButton(
tooltip: l.wRefresh,
onPressed: p.loading ? null : p.refresh,
icon: const Icon(Icons.refresh),
),
],
),
const SizedBox(height: 24),
TextField(
decoration: InputDecoration(
labelText: l.wSearch,
prefixIcon: const Icon(Icons.search),
),
onChanged: (value) => setState(() => _search = value),
),
const SizedBox(height: 16),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ChoiceChip(
label: Text(l.wAll),
selected: _kind == null,
onSelected: (_) => setState(() => _kind = null),
),
for (final k in TransferKind.values)
ChoiceChip(
label: Text(kindText(l, k)),
selected: _kind == k,
onSelected: (_) => setState(() => _kind = k),
),
],
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (final s in OperationStatus.values)
FilterChip(
label: Text(statusText(l, s)),
selected: _status == s,
onSelected: (value) =>
setState(() => _status = value ? s : null),
),
for (final a in p.data?.accounts ?? <CurrencyAccount>[])
FilterChip(
label: Text(a.currency),
selected: _currency == a.id,
onSelected: (value) =>
setState(() => _currency = value ? a.id : null),
),
],
),
const SizedBox(height: 20),
if (p.loading) const LinearProgressIndicator(),
if (p.failed) Text(l.wUnavailable),
if (list.isEmpty && !p.loading)
Padding(
padding: const EdgeInsets.all(24),
child: Text(
(p.data?.operations.isEmpty ?? true)
? l.wEmptyActivity
: l.wNoMatches,
),
),
for (final o in list) OperationTile(operation: o),
],
),
),
),
);
}
}
class OperationTile extends StatelessWidget {
const OperationTile({super.key, required this.operation});
final WalletOperation operation;
@override
Widget build(BuildContext context) {
final p = context.read<WalletProvider>();
final l = AppLocalizations.of(context)!;
final o = operation;
final a = p.account(o.quote.request.source);
final to = p.account(o.quote.request.destination);
final t = Theme.of(context);
return Card(
child: InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () => context.push('/activity/${o.id}'),
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
CircleAvatar(
backgroundColor: t.colorScheme.primaryContainer,
child: Icon(
kindIcon(o.quote.request.kind),
color: t.colorScheme.onPrimaryContainer,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
kindText(l, o.quote.request.kind),
style: t.textTheme.titleMedium,
),
Text(
'${a?.currency ?? ''}${to == null ? '' : ' → ${to.currency}'} · ${statusText(l, o.status)}',
),
Text(
DateFormat.yMMMd(
Localizations.localeOf(context).toLanguageTag(),
).add_Hm().format(o.createdAt),
style: t.textTheme.bodySmall,
),
],
),
),
const SizedBox(width: 8),
Flexible(
child: Text(
a == null ? '' : money(context, a, o.quote.request.amount),
textAlign: TextAlign.end,
style: t.textTheme.titleMedium,
),
),
const Icon(Icons.chevron_right),
],
),
),
),
);
}
}