Skip to content

Commit

Permalink
馃槰 ChangeNOW modal adjustements v2 (Joystream#6041)
Browse files Browse the repository at this point in the history
* Add callbacks to action buttons

* Hide estimated arrival if undefined and restrict rate to 10 decimal places

* Validate first input against user balance in sell scenario
  • Loading branch information
WRadoslaw committed Apr 22, 2024
1 parent e9aeb87 commit 4328f50
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const ChangeNowModal = ({ type, onClose }: ChangeNowModalProps) => {
if (primaryButtonProps) {
return {
text: 'Go to dashboard',
onClick: () => onClose(),
to: absoluteRoutes.viewer.portfolio(),
}
}
Expand Down
14 changes: 13 additions & 1 deletion packages/atlas/src/components/ChangeNowModal/steps/FormStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { FormField } from '@/components/_inputs/FormField'
import { Input } from '@/components/_inputs/Input'
import { TokenInput, TokenInputProps } from '@/components/_inputs/TokenInput'
import { Spinner } from '@/components/_loaders/Spinner'
import { hapiBnToTokenNumber } from '@/joystream-lib/utils'
import { useSubscribeAccountBalance } from '@/providers/joystream'
import { useSnackbar } from '@/providers/snackbars'
import { square } from '@/styles'
import {
Expand All @@ -23,6 +25,7 @@ import {
changeNowService,
} from '@/utils/ChangeNowService'
import { SentryLogger } from '@/utils/logs'
import { formatSmallDecimal } from '@/utils/number'

type CurrencyInputValues = {
amount: number
Expand All @@ -46,10 +49,13 @@ type FormStepProps = {

export const FormStep = ({ setPrimaryButtonProps, onSubmit, type, initialValues }: FormStepProps) => {
const { displaySnackbar } = useSnackbar()
const { accountBalance } = useSubscribeAccountBalance()
const [isLoadingRate, setIsLoadingRate] = useState<'to' | 'from' | null>(null)
const debouncedExchangeEstimation = useRef<DebouncedFunc<
(amount: number, type: 'from' | 'to') => Promise<void>
> | null>(null)
const isSellingJoy = type === 'sell'

const { data } = useQuery('changenow-currency', () => changeNowService.getAvailableCurrencies(), {
onSuccess: (data) => {
const currencyOptions = data.map((curr) => ({
Expand Down Expand Up @@ -179,6 +185,12 @@ export const FormStep = ({ setPrimaryButtonProps, onSubmit, type, initialValues
if (!value.currency) {
return 'Please choose currency'
}

if (isSellingJoy && accountBalance) {
if (value.amount > hapiBnToTokenNumber(accountBalance)) {
return 'Amount exceeds your balance'
}
}
},
}}
render={({ field: { value, onChange } }) => {
Expand Down Expand Up @@ -285,7 +297,7 @@ export const FormStep = ({ setPrimaryButtonProps, onSubmit, type, initialValues
/>
{from.currency && to.currency && (
<Text variant="t200" as="p" color={isLoadingRate ? 'colorTextMuted' : 'colorText'}>
Estimated rate: 1 {from.currency.toUpperCase()} ~ {to.amount / from.amount || 'N/A'}{' '}
Estimated rate: 1 {from.currency.toUpperCase()} ~ {formatSmallDecimal(to.amount / from.amount) || 'N/A'}{' '}
{to.currency.toUpperCase()}
</Text>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ type ProgressStepProps = {
transactionData: TransactionData
} & CommonProps

export const ProgressStep = ({ transactionData, type, setPrimaryButtonProps, goToStep }: ProgressStepProps) => {
export const ProgressStep = ({
transactionData,
type,
setPrimaryButtonProps,
goToStep,
onClose,
}: ProgressStepProps) => {
const [retry, setRetry] = useState(true)
const isSellingJoy = type === 'sell'
const steps = isSellingJoy ? sellSteps : buySteps
Expand Down Expand Up @@ -118,13 +124,13 @@ export const ProgressStep = ({ transactionData, type, setPrimaryButtonProps, goT
setRetry(false)
setPrimaryButtonProps({
text: 'Close',
onClick: () => undefined,
onClick: () => onClose(),
})
step = steps.length
extraContent = successText
}
return [step, steps[step]?.[1], extraContent]
}, [data, isSellingJoy, setPrimaryButtonProps, steps, transactionData.hasAutomaticTransactionSucceeded])
}, [data, isSellingJoy, onClose, setPrimaryButtonProps, steps, transactionData.hasAutomaticTransactionSucceeded])

return (
<FlexBox gap={6} flow="column">
Expand Down
33 changes: 22 additions & 11 deletions packages/atlas/src/components/ChangeNowModal/steps/SummaryStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { cVar, sizes } from '@/styles'
import { changeNowService } from '@/utils/ChangeNowService'
import { formatJoystreamAddress } from '@/utils/address'
import { shortenString } from '@/utils/misc'
import { formatSmallDecimal } from '@/utils/number'
import { formatDurationShort, getTimeDiffInSeconds } from '@/utils/time'

import { FormData } from './FormStep'
Expand All @@ -43,6 +44,7 @@ export const SummaryStep = ({
}: SummaryStepProps) => {
const [termsAccepted, setTermsAccepted] = useState(false)
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const [timeDiff, setTimeDiff] = useState<number | undefined>(undefined)
const { activeMembership } = useUser()
const { currentUser } = useAuth()
Expand All @@ -61,6 +63,7 @@ export const SummaryStep = ({
}
const isSellingJoy = type === 'sell'
const refundAddress = isSellingJoy ? activeMembership.controllerAccount : undefined
setLoading(true)
const txData = await changeNowService
.createExchangeTransaction({
refundAddress,
Expand All @@ -74,13 +77,15 @@ export const SummaryStep = ({
})
.then((res) => res.data)
.catch(() => {
setLoading(false)
displaySnackbar({
title: 'Transaction creation failed',
description: 'Please try again, if the problem persists contact support.',
})
})

if (!txData) {
setLoading(false)
return
}

Expand Down Expand Up @@ -110,6 +115,9 @@ export const SummaryStep = ({
})
goToStep(ChangeNowModalStep.PROGRESS)
},
onError: () => {
setLoading(false)
},
})
} else {
goToStep(ChangeNowModalStep.PROGRESS)
Expand All @@ -136,7 +144,8 @@ export const SummaryStep = ({

useEffect(() => {
setPrimaryButtonProps({
text: 'Next',
text: loading ? 'Next' : 'Waiting...',
disabled: loading,
onClick: async () => {
if (termsAccepted && validUntil) {
const timeDiff = getTimeDiffInSeconds(new Date(validUntil))
Expand All @@ -150,7 +159,7 @@ export const SummaryStep = ({
}
},
})
}, [goToStep, onTransactionSubmit, setPrimaryButtonProps, termsAccepted, validUntil])
}, [goToStep, loading, onTransactionSubmit, setPrimaryButtonProps, termsAccepted, validUntil])

useMountEffect(() => {
if (!validUntil) {
Expand Down Expand Up @@ -204,14 +213,16 @@ export const SummaryStep = ({
</Text>
</FlexBox>

<FlexBox width="100%" justifyContent="space-between">
<Text variant="t200" as="p" color="colorText">
Estimated Arrival
</Text>
<Text variant="t200" as="p">
{estimatedArrival ? new Date(estimatedArrival).toDateString() : 'N/A'}
</Text>
</FlexBox>
{estimatedArrival ? (
<FlexBox width="100%" justifyContent="space-between">
<Text variant="t200" as="p" color="colorText">
Estimated Arrival
</Text>
<Text variant="t200" as="p">
{new Date(estimatedArrival).toDateString()}
</Text>
</FlexBox>
) : null}

<FlexBox width="100%" justifyContent="space-between">
<Text variant="t200" as="p" color="colorText">
Expand All @@ -227,7 +238,7 @@ export const SummaryStep = ({
Estimated Rate
</Text>
<Text variant="t200" as="p">
1 {fromTicker} ~ {to.amount / from.amount} {toTicker}
1 {fromTicker} ~ {formatSmallDecimal(to.amount / from.amount)} {toTicker}
</Text>
</FlexBox>

Expand Down
2 changes: 1 addition & 1 deletion packages/atlas/src/utils/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const getRandomIntInclusive = (min: number, max: number) => {
}

const numberFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 })
const smallDecimalFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: 6 })
const smallDecimalFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: 10 })

export const formatNumber = (num: number): string => {
return numberFormatter.format(num).replaceAll(',', ' ')
Expand Down

0 comments on commit 4328f50

Please sign in to comment.