Skip to content

Commit

Permalink
[SWA-46] Add confirmation Modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Wixzi committed Jun 23, 2023
1 parent 0a08e7e commit 04912ba
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import styled, { useTheme } from 'styled-components'

import { ButtonPrimary } from '../../../../components/Button'
import { StyledKey, StyledValue } from '../SwapModalFooter'

// import { ButtonPrimary } from '../../../../../components/Button'
// import { StyledKey, StyledValue } from '../../../Components/SwapModalFooter'

export type FooterData = {
askPrice: string
marketPriceDifference: string
isDiffPositive: boolean
expiresIn: string
market: string
onConfirm: () => void
}

export const ConfirmationFooter = ({
askPrice,
onConfirm,
expiresIn,
marketPriceDifference,
isDiffPositive,
market,
}: FooterData) => {
const theme = useTheme()
const priceDiffColor = isDiffPositive ? theme.green1 : theme.red1

return (
<Wrapper>
<SingleRow>
<StyledKey>Ask price</StyledKey>
<StyledValue>{askPrice}</StyledValue>
</SingleRow>
<SingleRow>
<StyledKey>Diff. market price</StyledKey>
<StyledValue color={priceDiffColor}>{marketPriceDifference}%</StyledValue>
</SingleRow>
<SingleRow>
<StyledKey>Expires in</StyledKey>
<StyledValue> {expiresIn}</StyledValue>
</SingleRow>
<SingleRow>
<StyledKey>Market</StyledKey>
<StyledValue>{market}</StyledValue>
</SingleRow>
<ButtonPrimary marginTop={'20px'} onClick={onConfirm}>
PLACE LIMIT ORDER
</ButtonPrimary>
</Wrapper>
)
}

const Wrapper = styled.div`
display: flex;
gap: 7px;
flex-direction: column;
`
const SingleRow = styled.div`
display: flex;
justify-content: space-between;
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { CurrencyAmount, TokenAmount } from '@swapr/sdk'

import { ArrowDown } from 'react-feather'
import styled from 'styled-components'

import { CurrencyLogo } from '../../../../components/CurrencyLogo'
import { toFixedSix } from '../../LimitOrder/Components/utils'

export type HeaderData = {
fiatValueInput: CurrencyAmount | null
fiatValueOutput: CurrencyAmount | null
buyToken: TokenAmount
sellToken: TokenAmount
}

export const ConfirmationHeader = ({ fiatValueInput, fiatValueOutput, buyToken, sellToken }: HeaderData) => {
const fiatInput = fiatValueInput && fiatValueInput.toFixed(2, { groupSeparator: ',' })
const fiatOutput = fiatValueOutput && fiatValueOutput.toFixed(2, { groupSeparator: ',' })

return (
<Wrapper>
<CurrencyAmountContainer>
<CurrencyLogoInfo>
<PurpleText>YOU SWAP</PurpleText>
<LogoWithText>
<CurrencySymbol>{sellToken.currency.symbol}</CurrencySymbol>{' '}
<CurrencyLogo size="20px" currency={sellToken.currency} />
</LogoWithText>
</CurrencyLogoInfo>
<AmountWithUsd>
<Amount>{toFixedSix(Number(sellToken.toExact()))}</Amount>
{fiatInput && <PurpleText>${fiatInput}</PurpleText>}
</AmountWithUsd>
</CurrencyAmountContainer>
<StyledArrow />
<CurrencyAmountContainer>
<CurrencyLogoInfo>
<PurpleText>YOU RECIEVE</PurpleText>
<LogoWithText>
<CurrencySymbol>{buyToken.currency.symbol}</CurrencySymbol>{' '}
<CurrencyLogo size="20px" currency={buyToken.currency} />
</LogoWithText>
</CurrencyLogoInfo>
<AmountWithUsd>
<Amount>{toFixedSix(Number(buyToken.toExact()))}</Amount>
{fiatOutput && <PurpleText>${fiatOutput}</PurpleText>}
</AmountWithUsd>
</CurrencyAmountContainer>
</Wrapper>
)
}

const Wrapper = styled.div`
display: flex;
flex-direction: column;
margin-top: 20px;
`
const CurrencyAmountContainer = styled.div`
display: flex;
padding: 0 19px;
align-items: center;
justify-content: space-between;
height: 82px;
border: 1px solid ${({ theme }) => theme.bg3};
border-radius: 8.72381px;
`
const CurrencySymbol = styled.div`
font-weight: 600;
font-size: 20px;
line-height: 24px;
`
const LogoWithText = styled.div`
display: flex;
align-items: center;
gap: 6px;
`
const CurrencyLogoInfo = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
`

