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 'activity.dart'; import 'copy.dart'; import '../generated/i18n/app_localizations.dart'; class AccountsPage extends StatelessWidget { const AccountsPage({super.key, this.accountId}); final String? accountId; @override Widget build(BuildContext context) { final p = context.watch(); final l = AppLocalizations.of(context)!; final t = Theme.of(context); final c = t.colorScheme; final accounts = p.data?.accounts ?? []; final selected = accountId == null ? accounts.firstOrNull : p.account(accountId); return SingleChildScrollView( padding: const EdgeInsets.all(24), child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 1120), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Text(l.wHeadline, style: t.textTheme.displayMedium), ), IconButton( tooltip: l.wRefresh, onPressed: p.loading ? null : p.refresh, icon: const Icon(Icons.refresh), ), ], ), const SizedBox(height: 12), Text(l.wSubheading, style: t.textTheme.bodyLarge), const SizedBox(height: 16), Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l.kycIntro), TextButton( onPressed: () => context.push('/identity'), child: Text(l.wIdentity), ), ], ), ), ), const SizedBox(height: 28), if (p.loading) const LinearProgressIndicator(), if (p.failed) Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Text(l.wUnavailable, style: TextStyle(color: c.error)), ), if (!p.loading && accounts.isEmpty) Text(l.wEmptyAccounts), if (accountId != null && p.account(accountId) == null && !p.loading) Text(l.wNotFound), if (selected != null) ...[ const SizedBox(height: 24), Text(selected.currency, style: t.textTheme.titleLarge), const SizedBox(height: 12), Wrap( spacing: 12, runSpacing: 12, children: [ for (final kind in TransferKind.values) _action( context, kind, selected, primary: kind == (selected.available == 0 ? TransferKind.topUp : TransferKind.exchange), ), ], ), ], const SizedBox(height: 24), LayoutBuilder( builder: (context, box) { final width = box.maxWidth >= 660 ? (box.maxWidth - 32) / 3 : box.maxWidth; return Wrap( spacing: 16, runSpacing: 16, children: [ for (var i = 0; i < accounts.length; i++) SizedBox( width: width, child: _AccountCard( account: accounts[i], selected: accounts[i].id == selected?.id, index: i, ), ), ], ); }, ), const SizedBox(height: 36), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(l.wRecent, style: t.textTheme.headlineSmall), TextButton( onPressed: () => context.go('/activity'), child: Text(l.wSeeAll), ), ], ), const SizedBox(height: 12), ...?p.data?.operations .where( (o) => accountId == null || o.quote.request.source == accountId || o.quote.request.destination == accountId, ) .take(5) .map((o) => OperationTile(operation: o)), if (!(p.data?.operations.any( (o) => accountId == null || o.quote.request.source == accountId || o.quote.request.destination == accountId, ) ?? false)) Container( padding: const EdgeInsets.all(28), decoration: BoxDecoration( color: c.surfaceContainer, borderRadius: BorderRadius.circular(24), ), child: Text(l.wEmptyActivity), ), ], ), ), ), ); } Widget _action( BuildContext context, TransferKind kind, CurrencyAccount a, { required bool primary, }) { final l = AppLocalizations.of(context)!; void go() => context.go( '/${kind.name == "topUp" ? "top-up" : kind.name}', extra: a.id, ); return primary ? FilledButton.icon( key: ValueKey('${kind.name}-${a.id}'), onPressed: go, icon: Icon(kindIcon(kind)), label: Text(kindText(l, kind)), ) : FilledButton.tonalIcon( key: ValueKey('${kind.name}-${a.id}'), onPressed: go, icon: Icon(kindIcon(kind)), label: Text(kindText(l, kind)), ); } } class _AccountCard extends StatelessWidget { const _AccountCard({ required this.account, required this.selected, required this.index, }); final CurrencyAccount account; final bool selected; final int index; @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; final t = Theme.of(context); final c = t.colorScheme; final bg = selected ? c.primary : index == 1 ? c.tertiaryContainer : c.primaryContainer; final fg = selected ? c.onPrimary : index == 1 ? c.onTertiaryContainer : c.onPrimaryContainer; return Semantics( selected: selected, child: Material( color: bg, borderRadius: BorderRadius.circular(28), child: InkWell( key: ValueKey('account-${account.id}'), borderRadius: BorderRadius.circular(28), onTap: () => context.go('/accounts/${account.id}'), child: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Text( account.currency, style: t.textTheme.titleLarge?.copyWith(color: fg), ), const Spacer(), Icon( selected ? Icons.check_circle_outline : Icons.arrow_outward_rounded, color: fg, ), ], ), const SizedBox(height: 32), Text(l.wAvailable, style: TextStyle(color: fg)), const SizedBox(height: 8), Text( money(context, account, account.available), key: ValueKey('balance-${account.id}'), style: t.textTheme.headlineMedium?.copyWith(color: fg), ), ], ), ), ), ), ); } }