Skip to content

Commit

Permalink
Merge pull request #21 from shapeshift/amount-component
Browse files Browse the repository at this point in the history
feat: bring in the amount component
  • Loading branch information
reallybeard authored Jan 8, 2024
2 parents 70be266 + 9d4f858 commit 782e52a
Show file tree
Hide file tree
Showing 5 changed files with 548 additions and 9 deletions.
180 changes: 180 additions & 0 deletions src/components/Amount/Amount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import type { TextProps } from '@chakra-ui/react'
import { Text, useColorModeValue } from '@chakra-ui/react'
import { useMemo } from 'react'
import type { NumberFormatOptions } from 'hooks/useLocaleFormatter/useLocaleFormatter'
import { useLocaleFormatter } from 'hooks/useLocaleFormatter/useLocaleFormatter'

export type AmountProps = {
value: number | string
prefix?: string
suffix?: string
omitDecimalTrailingZeros?: boolean
abbreviated?: boolean
maximumFractionDigits?: number
} & TextProps

export function Amount({
value,
prefix = '',
suffix = '',
maximumFractionDigits,
omitDecimalTrailingZeros = false,
abbreviated = false,
...props
}: any): React.ReactElement {
const {
number: { toString },
} = useLocaleFormatter()

return (
<Text {...props}>
{prefix}
{toString(value, { maximumFractionDigits, omitDecimalTrailingZeros, abbreviated })}
{suffix}
</Text>
)
}

type CryptoAmountProps = {
value: string
symbol: string
cryptoSymbolStyle?: TextProps
maximumFractionDigits?: number
} & AmountProps

type FiatAmountProps = {
fiatSymbolStyle?: TextProps
fiatType?: string
} & AmountProps

type PercentAmountProps = AmountProps & {
options?: NumberFormatOptions
autoColor?: boolean
}

const Crypto = ({
value,
symbol,
cryptoSymbolStyle,
maximumFractionDigits = 8,
prefix,
suffix,
omitDecimalTrailingZeros = false,
...props
}: CryptoAmountProps) => {
const {
number: { toCrypto, toParts },
} = useLocaleFormatter()

const crypto = toCrypto(value, symbol, { maximumFractionDigits, omitDecimalTrailingZeros })

if (!cryptoSymbolStyle) {
return (
<Text {...props}>
{prefix && `${prefix} `}
{crypto}
{suffix && ` ${suffix}`}
</Text>
)
}

const parts = toParts(crypto)

return (
<Text {...props}>
{parts.prefix && (
<Text {...props} {...cryptoSymbolStyle}>
{parts.prefix}
</Text>
)}
{parts.number}
{parts.postfix && (
<Text {...props} {...cryptoSymbolStyle}>
{parts.postfix}
</Text>
)}
</Text>
)
}

const Fiat = ({
value,
fiatSymbolStyle,
fiatType,
prefix,
suffix,
maximumFractionDigits,
omitDecimalTrailingZeros = false,
abbreviated = false,
...props
}: FiatAmountProps) => {
const {
number: { toFiat, toParts },
} = useLocaleFormatter({ fiatType })

const fiat = toFiat(value, {
fiatType,
omitDecimalTrailingZeros,
abbreviated,
maximumFractionDigits,
})

if (!fiatSymbolStyle) {
return (
<Text {...props}>
{prefix && `${prefix} `}
{fiat}
{suffix && ` ${suffix}`}
</Text>
)
}

const parts = toParts(fiat)

return (
<Text {...props}>
{parts.prefix && (
<Text {...props} {...fiatSymbolStyle}>
{parts.prefix}
</Text>
)}
{parts.number}
{parts.postfix && (
<Text {...props} {...fiatSymbolStyle}>
{parts.postfix}
</Text>
)}
</Text>
)
}

const Percent = ({ value, autoColor, options, prefix, suffix, ...props }: PercentAmountProps) => {
const {
number: { toPercent },
} = useLocaleFormatter()
const formattedNumber = toPercent(value, options)
const red = useColorModeValue('red.800', 'red.500')
const green = useColorModeValue('green.500', 'green.200')
const color = useMemo(() => {
const roundedValue = parseFloat(formattedNumber)
if (roundedValue === 0) {
return green
}
if (roundedValue > 0) {
return green
}
return red
}, [formattedNumber, green, red])

return (
<Text color={autoColor ? color : 'inherit'} {...props}>
{prefix && `${prefix} `}
{formattedNumber}
{suffix && ` ${suffix}`}
</Text>
)
}