const AmountWithUsd = styled.div`
display: flex;
flex-direction: column;
align-items: end;
gap: 4px;
`
const Amount = styled.div`
font-weight: 600;
font-size: 20px;
line-height: 28px;
`
const PurpleText = styled.div`
font-weight: 600;
font-size: 10px;
line-height: 12px;
letter-spacing: 0.08em;
color: ${({ theme }) => theme.purple3};
`
const StyledArrow = styled(ArrowDown)`
width: 100%;
margin: 4px 0;
height: 16px;
`
103 changes: 103 additions & 0 deletions src/pages/Swap/Components/ConfirmLimitOrderModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { CurrencyAmount } from '@swapr/sdk'

import { useCallback, useContext } from 'react'

import TransactionConfirmationModal, {
ConfirmationModalContent,
TransactionErrorContent,
} from '../../../../components/TransactionConfirmationModal'
import { Kind, LimitOrderContext, MarketPrices } from '../../../../services/LimitOrders'
import { calculateMarketPriceDiffPercentage } from '../../LimitOrder/Components/utils'

import { ConfirmationFooter } from './ConfirmationFooter'
import { ConfirmationHeader } from './ConfirmationHeader'

interface ConfirmLimitOrderModalProps {
isOpen: boolean
attemptingTxn: boolean
errorMessage: string | undefined
onDismiss: () => void
onConfirm: () => void
marketPrices: MarketPrices
fiatValueInput: CurrencyAmount | null
fiatValueOutput: CurrencyAmount | null
}

export default function ConfirmLimitOrderModal({
onConfirm,
onDismiss,
errorMessage,
isOpen,
attemptingTxn,
marketPrices,
fiatValueInput,
fiatValueOutput,
}: ConfirmLimitOrderModalProps) {
const { limitOrder, buyAmount, sellAmount, limitPrice, expiresAt, expiresAtUnit, kind } =
useContext(LimitOrderContext)

//hardcoded for now
const market = 'CoW Protocol'

const modalHeader = useCallback(() => {
return (
<ConfirmationHeader
fiatValueInput={fiatValueInput}
fiatValueOutput={fiatValueOutput}
buyToken={buyAmount}
sellToken={sellAmount}
/>
)
}, [fiatValueInput, fiatValueOutput, buyAmount, sellAmount])

const [baseTokenAmount, quoteTokenAmount] = kind === Kind.Sell ? [sellAmount, buyAmount] : [buyAmount, sellAmount]
const askPrice = `${kind} ${baseTokenAmount?.currency?.symbol} at ${limitPrice} ${quoteTokenAmount?.currency?.symbol}`

let { marketPriceDiffPercentage, isDiffPositive } = calculateMarketPriceDiffPercentage(
limitOrder!.kind,
marketPrices,
limitPrice!
)
const expiresInFormatted = `${expiresAt} ${expiresAtUnit}`

const modalBottom = useCallback(() => {
return onConfirm ? (
<ConfirmationFooter
onConfirm={onConfirm}
askPrice={askPrice}
expiresIn={expiresInFormatted}
marketPriceDifference={marketPriceDiffPercentage.toFixed(2)}
market={market}
isDiffPositive={isDiffPositive}
/>
) : null
}, [marketPriceDiffPercentage, isDiffPositive, onConfirm, askPrice, expiresInFormatted])

// text to show while loading
const pendingText = 'Confirm Signature'

const confirmationContent = useCallback(
() =>
errorMessage ? (
<TransactionErrorContent onDismiss={onDismiss} message={errorMessage} />
) : (
<ConfirmationModalContent
title="Confirm Limit Order"
onDismiss={onDismiss}
topContent={modalHeader}
bottomContent={modalBottom}
/>
),
[onDismiss, modalBottom, modalHeader, errorMessage]
)

return (
<TransactionConfirmationModal
isOpen={isOpen}
onDismiss={onDismiss}
attemptingTxn={attemptingTxn}
content={confirmationContent}
pendingText={pendingText}
/>
)
}
Loading

0 comments on commit 04912ba

Please sign in to comment.