Skip to content

Commit

Permalink
Add rhf and transaction into modal
Browse files Browse the repository at this point in the history
  • Loading branch information
WRadoslaw committed Oct 3, 2023
1 parent 4e2417d commit 53e0413
Showing 1 changed file with 106 additions and 35 deletions.
141 changes: 106 additions & 35 deletions packages/atlas/src/components/_crt/SellTokenModal/SellTokenModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo, useState } from 'react'
import { useMemo } from 'react'
import { Controller, useForm } from 'react-hook-form'

import { FlexBox } from '@/components/FlexBox/FlexBox'
import { Information } from '@/components/Information'
import { JoyTokenIcon } from '@/components/JoyTokenIcon'
import { NumberFormat } from '@/components/NumberFormat'
import { Text } from '@/components/Text'
Expand All @@ -10,7 +10,12 @@ import { FormField } from '@/components/_inputs/FormField'
import { TokenInput } from '@/components/_inputs/TokenInput'
import { DetailsContent } from '@/components/_nft/NftTile'
import { DialogModal } from '@/components/_overlays/DialogModal'
import { atlasConfig } from '@/config'
import { useMediaMatch } from '@/hooks/useMediaMatch'
import { useFee, useJoystream, useTokenPrice } from '@/providers/joystream'
import { useSnackbar } from '@/providers/snackbars'
import { useTransaction } from '@/providers/transactions/transactions.hooks'
import { useUser } from '@/providers/user/user.hooks'

export type SellTokenModalProps = {
tokenId: string
Expand All @@ -25,47 +30,104 @@ const getTokenDetails = (_: string) => ({
})

export const SellTokenModal = ({ tokenId, onClose }: SellTokenModalProps) => {
const [tokens, setTokens] = useState<number | null>(null)
const { control, watch, handleSubmit } = useForm<{ tokens: number }>()
const { convertTokensToUSD } = useTokenPrice()
const smMatch = useMediaMatch('sm')
const { memberId } = useUser()
const { pricePerUnit, tokensOnSale, userBalance, title } = getTokenDetails(tokenId)

const tokens = watch('tokens')
const { joystream, proxyCallback } = useJoystream()
const handleTransaction = useTransaction()
const { displaySnackbar } = useSnackbar()
const { fullFee } = useFee('sellTokenOnMarketTx')
const details = useMemo(
() => [
{
title: 'You will get',
title: 'You will receive',
content: (
<NumberFormat
value={tokens || 0}
value={tokens ? tokens * pricePerUnit : 0}
format={(tokens || 0) > 1_000_000 ? 'short' : 'full'}
as="p"
variant="t200-strong"
withToken
/>
),
},
{
title: 'Purchase',
content: (
<NumberFormat
value={tokens}
as="p"
variant="t200"
withDenomination="before"
withToken
customTicker={`$${title}`}
/>
),
tooltipText: 'Lorem ipsum',
},
{
title: 'Fee',
content: <NumberFormat value={tokensOnSale} as="p" variant="t200" withDenomination="before" withToken />,
tooltipText: 'Lorem ipsum',
title: 'Platform fee', // todo: introduce platform fee
content: <NumberFormat value={2} as="p" variant="t200" withDenomination="before" withToken />,
},
{
title: 'Transaction fee',
content: <NumberFormat value={fullFee} as="p" variant="t200" withDenomination="before" withToken />,
},
{
title: 'You will spend',
content: <NumberFormat value={tokensOnSale} as="p" variant="t200" withDenomination="before" withToken />,
tooltipText: 'Lorem ipsum',
title: 'Total',
content: (
<FlexBox alignItems="start">
<NumberFormat value={tokensOnSale} as="p" variant="t200-strong" withToken customTicker={`$${title}`} />
<Text variant="t200-strong" as="p" color="colorText">
+
</Text>
<NumberFormat value={fullFee.addn(2)} as="p" variant="t200-strong" withDenomination withToken />
</FlexBox>
),
},
],
[title, tokens, tokensOnSale]
[fullFee, pricePerUnit, title, tokens, tokensOnSale]
)

const onSubmit = () =>
handleSubmit((data) => {
if (!joystream || !memberId) {
return
}
handleTransaction({
txFactory: async (updateStatus) =>
(await joystream.extrinsics).sellTokenOnMarket(
tokenId,
memberId,
String(data.tokens),
proxyCallback(updateStatus)
),
onError: () => {
displaySnackbar({
title: 'Something went wrong',
iconType: 'error',
})
},
onTxSync: async () => {
displaySnackbar({
title: `${tokens * pricePerUnit} ${atlasConfig.joystream.tokenTicker} received`,
description: `${tokens} $${title} sold`,
})
onClose()
},
})
})()

return (
<DialogModal
title={`Sell $${title}`}
show
onExitClick={onClose}
primaryButton={{
text: 'Sell tokens',
onClick: onSubmit,
}}
>
<FlexBox flow="column" gap={8}>
Expand All @@ -87,31 +149,40 @@ export const SellTokenModal = ({ tokenId, onClose }: SellTokenModalProps) => {
withDenomination
/>
</FlexBox>
<FormField label="Tokens to spend">
<TokenInput
value={tokens}
onChange={setTokens}
placeholder="0"
nodeEnd={
<FlexBox gap={2} alignItems="baseline">
<Text variant="t300" as="p" color="colorTextMuted">
$0.00
</Text>
<TextButton>Max</TextButton>
</FlexBox>
}
/>
</FormField>
<Controller
name="tokens"
control={control}
rules={{
max: {
value: userBalance,
message: 'Amount exceeds your account balance',
},
}}
render={({ field }) => (
<FormField label="Tokens to spend">
<TokenInput
value={field.value}
onChange={field.onChange}
placeholder="0"
nodeEnd={
<FlexBox gap={2} alignItems="baseline">
<Text variant="t300" as="p" color="colorTextMuted">
${convertTokensToUSD(field.value * pricePerUnit)?.toFixed(2)}
</Text>
<TextButton onClick={() => field.onChange(userBalance)}>Max</TextButton>
</FlexBox>
}
/>
</FormField>
)}
/>

<FlexBox flow="column" gap={2}>
{details.map((row, i) => (
<FlexBox key={row.title} alignItems="center" justifyContent="space-between">
<FlexBox width="fit-content" alignItems="center">
<Text variant={i + 1 === details.length ? 't200-strong' : 't200'} as="p" color="colorText">
{row.title}
</Text>
<Information text={row.tooltipText} />
</FlexBox>
<Text variant={i + 1 === details.length ? 't200-strong' : 't200'} as="p" color="colorText">
{row.title}
</Text>
{row.content}
</FlexBox>
))}
Expand Down

0 comments on commit 53e0413

Please sign in to comment.