diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index 5053a7ef8..d2a4bc966 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -43,7 +43,7 @@ abstract class BuyProvider { required double amount, required bool isBuyAction, required String cryptoCurrencyAddress, - String? countryCode}); + String? countryCode}) => null; Future requestUrl(String amount, String sourceCurrency) => throw UnimplementedError(); diff --git a/lib/new-ui/pages/buy_sell/buy_sell_amount_page.dart b/lib/new-ui/pages/buy_sell/buy_sell_amount_page.dart index b29a747db..3b36c5834 100644 --- a/lib/new-ui/pages/buy_sell/buy_sell_amount_page.dart +++ b/lib/new-ui/pages/buy_sell/buy_sell_amount_page.dart @@ -1,15 +1,25 @@ +import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/new-ui/widgets/buy_sell/buy_sell_selector_modal.dart'; import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; +import 'package:cake_wallet/themes/core/theme_extension.dart'; import 'package:cake_wallet/view_model/buy/buy_sell_view_model.dart'; +import 'package:cw_core/amount/money.dart'; import 'package:flutter/material.dart'; -class NewBuySellAmountPage extends StatelessWidget { +class NewBuySellAmountPage extends StatefulWidget { const NewBuySellAmountPage({super.key, required this.mode, required this.buySellViewModel}); final BuySellPageMode mode; final BuySellViewModel buySellViewModel; + @override + State createState() => _NewBuySellAmountPageState(); +} + +class _NewBuySellAmountPageState extends State { + bool _customAmountMode = false; + @override Widget build(BuildContext context) { return Container( @@ -25,26 +35,152 @@ class NewBuySellAmountPage extends StatelessWidget { ), ), child: SafeArea( - child: Column(children: [ - ModalTopBar(title: _pageTitle, leadingIcon: Icon(Icons.close), onLeadingPressed: Navigator.of(context).pop,), - Expanded(child: GridView.builder(itemCount: 6, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - mainAxisExtent: 150), itemBuilder: (context, index){ - - - })) - ],), + child: Column( + children: [ + ModalTopBar( + title: _pageTitle, + leadingIcon: Icon(Icons.close), + onLeadingPressed: Navigator.of(context).pop, + ), + Expanded( + child: BuySellDefaultAmountSelector( + defaultAmounts: widget.buySellViewModel.defaultAmounts, + currency: widget.buySellViewModel.fiatCurrency, + mode: widget.mode, + onSelected: (amount) { + if (amount == null) { + setState(() { + _customAmountMode = true; + }); + } else { + widget.buySellViewModel.changeFiatAmount(amount: amount); + } + }, + )) + ], + ), ), ); } - String get _pageTitle => - mode == BuySellPageMode.buy ? S.current.buy : S.current.sell + - ((buySellViewModel.cryptoCurrencies.length == 1) - ? " ${buySellViewModel.cryptoCurrencies.first.fullName}" + String get _pageTitle => widget.mode == BuySellPageMode.buy + ? S.current.buy + : S.current.sell + + ((widget.buySellViewModel.cryptoCurrencies.length == 1) + ? " ${widget.buySellViewModel.cryptoCurrencies.first.fullName}" : ""); } +class BuySellDefaultAmountSelector extends StatelessWidget { + const BuySellDefaultAmountSelector( + {super.key, + required this.defaultAmounts, + required this.currency, + required this.mode, + required this.onSelected}); + final List defaultAmounts; + final FiatCurrency currency; + final BuySellPageMode mode; + final Function(String?) onSelected; + + @override + Widget build(BuildContext context) { + return Column( + spacing: 24, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + mode == BuySellPageMode.sell + ? S.of(context).choose_amount_to_sell + : S.of(context).choose_amount_to_buy, + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 18.0), + child: GridView.builder( + shrinkWrap: true, + // +1 for "custom" option + itemCount: defaultAmounts.length + 1, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, crossAxisSpacing: 8, mainAxisSpacing: 16, mainAxisExtent: 105), + itemBuilder: (context, index) { + final String? item = index == defaultAmounts.length ? null : defaultAmounts[index]; + + return BuySellAmountPill( + amount: item == null ? null : Money.parse(item, currency), + onTap: () => onSelected(item), + ); + }), + ), + ], + ); + } +} + +class BuySellAmountPill extends StatelessWidget { + const BuySellAmountPill({super.key, this.amount, required this.onTap}); + + final Money? amount; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(9999999999), + border: Border.all( + width: 1, + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), + gradient: LinearGradient( + colors: [ + context.customColors.cardGradientColorPrimary, + context.customColors.cardGradientColorSecondary + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: Material( + color: Colors.transparent, + borderRadius: BorderRadius.circular(9999999999), + child: InkWell( + borderRadius: BorderRadius.circular(9999999999), + onTap: onTap, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + spacing: 4, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (amount != null) + Text( + amount!.toStringWithPrecision(fractionalDigits: 0), + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600), + ), + Text( + amount?.currency.symbol ?? S.of(context).custom, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: amount == null + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant), + ) + ], + ), + if (amount == null) + Text( + S.of(context).enter_amount, + style: TextStyle( + fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/new-ui/widgets/buy_sell/buy_sell_selector_modal.dart b/lib/new-ui/widgets/buy_sell/buy_sell_selector_modal.dart index 85b82566a..7e6efd004 100644 --- a/lib/new-ui/widgets/buy_sell/buy_sell_selector_modal.dart +++ b/lib/new-ui/widgets/buy_sell/buy_sell_selector_modal.dart @@ -46,7 +46,7 @@ class BuySellSelectorModal extends StatelessWidget { void openBuySellPage(BuildContext context, BuySellPageMode mode) { Navigator.of(context).pop(); - showModalBottomSheet(isScrollControlled: true, context: context, builder: (modalContext)=>ModalNavigator(rootPage: getIt.get(param1: mode), parentContext: context,)); + showModalBottomSheet(useSafeArea:true, isScrollControlled: true, context: context, builder: (modalContext)=>ModalNavigator(rootPage: getIt.get(param1: mode), parentContext: context,)); } } diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart index a299aebac..4d181d7f6 100644 --- a/lib/view_model/buy/buy_sell_view_model.dart +++ b/lib/view_model/buy/buy_sell_view_model.dart @@ -149,6 +149,59 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S @observable bool skipIsReadyToTradeReaction = false; + + + // based on usd values, should have roughly equal worth (was done with ai though so it's subject to correction) + static final Map> _defaultAmountsMap = { + FiatCurrency.amd: ["20000", "40000", "200000", "400000", "1000000"], + FiatCurrency.aud: ["100", "200", "1000", "2000", "5000"], + FiatCurrency.bgn: ["100", "200", "1000", "2000", "5000"], + FiatCurrency.brl: ["250", "500", "2500", "5000", "12500"], + FiatCurrency.cad: ["50", "100", "500", "1000", "2500"], + FiatCurrency.chf: ["50", "100", "500", "1000", "2500"], + FiatCurrency.clp: ["50000", "100000", "500000", "1000000", "2500000"], + FiatCurrency.cop: ["200000", "400000", "2000000", "4000000", "10000000"], + FiatCurrency.czk: ["1000", "2000", "10000", "20000", "50000"], + FiatCurrency.dkk: ["400", "800", "4000", "8000", "20000"], + FiatCurrency.egp: ["2500", "5000", "25000", "50000", "125000"], + FiatCurrency.eur: ["50", "100", "500", "1000", "2500"], + FiatCurrency.gbp: ["50", "100", "500", "1000", "2500"], + FiatCurrency.gtq: ["400", "800", "4000", "8000", "20000"], + FiatCurrency.hkd: ["400", "800", "4000", "8000", "20000"], + FiatCurrency.hrk: ["400", "800", "4000", "8000", "20000"], + FiatCurrency.huf: ["20000", "40000", "200000", "400000", "1000000"], + FiatCurrency.idr: ["800000", "1600000", "8000000", "16000000", "40000000"], + FiatCurrency.ils: ["200", "400", "2000", "4000", "10000"], + FiatCurrency.inr: ["5000", "10000", "50000", "100000", "250000"], + FiatCurrency.isk: ["7000", "14000", "70000", "140000", "350000"], + FiatCurrency.jpy: ["10000", "20000", "100000", "200000", "500000"], + FiatCurrency.krw: ["50000", "100000", "500000", "1000000", "2500000"], + FiatCurrency.mad: ["500", "1000", "5000", "10000", "25000"], + FiatCurrency.mxn: ["1000", "2000", "10000", "20000", "50000"], + FiatCurrency.myr: ["250", "500", "2500", "5000", "12500"], + FiatCurrency.ngn: ["50000", "100000", "500000", "1000000", "2500000"], + FiatCurrency.nok: ["500", "1000", "5000", "10000", "25000"], + FiatCurrency.nzd: ["100", "200", "1000", "2000", "5000"], + FiatCurrency.php: ["3000", "6000", "30000", "60000", "150000"], + FiatCurrency.pkr: ["15000", "30000", "150000", "300000", "750000"], + FiatCurrency.pln: ["200", "400", "2000", "4000", "10000"], + FiatCurrency.ron: ["250", "500", "2500", "5000", "12500"], + FiatCurrency.sek: ["500", "1000", "5000", "10000", "25000"], + FiatCurrency.sgd: ["50", "100", "500", "1000", "2500"], + FiatCurrency.thb: ["2000", "4000", "20000", "40000", "100000"], + FiatCurrency.tur: ["1500", "3000", "15000", "30000", "75000"], + FiatCurrency.twd: ["1500", "3000", "15000", "30000", "75000"], + FiatCurrency.usd: ["50", "100", "500", "1000", "2500"], + FiatCurrency.vnd: ["1000000", "2000000", "10000000", "20000000", "50000000"], + FiatCurrency.zar: ["1000", "2000", "10000", "20000", "50000"], + FiatCurrency.kes: ["5000", "10000", "50000", "100000", "250000"], + }; + + // the fallback is just the usd values. + // not great but this fallback shouldn't be triggered anyway + List get defaultAmounts => + _defaultAmountsMap[fiatCurrency] ?? ["50", "100", "500", "1000", "2500"]; + @computed bool get isReadyToTrade { final hasSelectedQuote = selectedQuote != null; diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 8cf1c7835..207ee288c 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -199,6 +199,8 @@ "choose_a_provider": "Choose a provider", "choose_account": "Choose account", "choose_address": "\n\nPlease choose the address:", + "choose_amount_to_buy": "Choose amount to buy", + "choose_amount_to_sell": "Choose amount to sell", "choose_card_value": "Choose a card value", "choose_derivation": "Choose Wallet Derivation", "choose_from_available_options": "Choose from the available options:",