diff options
author | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-12-08 03:14:55 +0800 |
---|---|---|
committer | Steve Klebanoff <steve.klebanoff@gmail.com> | 2018-12-12 06:37:45 +0800 |
commit | 5cbe04acab982ead39f7794547de0f045952a1b7 (patch) | |
tree | 5847cfb56df0c357997d5b1dfeb7811394a5da98 /packages/instant/src/components | |
parent | d37680610b772d7bb585203047bef0af0439df0a (diff) | |
download | dexon-0x-contracts-5cbe04acab982ead39f7794547de0f045952a1b7.tar.gz dexon-0x-contracts-5cbe04acab982ead39f7794547de0f045952a1b7.tar.zst dexon-0x-contracts-5cbe04acab982ead39f7794547de0f045952a1b7.zip |
feat(instant): ETH/USD toggle
Diffstat (limited to 'packages/instant/src/components')
-rw-r--r-- | packages/instant/src/components/order_details.tsx | 196 |
1 files changed, 161 insertions, 35 deletions
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index a8e0e2513..85761a5b9 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -6,63 +6,92 @@ import { oc } from 'ts-optchain'; import { BIG_NUMBER_ZERO } from '../constants'; import { ColorOption } from '../style/theme'; +import { BaseCurrency } from '../types'; +import { buyQuoteUtil } from '../util/buy_quote'; import { format } from '../util/format'; import { AmountPlaceholder } from './amount_placeholder'; import { Container } from './ui/container'; import { Flex } from './ui/flex'; -import { Text } from './ui/text'; +import { Text, TextProps } from './ui/text'; + +interface BaseCurrenySwitchProps { + currencyName: string; + onClick: () => void; + isSelected: boolean; +} +const BaseCurrencySelector: React.StatelessComponent<BaseCurrenySwitchProps> = props => { + const textStyle: TextProps = { onClick: props.onClick, fontSize: '12px' }; + if (props.isSelected) { + textStyle.fontColor = ColorOption.primaryColor; + textStyle.fontWeight = 700; + } + return <Text {...textStyle}>{props.currencyName}</Text>; +}; export interface OrderDetailsProps { buyQuoteInfo?: BuyQuoteInfo; selectedAssetUnitAmount?: BigNumber; ethUsdPrice?: BigNumber; isLoading: boolean; + assetName?: string; + baseCurrency: BaseCurrency; + onBaseCurrencySwitchEth: () => void; + onBaseCurrencySwitchUsd: () => void; } export class OrderDetails extends React.Component<OrderDetailsProps> { public render(): React.ReactNode { const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props; - const buyQuoteAccessor = oc(buyQuoteInfo); - const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount(); - const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount(); - const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount(); - const pricePerTokenEth = - !_.isUndefined(assetEthBaseUnitAmount) && - !_.isUndefined(selectedAssetUnitAmount) && - !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO) - ? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil() - : undefined; + const weiAmounts = buyQuoteUtil.getWeiAmounts(selectedAssetUnitAmount, buyQuoteInfo); + + const displayAmounts = + this.props.baseCurrency === BaseCurrency.USD + ? buyQuoteUtil.displayAmountsUsd(weiAmounts, ethUsdPrice) + : buyQuoteUtil.displayAmountsEth(weiAmounts, ethUsdPrice); + return ( <Container width="100%" flexGrow={1} padding="20px 20px 0px 20px"> <Container marginBottom="10px"> - <Text - letterSpacing="1px" - fontColor={ColorOption.primaryColor} - fontWeight={600} - textTransform="uppercase" - fontSize="14px" - > - Order Details - </Text> + <Flex justify="space-between"> + <Text + letterSpacing="1px" + fontColor={ColorOption.primaryColor} + fontWeight={600} + textTransform="uppercase" + fontSize="14px" + > + Order Details + </Text> + + <Container> + <BaseCurrencySelector + onClick={this.props.onBaseCurrencySwitchEth} + currencyName="ETH" + isSelected={this.props.baseCurrency === BaseCurrency.ETH} + /> + <Container marginLeft="3px" marginRight="3px" display="inline"> + <Text fontSize="12px">/</Text> + </Container> + <BaseCurrencySelector + onClick={this.props.onBaseCurrencySwitchUsd} + currencyName="USD" + isSelected={this.props.baseCurrency === BaseCurrency.USD} + /> + </Container> + </Flex> </Container> - <EthAmountRow - rowLabel="Token Price" - ethAmount={pricePerTokenEth} - ethUsdPrice={ethUsdPrice} - isLoading={this.props.isLoading} - /> - <EthAmountRow - rowLabel="Fee" - ethAmount={feeEthBaseUnitAmount} - ethUsdPrice={ethUsdPrice} + <TokenAmountRow + numTokens={selectedAssetUnitAmount} + assetName={this.props.assetName} + displayPricePerToken={displayAmounts.pricePerToken} + displayTotalPrice={displayAmounts.assetTotal} isLoading={this.props.isLoading} /> - <EthAmountRow - rowLabel="Total Cost" - ethAmount={totalEthBaseUnitAmount} - ethUsdPrice={ethUsdPrice} - shouldEmphasize={true} + <OrderDetailsRow labelText="Fee" value={displayAmounts.feeTotal} isLoading={this.props.isLoading} /> + <TotalCostRow + displaySecondaryTotalCost={displayAmounts.secondaryGrandTotal} + displayPrimaryTotalCost={displayAmounts.primaryGrandTotal} isLoading={this.props.isLoading} /> </Container> @@ -79,6 +108,103 @@ export interface EthAmountRowProps { isLoading: boolean; } +export interface OrderDetailsRowProps { + labelText: string; + isLabelBold?: boolean; + isLoading: boolean; + value?: React.ReactNode; +} +export class OrderDetailsRow extends React.Component<OrderDetailsRowProps, {}> { + public render(): React.ReactNode { + const { labelText, value, isLabelBold, isLoading } = this.props; + return ( + <Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}> + <Flex justify="space-between"> + <Text fontWeight={isLabelBold ? 700 : 400} fontColor={ColorOption.grey}> + {labelText} + </Text> + <Container> + {value || ( + <Container opacity={0.5}> + <AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} /> + </Container> + )} + </Container> + </Flex> + </Container> + ); + } +} +export interface TotalCostRowProps { + displayPrimaryTotalCost?: React.ReactNode; + displaySecondaryTotalCost?: React.ReactNode; + isLoading: boolean; +} +export class TotalCostRow extends React.Component<TotalCostRowProps, {}> { + public render(): React.ReactNode { + let value: React.ReactNode; + if (this.props.displayPrimaryTotalCost) { + const secondaryText = this.props.displaySecondaryTotalCost && ( + <Container marginRight="3px" display="inline-block"> + <Text fontColor={ColorOption.lightGrey}>({this.props.displaySecondaryTotalCost})</Text> + </Container> + ); + value = ( + <React.Fragment> + {secondaryText} + <Text fontWeight={700} fontColor={ColorOption.grey}> + {this.props.displayPrimaryTotalCost} + </Text> + </React.Fragment> + ); + } + + return ( + <OrderDetailsRow isLoading={this.props.isLoading} isLabelBold={true} labelText="Total Cost" value={value} /> + ); + } +} + +export interface TokenAmountRowProps { + assetName?: string; + displayPricePerToken?: React.ReactNode; + displayTotalPrice?: React.ReactNode; + isLoading: boolean; + numTokens?: BigNumber; +} +export class TokenAmountRow extends React.Component<TokenAmountRowProps> { + public static DEFAULT_TEXT: string = 'Token Price'; + public render(): React.ReactNode { + return ( + <OrderDetailsRow + isLoading={this.props.isLoading} + labelText={this._labelText()} + value={this.props.displayTotalPrice} + /> + ); + } + private _labelText(): string { + if (this.props.isLoading) { + return TokenAmountRow.DEFAULT_TEXT; + } + const { numTokens, displayPricePerToken, assetName } = this.props; + if (numTokens) { + let numTokensWithSymbol = numTokens.toString(); + + if (assetName) { + numTokensWithSymbol += ` ${assetName}`; + } + + if (displayPricePerToken) { + numTokensWithSymbol += ` @ ${displayPricePerToken}`; + } + return numTokensWithSymbol; + } + + return TokenAmountRow.DEFAULT_TEXT; + } +} + export class EthAmountRow extends React.Component<EthAmountRowProps> { public static defaultProps = { shouldEmphasize: false, |