Merge branch 'hn.validator-onboarding' of github.com:nimbus-gui/nimbus-gui into ia.responsive-css

This commit is contained in:
Ivana Andersson 2023-09-07 15:12:49 +03:00
commit 4dc83a834a
13 changed files with 238 additions and 17 deletions

View File

@ -1,12 +1,25 @@
import { Stack, XStack, YStack } from 'tamagui'
import { Input as StatusInput, Text } from '@status-im/components'
import { AddIcon, ChevronDownIcon } from '@status-im/icons'
import { useState } from 'react'
type SetupRowProps = {
title: string
}
const SetupRow = ({ title }: SetupRowProps) => {
const [validatorCount, setValidatorCount] = useState(0)
const addValidatorHandler = () => {
setValidatorCount((state: number) => state + 1)
}
const changeValidatorCountHandler = (e: any) => {
if (!isNaN(e.target.value)) {
setValidatorCount(Number(e.target.value))
}
}
return (
<YStack space={'$4'}>
<Text size={19} weight={'semibold'}>
@ -17,7 +30,12 @@ const SetupRow = ({ title }: SetupRowProps) => {
<Text size={15} weight="regular" color={'#647084'}>
How many Validators would you like to run?
</Text>
<StatusInput icon={<AddIcon size={16} />} />
<StatusInput
icon={<AddIcon size={16} style={{ cursor: 'pointer' }} onClick={addValidatorHandler} />}
value={validatorCount.toString()}
onChange={changeValidatorCountHandler}
style={{ fontWeight: 'bold' }}
/>
</Stack>
<YStack space={'$2'}>
<Text size={15} weight={'semibold'} color="#09101C">

View File

@ -1,12 +1,23 @@
import { Stack, YStack } from 'tamagui'
import { InformationBox, Input as StatusInput, Text } from '@status-im/components'
import { ClearIcon, CloseCircleIcon } from '@status-im/icons'
import { useState } from 'react'
type WithdrawalAddressProps = {
title: string
}
const WithdrawalAddress = ({ title }: WithdrawalAddressProps) => {
const [withdrawalAddress, setWithdrawalAddress] = useState('')
const changeWithdrawalAddressHandler = (e: any) => {
setWithdrawalAddress(e.target.value)
}
const removeWithdrawalAddressHandler = () => {
setWithdrawalAddress('')
}
return (
<YStack space={'$4'}>
<Text size={19} weight={'semibold'}>
@ -20,7 +31,15 @@ const WithdrawalAddress = ({ title }: WithdrawalAddressProps) => {
<StatusInput
placeholder={'******************'}
width={'100%'}
icon={<ClearIcon size={16} />}
icon={
<ClearIcon
size={16}
style={{ cursor: 'pointer' }}
onClick={removeWithdrawalAddressHandler}
/>
}
value={withdrawalAddress}
onChange={changeWithdrawalAddressHandler}
/>
</Stack>
<InformationBox

View File

@ -8,13 +8,21 @@ import { RootState } from '../../redux/store'
type ContinueButton = {
continueHandler: () => void
activeStep: number
isConfirmPhraseStage: boolean
}
const ContinueButton = ({ continueHandler, activeStep }: ContinueButton) => {
const isCopyPastedPhrase = useSelector(
(state: RootState) => state.keyGeneration.isCopyPastedPhrase,
const ContinueButton = ({ continueHandler, activeStep, isConfirmPhraseStage }: ContinueButton) => {
const { isCopyPastedPhrase, isRightPhrase } = useSelector(
(state: RootState) => state.keyGeneration,
)
const isDisabled = () => {
if (isConfirmPhraseStage && !isRightPhrase) {
return true
}
return false
}
return (
<XStack style={{ width: '100%', marginTop: '16px', zIndex: 999, alignItems: 'center' }}>
<Stack style={{ width: '100%' }}>
@ -35,7 +43,7 @@ const ContinueButton = ({ continueHandler, activeStep }: ContinueButton) => {
marginTop: isCopyPastedPhrase ? '0px' : '40px',
}}
>
<Button onPress={continueHandler} size={40}>
<Button onPress={continueHandler} size={40} disabled={isDisabled()}>
{activeStep < 5 ? 'Continue' : 'Continue to Dashboard'}
</Button>
</Stack>

View File

@ -18,6 +18,7 @@ import ContinueButton from './ContinueButton'
import { setIsCopyPastedPhrase } from '../../redux/ValidatorOnboarding/KeyGeneration/slice'
import { RootState } from '../../redux/store'
import './layoutGradient.css'
import ActivationValidatorSetup from './ValidatorSetup/ActivationValidatorSetup'
const ValidatorOnboarding = () => {
const [activeStep, setActiveStep] = useState(0)
@ -37,7 +38,7 @@ const ValidatorOnboarding = () => {
const continueHandler = () => {
if (activeStep === 4 && isConfirmPhraseStage === false) {
setIsConfirmPhraseStage(true)
} else if (activeStep === 3 && subStepValidatorSetup < 2) {
} else if (activeStep === 3 && subStepValidatorSetup < 3) {
setSubStepValidatorSetup(subStepValidatorSetup + 1)
} else if (activeStep < 5) {
setActiveStep(activeStep + 1)
@ -81,11 +82,16 @@ const ValidatorOnboarding = () => {
{activeStep === 3 && subStepValidatorSetup === 0 && <ValidatorSetup />}
{activeStep === 3 && subStepValidatorSetup === 1 && <ValidatorSetupInstall />}
{activeStep === 3 && subStepValidatorSetup === 2 && <ConsensusSelection />}
{activeStep === 3 && subStepValidatorSetup === 3 && <ActivationValidatorSetup />}
{activeStep === 4 && <KeyGeneration isConfirmPhraseStage={isConfirmPhraseStage} />}
{activeStep === 5 && <Activation />}
</ValidatorBoxWrapper>
<ContinueButton activeStep={activeStep} continueHandler={continueHandler} />
<ContinueButton
activeStep={activeStep}
continueHandler={continueHandler}
isConfirmPhraseStage={isConfirmPhraseStage}
/>
</YStack>
</div>
)

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import ActivationValidatorSetup from './ActivationValidatorSetup'
import { withRouter } from 'storybook-addon-react-router-v6'
const meta = {
title: 'ValidatorOnboarding/ActivationValidatorSetup',
component: ActivationValidatorSetup,
tags: ['autodocs'],
decorators: [withRouter()],
} satisfies Meta<typeof ActivationValidatorSetup>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {},
}

View File

@ -0,0 +1,87 @@
import { useState, useEffect } from 'react'
import { XStack, Stack, YStack } from 'tamagui'
import { Text } from '@status-im/components'
import Confetti from 'react-confetti'
import LinkWithArrow from '../../../components/General/LinkWithArrow'
import ActivationCard from '../Activation/ActivationCard'
const styles = {
confettiContainer: {
position: 'relative' as const,
width: '100%',
height: '100%',
justifyContent: 'fit-content'
},
confettiCanvas: {
position: 'absolute' as const,
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: 0,
},
}
const ActivationValidatorSetup = () => {
const [showConfetti, setShowConfetti] = useState(true)
useEffect(() => {
const timer = setTimeout(() => {
setShowConfetti(false)
}, 10000)
return () => {
clearTimeout(timer)
}
}, [])
return (
<Stack style={styles.confettiContainer} width={'100%'} >
{showConfetti && <Confetti style={styles.confettiCanvas} />}
<YStack style={{ padding: '16px 32px' }}>
<YStack space={'$5'}>
<Text size={27} weight={'semibold'}>
Activation
</Text>
<Stack >
<Text size={27}>
Congratulations! You have successfully setup your Execution and Consensus clients and are currently syncing your nodes. You need to be sufficiently synced prior to setting up your validators and making a deposit.
</Text>
</Stack>
<YStack space={'$3'} marginTop={'10px'} width={'33%'} >
<XStack width={'151%'} space={'$3'} >
<ActivationCard
text="Execution Sync Status"
isGaugeIncluded={true}
gaugeColor={'#2a4af5'}
gaugeSynced={123.524}
gaugeTotal={172.503}
/>
<ActivationCard
text="Execution Sync Status"
isGaugeIncluded={true}
gaugeColor={'#EB5757'}
gaugeSynced={123.524}
gaugeTotal={172.503}
/>
</XStack>
<XStack space={'$3'}>
<ActivationCard text="Validator Queue" value="92603" />
<ActivationCard text="Estimated Activation Time" value="32 Days" />
<ActivationCard text="Current APR" value="4.40%" />
</XStack>
</YStack>
</YStack>
<LinkWithArrow
text="Skip to Dashboard"
to="/"
arrowLeft={true}
style={{ marginTop: '44px', marginBottom: '88px' }}
/>
</YStack>
</Stack>
)
}
export default ActivationValidatorSetup

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import ConsensusClientCard from './ConsensusClientCard'
import { withRouter } from 'storybook-addon-react-router-v6'
const meta = {
title: 'ValidatorOnboarding/ConsensusClientCard',
component: ConsensusClientCard,
tags: ['autodocs'],
decorators: [withRouter()],
} satisfies Meta<typeof ConsensusClientCard>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: { name: 'Erigon', icon: '/icons/erigon-circle.png' },
}

View File

@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react'
import ConsensusGaugeCard from './ConsensusGaugeCard'
import { withRouter } from 'storybook-addon-react-router-v6'
const meta = {
title: 'ValidatorOnboarding/ConsensusGaugeCard',
component: ConsensusGaugeCard,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [withRouter()],
} satisfies Meta<typeof ConsensusGaugeCard>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
color:'orange', synced:140000, total:200000, title: 'Synced Files'
},
}

View File

@ -10,7 +10,7 @@ const meta = {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [withRouter()],
decorators: [withRouter],
}
export default meta
type Story = StoryObj<typeof meta>

View File

@ -6,9 +6,8 @@ import { withRouter } from 'storybook-addon-react-router-v6'
const meta = {
title: 'ValidatorOnboarding/ExecClientCard',
component: ExecClientCard,
tags: ['autodocs'],
decorators: [withRouter()],
decorators: [withRouter],
} satisfies Meta<typeof ExecClientCard>
export default meta

View File

@ -10,7 +10,7 @@ const meta = {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [withRouter()],
decorators: [withRouter],
} satisfies Meta<typeof PairedDeviceCard>
export default meta

View File

@ -0,0 +1,21 @@
import type { Meta, StoryObj } from '@storybook/react'
import SyntaxHighlighter from './SyntaxHighlighter'
import { withRouter } from 'storybook-addon-react-router-v6'
const meta = {
title: 'ValidatorOnboarding/SyntaxHighlighter',
component: SyntaxHighlighter,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [withRouter()],
} satisfies Meta<typeof SyntaxHighlighter>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: { rows: ['yarn', 'yarn build', 'yarn dev', 'house'] },
}

View File

@ -3,6 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
type KeyGenerationState = {
words: string[]
isCopyPastedPhrase: boolean
isRightPhrase: boolean
}
type wordProps = {
@ -13,6 +14,7 @@ type wordProps = {
const initialState: KeyGenerationState = {
words: Array(24).fill(''),
isCopyPastedPhrase: false,
isRightPhrase: false,
}
const keyGenerationSlice = createSlice({
@ -30,13 +32,13 @@ const keyGenerationSlice = createSlice({
setIsCopyPastedPhrase: (state, action: PayloadAction<boolean>) => {
state.isCopyPastedPhrase = action.payload
},
setIsRightPhrase: (state, action: PayloadAction<boolean>) => {
state.isRightPhrase = action.payload
},
},
})
export const {
setWord,
setMnemonic,
setIsCopyPastedPhrase,
} = keyGenerationSlice.actions
export const { setWord, setMnemonic, setIsCopyPastedPhrase, setIsRightPhrase } =
keyGenerationSlice.actions
export default keyGenerationSlice.reducer