Amount.Crypto = Crypto
Amount.Fiat = Fiat
Amount.Percent = Percent
14 changes: 9 additions & 5 deletions src/components/Status/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from '@chakra-ui/react'
import { useCallback, useMemo } from 'react'
import { FaArrowDown, FaArrowRightArrowLeft, FaCheck, FaRegCopy } from 'react-icons/fa6'
import { Amount } from 'components/Amount/Amount'
import { useCopyToClipboard } from 'hooks/useCopyToClipboard'
import { BTCImage, ETHImage } from 'lib/const'

Expand Down Expand Up @@ -88,7 +89,7 @@ export const Status = () => {
<Text fontWeight='bold'>Send</Text>
<Flex alignItems='center' gap={2}>
<Avatar size='sm' src={BTCImage} />
<Text>0.002 BTC</Text>
<Amount.Crypto value='0.002' symbol='BTC' />
</Flex>
</Stack>
<Stack>
Expand All @@ -112,7 +113,7 @@ export const Status = () => {
<Text fontWeight='bold'>You will receive</Text>
<Flex gap={2} alignItems='center'>
<Avatar size='xs' src={ETHImage} />
<Text>0.000158162 ETH</Text>
<Amount.Crypto value='0.000158162' symbol='ETH' />
</Flex>
</Stack>
</Stack>
Expand All @@ -133,7 +134,7 @@ export const Status = () => {
<Avatar size='xs' src={BTCImage} />
<Text>Deposit</Text>
</Flex>
<Text color='text.subtle'>0.002 BTC</Text>
<Amount.Crypto value='0.002' symbol='BTC' />
</Flex>
<Flex alignItems='center' gap={2}>
<Text>bc1q8n6t65jpm6k048ejvwgfa69xp5laqr2sexx7gl</Text>
Expand All @@ -152,7 +153,7 @@ export const Status = () => {
<Avatar size='xs' src={ETHImage} />
<Text>Receive</Text>
</Flex>
<Text color='text.subtle'>0.00158162 ETH</Text>
<Amount.Crypto value='0.00158162' symbol='ETH' />
</Flex>
<Flex alignItems='center' gap={2}>
<Text>0x1234484844949494949</Text>
Expand All @@ -161,7 +162,10 @@ export const Status = () => {
<Divider borderColor='border.base' />
<Flex alignItems='center' justifyContent='space-between'>
<Text>Estimated Rate</Text>
<Text>1 BTC = 12.90126 ETH</Text>
<Flex gap={1}>
<Amount.Crypto value='1' symbol='BTC' suffix='=' />
<Amount.Crypto value='12.90126' symbol='ETH' />
</Flex>
</Flex>
</CardFooter>
</Card>
Expand Down
19 changes: 15 additions & 4 deletions src/components/TradeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { FaArrowRightArrowLeft } from 'react-icons/fa6'
import { useNavigate } from 'react-router-dom'
import { BTCImage, ETHImage } from 'lib/const'

import { Amount } from './Amount/Amount'

export const TradeInput = () => {
const navigate = useNavigate()
const Divider = useMemo(() => <StackDivider borderColor='border.base' />, [])
Expand Down Expand Up @@ -48,20 +50,29 @@ export const TradeInput = () => {
bg='background.surface.raised.base'
>
<Text color='text.subtle'>Your rate</Text>
<Text>1 BTC = 12.90126 ETH</Text>
<Flex gap={1}>
<Amount.Crypto value='1' symbol='BTC' suffix='=' />
<Amount.Crypto value='12.90126' symbol='ETH' />
</Flex>
</Flex>
<HStack divider={Divider} fontSize='sm'>
<Stat size='sm' textAlign='center' py={4}>
<StatLabel color='text.subtle'>Deposit This</StatLabel>
<StatNumber>0.002 BTC</StatNumber>
<StatNumber>
<Amount.Crypto value='0.002' symbol='BTC' />
</StatNumber>
</Stat>
<Stat size='sm' textAlign='center' py={4}>
<StatLabel color='text.subtle'>To Get This</StatLabel>
<StatNumber>0.0248 ETH</StatNumber>
<StatNumber>
<Amount.Crypto value='0.0248' symbol='ETH' />
</StatNumber>
</Stat>
<Stat size='sm' textAlign='center' py={4}>
<StatLabel color='text.subtle'>Miner Fee</StatLabel>
<StatNumber>$10</StatNumber>
<StatNumber>
<Amount.Fiat value='10' />
</StatNumber>
</Stat>
</HStack>
</CardHeader>
Expand Down
Loading

0 comments on commit 782e52a

Please sign in to comment.