set up form validation for undelegation

This commit is contained in:
fmtabbara
2021-09-06 11:12:39 +01:00
parent 7cff72757b
commit 01d2df7bb7
8 changed files with 148 additions and 63 deletions
@@ -11,12 +11,12 @@ export enum EnumRequestStatus {
export const RequestStatus = ({
status,
onSuccess,
onError,
Success,
Error,
}: {
status: EnumRequestStatus
onSuccess: () => void
onError: () => void
Success: React.ReactNode
Error: React.ReactNode
}) => {
const theme: Theme = useTheme()
return (
@@ -26,8 +26,8 @@ export const RequestStatus = ({
<CircularProgress size={48} />
</div>
)}
{status === EnumRequestStatus.success && onSuccess()}
{status === EnumRequestStatus.error && onError()}
{status === EnumRequestStatus.success && Success}
{status === EnumRequestStatus.error && Error}
</div>
)
}
+5 -5
View File
@@ -2,13 +2,13 @@ import React, { useState } from 'react'
import { Button, Theme } from '@material-ui/core'
import { Alert } from '@material-ui/lab'
import { useTheme } from '@material-ui/styles'
import { BondForm } from './BondForm'
import { NymCard } from '../../components'
import {
EnumRequestStatus,
RequestStatus,
} from '../../components/RequestStatus'
import { Layout } from '../../layouts'
import { BondForm } from './BondForm'
export const Bond = () => {
const [status, setStatus] = useState(EnumRequestStatus.initial)
@@ -36,14 +36,14 @@ export const Bond = () => {
<>
<RequestStatus
status={status}
onSuccess={() => (
Success={
<Alert severity="success">Successfully bonded node</Alert>
)}
onError={() => (
}
Error={
<Alert severity="error">
An error occurred with the request: {message}
</Alert>
)}
}
/>
<div
style={{
@@ -1,6 +1,7 @@
import React from 'react'
import {
Button,
CircularProgress,
FormControl,
Grid,
InputAdornment,
@@ -40,7 +41,7 @@ export const DelegateForm = ({
setValue,
watch,
handleSubmit,
formState: { errors },
formState: { errors, isSubmitting },
} = useForm<TDelegateForm>({
defaultValues,
resolver: yupResolver(validationSchema),
@@ -48,8 +49,8 @@ export const DelegateForm = ({
const watchNodeType = watch('nodeType', defaultValues.nodeType)
const onSubmit = (data: TDelegateForm) => {
invoke('delegate_to_mixnode', {
const onSubmit = async (data: TDelegateForm) => {
await invoke('delegate_to_mixnode', {
identity: data.identity,
amount: { denom: 'punk', amount: data.amount },
})
@@ -119,10 +120,12 @@ export const DelegateForm = ({
>
<Button
onClick={handleSubmit(onSubmit)}
disabled={isSubmitting}
variant="contained"
color="primary"
type="submit"
disableElevation
endIcon={isSubmitting && <CircularProgress size={20} />}
>
Delegate stake
</Button>
+5 -4
View File
@@ -31,8 +31,9 @@ export const Delegate = () => {
setStatus(EnumRequestStatus.error)
setMessage(message)
}}
onSuccess={() => {
onSuccess={(message?: string) => {
setStatus(EnumRequestStatus.success)
setMessage(message)
}}
/>
)}
@@ -40,12 +41,12 @@ export const Delegate = () => {
<>
<RequestStatus
status={status}
onError={() => (
Error={
<Alert severity="error">
An error occurred with the request: {message}
</Alert>
)}
onSuccess={() => {}}
}
Success={<Alert severity="success">{message}</Alert>}
/>
<div
style={{
+3 -1
View File
@@ -17,7 +17,9 @@ import { ClientContext } from '../context/main'
import { TClientDetails } from '../types/global'
export const SignIn = () => {
const [mnemonic, setMnemonic] = useState<string>('')
const [mnemonic, setMnemonic] = useState<string>(
'alley mutual arrange escape army vacuum cherry ozone frame steel current smile dad subject primary foster lazy want perfect fury general eye cannon motor'
)
const [inputError, setInputError] = useState<string | undefined>()
const [isLoading, setIsLoading] = useState(false)
@@ -1,78 +1,111 @@
import React, { useState } from 'react'
import { Alert } from '@material-ui/lab'
import { Button, Grid, TextField, Theme } from '@material-ui/core'
import { useGetBalance } from '../../hooks/useGetBalance'
import React from 'react'
import { useForm } from 'react-hook-form'
import {
Button,
CircularProgress,
FormControl,
Grid,
TextField,
Theme,
} from '@material-ui/core'
import { useTheme } from '@material-ui/styles'
import { invoke } from '@tauri-apps/api'
import { yupResolver } from '@hookform/resolvers/yup'
import { validationSchema } from './validationSchema'
import { NodeTypeSelector } from '../../components/NodeTypeSelector'
import { EnumNodeType } from '../../types/global'
import { useTheme } from '@material-ui/styles'
export const UndelegateForm = () => {
const [isValidAmount, setIsValidAmount] = useState(true)
const [validIdentity, setValidIdentity] = useState(true)
const [allocationWarning, setAllocationWarning] = useState<string>()
const [nodeType, setNodeType] = useState(EnumNodeType.Mixnode)
type TFormData = {
nodeType: EnumNodeType
identity: string
}
const defaultValues = {
nodeType: EnumNodeType.Mixnode,
identity: '',
}
export const UndelegateForm = ({
onError,
onSuccess,
}: {
onError: (message?: string) => void
onSuccess: (message?: string) => void
}) => {
const {
handleSubmit,
register,
setValue,
watch,
formState: { errors, isSubmitting },
} = useForm<TFormData>({
defaultValues,
resolver: yupResolver(validationSchema),
})
const watchNodeType = watch('nodeType')
const onSubmit = async (data: TFormData) => {
await invoke('undelegate_from_mixnode', { identity: data.identity })
.then((res: any) => onSuccess(res))
.catch((e) => onError(e))
}
const { getBalance, accountBalance } = useGetBalance()
const theme: Theme = useTheme()
const handleAmountChange = (event: any) => {
// don't ask me about that. javascript works in mysterious ways
// and this is apparently a good way of checking if string
// is purely made of numeric characters
const parsed = +event.target.value
if (isNaN(parsed)) {
setIsValidAmount(false)
} else {
try {
const allocationCheck = { error: undefined, message: '' }
if (allocationCheck.error) {
setAllocationWarning(allocationCheck.message)
setIsValidAmount(false)
} else {
setAllocationWarning(allocationCheck.message)
setIsValidAmount(true)
}
} catch {
setIsValidAmount(false)
}
}
// const parsed = +event.target.value
// if (isNaN(parsed)) {
// setIsValidAmount(false)
// } else {
// try {
// const allocationCheck = { error: undefined, message: '' }
// if (allocationCheck.error) {
// setAllocationWarning(allocationCheck.message)
// setIsValidAmount(false)
// } else {
// setAllocationWarning(allocationCheck.message)
// setIsValidAmount(true)
// }
// } catch {
// setIsValidAmount(false)
// }
// }
}
return (
<form onSubmit={() => {}}>
<FormControl fullWidth>
<div style={{ padding: theme.spacing(3, 5) }}>
<Grid container spacing={3} direction="column">
<Grid item xs={12}>
<NodeTypeSelector
nodeType={nodeType}
setNodeType={(nodeType) => setNodeType(nodeType)}
nodeType={watchNodeType}
setNodeType={(nodeType) => setValue('nodeType', nodeType)}
/>
</Grid>
<Grid item xs={12}>
<TextField
{...register('identity')}
required
variant="outlined"
id="identity"
name="identity"
label="Node identity"
error={!validIdentity}
helperText={
validIdentity
? ''
: "Please enter a valid identity like '824WyExLUWvLE2mpSHBatN4AoByuLzfnHFeHWiBYzg4z'"
}
error={!!errors.identity}
helperText={errors.identity?.message}
fullWidth
/>
</Grid>
{allocationWarning && (
{/* {allocationWarning && (
<Grid item xs={12} lg={6}>
<Alert severity={!isValidAmount ? 'error' : 'info'}>
{allocationWarning}
</Alert>
</Grid>
)}
)} */}
</Grid>
</div>
<div
@@ -86,15 +119,17 @@ export const UndelegateForm = () => {
}}
>
<Button
onClick={handleSubmit(onSubmit)}
variant="contained"
color="primary"
type="submit"
disabled={!isValidAmount}
disableElevation
disabled={isSubmitting}
endIcon={isSubmitting && <CircularProgress size={20} />}
>
Undelegate stake
</Button>
</div>
</form>
</FormControl>
)
}
+36 -2
View File
@@ -1,9 +1,19 @@
import React from 'react'
import React, { useState } from 'react'
import { NymCard } from '../../components'
import { UndelegateForm } from './UndelegateForm'
import { Layout } from '../../layouts'
import {
EnumRequestStatus,
RequestStatus,
} from '../../components/RequestStatus'
import { Alert } from '@material-ui/lab'
export const Undelegate = () => {
const [message, setMessage] = useState<string>()
const [status, setStaus] = useState<EnumRequestStatus>(
EnumRequestStatus.initial
)
return (
<Layout>
<NymCard
@@ -11,7 +21,31 @@ export const Undelegate = () => {
subheader="Undelegate from a mixnode or gateway"
noPadding
>
<UndelegateForm />
<>
{status === EnumRequestStatus.initial && (
<UndelegateForm
onError={(message) => {
setMessage(message)
setStaus(EnumRequestStatus.error)
}}
onSuccess={(message) => {
setMessage(message)
setStaus(EnumRequestStatus.success)
}}
/>
)}
{status !== EnumRequestStatus.initial && (
<RequestStatus
status={status}
Error={
<Alert severity="error">
An error occurred with the request: {message}
</Alert>
}
Success={<Alert severity="success">{message}</Alert>}
/>
)}
</>
</NymCard>
</Layout>
)
@@ -0,0 +1,10 @@
import * as Yup from 'yup'
import { validateKey } from '../../utils'
export const validationSchema = Yup.object().shape({
identity: Yup.string()
.required()
.test('valid-id-key', 'A valid identity key is required', function (value) {
return validateKey(value || '')
}),
})