buy quote preview view and sample quote class

This commit is contained in:
julian 2023-01-15 18:09:11 -06:00
parent 0c9dcf6403
commit 650ae9fe09
8 changed files with 277 additions and 5 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,25 @@
import 'package:decimal/decimal.dart';
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
class SimplexQuote {
// todo: this class
final Crypto crypto;
final Fiat fiat;
final Decimal youPayFiatPrice;
final Decimal youReceiveCryptoAmount;
final String purchaseId;
final String receivingAddress;
SimplexQuote({
required this.crypto,
required this.fiat,
required this.youPayFiatPrice,
required this.youReceiveCryptoAmount,
required this.purchaseId,
required this.receivingAddress,
});
}

View file

@ -1,12 +1,15 @@
import 'dart:async';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
import 'package:stackwallet/models/buy/response_objects/quote.dart';
import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
import 'package:stackwallet/pages/buy_view/buy_quote_preview.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart';
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_selection_view.dart';
@ -814,10 +817,24 @@ class _BuyFormState extends ConsumerState<BuyForm> {
),
PrimaryButton(
buttonHeight: isDesktop ? ButtonHeight.l : null,
enabled: ref.watch(exchangeFormStateProvider
.select((value) => value.canExchange)),
enabled: _receiveAddressController.text.isNotEmpty &&
_buyAmountController.text.isNotEmpty,
onPressed: () {
// preview buy quote
// TODO: show loading while fetching quote
final quote = SimplexQuote(
crypto: selectedCrypto!,
fiat: selectedFiat!,
youPayFiatPrice: Decimal.parse("100"),
youReceiveCryptoAmount: Decimal.parse("1.0238917"),
purchaseId: "someID",
receivingAddress: _receiveAddressController.text,
);
Navigator.of(context).pushNamed(
BuyQuotePreviewView.routeName,
arguments: quote,
);
},
label: "Preview quote",
)

View file

@ -0,0 +1,197 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/buy/response_objects/quote.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class BuyQuotePreviewView extends StatefulWidget {
const BuyQuotePreviewView({
Key? key,
required this.quote,
}) : super(key: key);
final SimplexQuote quote;
static const String routeName = "/buyQuotePreview";
@override
State<BuyQuotePreviewView> createState() => _BuyQuotePreviewViewState();
}
class _BuyQuotePreviewViewState extends State<BuyQuotePreviewView> {
final isDesktop = Util.isDesktop;
Future<void> _buy() async {
// do buy/redirect to simplex page
}
@override
Widget build(BuildContext context) {
return ConditionalParent(
condition: !isDesktop,
builder: (child) {
return Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
backgroundColor:
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
leading: const AppBarBackButton(),
title: Text(
"Preview quote",
style: STextStyles.navBarTitle(context),
),
),
body: LayoutBuilder(
builder: (builderContext, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: child,
),
),
),
),
);
},
),
),
);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Buy ${widget.quote.crypto.ticker.toUpperCase()}",
style: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 16,
),
RoundedWhiteContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"You pay",
style: STextStyles.label(context),
),
Text(
"${widget.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.quote.fiat.ticker.toUpperCase()}",
style: STextStyles.label(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,
),
),
],
),
),
const SizedBox(
height: 8,
),
RoundedWhiteContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"You receive",
style: STextStyles.label(context),
),
Text(
"${widget.quote.youReceiveCryptoAmount} ${widget.quote.crypto.ticker.toUpperCase()}",
style: STextStyles.label(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,
),
),
],
),
),
const SizedBox(
height: 8,
),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Receiving ${widget.quote.crypto.ticker.toUpperCase()} address",
style: STextStyles.label(context),
),
Text(
"${widget.quote.receivingAddress} ",
style: STextStyles.label(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,
),
),
],
),
),
const SizedBox(
height: 8,
),
RoundedWhiteContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Purchase ID",
style: STextStyles.label(context),
),
Text(
widget.quote.purchaseId,
style: STextStyles.label(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark,
),
),
],
),
),
const SizedBox(
height: 8,
),
RoundedWhiteContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Provider",
style: STextStyles.label(context),
),
SizedBox(
width: 64,
child: SvgPicture.asset(Assets.buy.simplexLogo),
),
],
),
),
const SizedBox(
height: 8,
),
const Spacer(),
PrimaryButton(
label: "Buy",
onPressed: _buy,
)
],
),
);
}
}

View file

@ -61,6 +61,8 @@ class _ConfirmChangeNowSendViewState
late final String routeOnSuccessName;
late final Trade trade;
final isDesktop = Util.isDesktop;
Future<void> _attemptSend(BuildContext context) async {
unawaited(
showDialog<void>(
@ -227,8 +229,6 @@ class _ConfirmChangeNowSendViewState
final managerProvider = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManagerProvider(walletId)));
final isDesktop = Util.isDesktop;
return ConditionalParent(
condition: !isDesktop,
builder: (child) {
@ -238,7 +238,7 @@ class _ConfirmChangeNowSendViewState
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
leading: AppBarBackButton(
onPressed: () async {
// if (FocusScope.of(context).hasFocus) {

View file

@ -2,6 +2,7 @@ import 'package:decimal/decimal.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/buy/response_objects/quote.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
@ -22,6 +23,7 @@ import 'package:stackwallet/pages/address_book_views/subviews/address_book_filte
import 'package:stackwallet/pages/address_book_views/subviews/contact_details_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
import 'package:stackwallet/pages/buy_view/buy_quote_preview.dart';
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_loading_overlay.dart';
@ -1001,6 +1003,20 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case BuyQuotePreviewView.routeName:
if (args is SimplexQuote) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => BuyQuotePreviewView(
quote: args,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
// == Desktop specific routes ============================================
case CreatePasswordView.routeName:
if (args is bool) {

View file

@ -31,7 +31,12 @@ class _EXCHANGE {
class _BUY {
const _BUY();
// TODO: switch this to something like
// String buy(BuildContext context) =>
// "assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/buy.svg";
String get buy => "assets/svg/light/buy-coins-icon.svg";
String get simplexLogo => "assets/svg/buy/Simplex-Nuvei-Logo.svg";
}
class _SVG {

View file

@ -384,6 +384,9 @@ flutter:
- assets/svg/oceanBreeze/buy-coins-icon.svg
- assets/svg/oceanBreeze/bg.svg
# buy
- assets/svg/buy/Simplex-Nuvei-Logo.svg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see