Merge branch 'main' of github.com:nimbus-gui/nimbus-gui into ia.responsive-css
This commit is contained in:
commit
f3e852a204
|
@ -17,5 +17,25 @@ export default meta
|
|||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
args: {
|
||||
validatorsValue: '4',
|
||||
executionSyncStatus1: {
|
||||
text: "Execution Sync Status",
|
||||
isGaugeIncluded: true,
|
||||
gaugeColor: "$blue",
|
||||
gaugeSynced: 123.524,
|
||||
gaugeTotal: 172.503,
|
||||
|
||||
},
|
||||
executionSyncStatus2: {
|
||||
text: "Execution Sync Status",
|
||||
isGaugeIncluded: true,
|
||||
gaugeColor: "$red",
|
||||
gaugeSynced: 123.524,
|
||||
gaugeTotal: 172.503,
|
||||
},
|
||||
currentAPRValue: "4.40%",
|
||||
estimatedActivationTimeValue: "32 Days",
|
||||
validatorQueueValue: "92603",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,26 +2,39 @@ import { useState, useEffect } from 'react'
|
|||
import { XStack, Stack, YStack } from 'tamagui'
|
||||
import { Text } from '@status-im/components'
|
||||
import Confetti from 'react-confetti'
|
||||
|
||||
import ActivationCard from './ActivationCard'
|
||||
import LinkWithArrow from '../../../components/General/LinkWithArrow'
|
||||
|
||||
const styles = {
|
||||
confettiContainer: {
|
||||
position: 'relative' as const,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
confettiCanvas: {
|
||||
position: 'absolute' as const,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: 0,
|
||||
},
|
||||
type ActivationProps = {
|
||||
validatorsValue: string
|
||||
executionSyncStatus1: {
|
||||
text: string
|
||||
isGaugeIncluded: boolean
|
||||
gaugeColor: string
|
||||
gaugeSynced: number
|
||||
gaugeTotal: number
|
||||
}
|
||||
executionSyncStatus2: {
|
||||
text: string
|
||||
isGaugeIncluded: boolean
|
||||
gaugeColor: string
|
||||
gaugeSynced: number
|
||||
gaugeTotal: number
|
||||
}
|
||||
currentAPRValue: string
|
||||
estimatedActivationTimeValue: string
|
||||
validatorQueueValue: string
|
||||
}
|
||||
|
||||
const Activation = () => {
|
||||
const Activation = ({
|
||||
validatorsValue,
|
||||
executionSyncStatus1,
|
||||
executionSyncStatus2,
|
||||
currentAPRValue,
|
||||
estimatedActivationTimeValue,
|
||||
validatorQueueValue,
|
||||
}: ActivationProps) => {
|
||||
const [showConfetti, setShowConfetti] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -50,26 +63,17 @@ const Activation = () => {
|
|||
</Stack>
|
||||
<YStack space={'$3'} marginTop={'25px'} width={'33%'}>
|
||||
<XStack space={'$3'} justifyContent={'space-between'}>
|
||||
<ActivationCard text="Validators" value="4" />
|
||||
<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}
|
||||
/>
|
||||
<ActivationCard text="Validators" value={validatorsValue} />
|
||||
<ActivationCard {...executionSyncStatus1} />
|
||||
<ActivationCard {...executionSyncStatus2} />
|
||||
</XStack>
|
||||
<XStack space={'$3'}>
|
||||
<ActivationCard text="Current APR" value="4.40%" />
|
||||
<ActivationCard text="Estimated Activation Time" value="32 Days" />
|
||||
<ActivationCard text="Validator Queue" value="92603" />
|
||||
<ActivationCard text="Current APR" value={currentAPRValue} />
|
||||
<ActivationCard
|
||||
text="Estimated Activation Time"
|
||||
value={estimatedActivationTimeValue}
|
||||
/>
|
||||
<ActivationCard text="Validator Queue" value={validatorQueueValue} />
|
||||
</XStack>
|
||||
</YStack>
|
||||
</YStack>
|
||||
|
@ -85,3 +89,19 @@ const Activation = () => {
|
|||
}
|
||||
|
||||
export default Activation
|
||||
|
||||
const styles = {
|
||||
confettiContainer: {
|
||||
position: 'relative' as const,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
confettiCanvas: {
|
||||
position: 'absolute' as const,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: 0,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import { withRouter } from 'storybook-addon-react-router-v6'
|
||||
|
||||
import ContinueButton from './ContinueButton'
|
||||
|
||||
const meta = {
|
||||
title: 'ValidatorOnboarding/ContinueButton',
|
||||
component: ContinueButton,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
decorators: [withRouter],
|
||||
} satisfies Meta<typeof ContinueButton>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
continueHandler: () => {},
|
||||
activeStep: 0,
|
||||
isConfirmPhraseStage: false,
|
||||
subStepValidatorSetup: 0,
|
||||
},
|
||||
}
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
continueHandler: () => {},
|
||||
activeStep: 0,
|
||||
isConfirmPhraseStage: true,
|
||||
subStepValidatorSetup: 0,
|
||||
},
|
||||
}
|
|
@ -1,30 +1,49 @@
|
|||
import { Stack, XStack } from 'tamagui'
|
||||
import { Button, InformationBox } from '@status-im/components'
|
||||
import { CloseCircleIcon } from '@status-im/icons'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { RootState } from '../../redux/store'
|
||||
import { setIsRightPhrase } from '../../redux/ValidatorOnboarding/KeyGeneration/slice'
|
||||
import LinkWithArrow from '../../components/General/LinkWithArrow'
|
||||
|
||||
type ContinueButton = {
|
||||
continueHandler: () => void
|
||||
activeStep: number
|
||||
isConfirmPhraseStage: boolean
|
||||
subStepValidatorSetup: number
|
||||
}
|
||||
|
||||
const ContinueButton = ({ continueHandler, activeStep, isConfirmPhraseStage }: ContinueButton) => {
|
||||
const { isCopyPastedPhrase, isRightPhrase } = useSelector(
|
||||
const ContinueButton = ({
|
||||
continueHandler,
|
||||
activeStep,
|
||||
isConfirmPhraseStage,
|
||||
subStepValidatorSetup,
|
||||
}: ContinueButton) => {
|
||||
const { isCopyPastedPhrase, isRightPhrase, words, validWords } = useSelector(
|
||||
(state: RootState) => state.keyGeneration,
|
||||
)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setIsRightPhrase(words.every(word => word !== '')))
|
||||
}, [words])
|
||||
|
||||
const isDisabled = () => {
|
||||
if (isConfirmPhraseStage && !isRightPhrase) {
|
||||
if (
|
||||
(isConfirmPhraseStage && !isRightPhrase) ||
|
||||
(isConfirmPhraseStage && validWords.some(w => w === false))
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const isActivationValScreen = activeStep === 3 && subStepValidatorSetup === 3
|
||||
|
||||
return (
|
||||
<XStack style={{ width: '100%', marginTop: '16px', zIndex: 999, alignItems: 'center' }}>
|
||||
<XStack style={{ width: '100%', alignItems: 'center', zIndex: 999, marginTop: '40px' }}>
|
||||
<Stack style={{ width: '100%' }}>
|
||||
{isCopyPastedPhrase && (
|
||||
<InformationBox
|
||||
|
@ -33,14 +52,21 @@ const ContinueButton = ({ continueHandler, activeStep, isConfirmPhraseStage }: C
|
|||
icon={<CloseCircleIcon size={20} />}
|
||||
/>
|
||||
)}
|
||||
{isActivationValScreen && (
|
||||
<LinkWithArrow
|
||||
text="Skip to Dashboard"
|
||||
to="/"
|
||||
arrowRight={true}
|
||||
style={{ fontWeight: 'bold', zIndex: 1000 }}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
<Stack
|
||||
style={{
|
||||
width: '100%',
|
||||
alignItems: 'end',
|
||||
zIndex: 999,
|
||||
alignItems: 'end',
|
||||
position: 'absolute',
|
||||
marginTop: isCopyPastedPhrase ? '0px' : '40px',
|
||||
}}
|
||||
>
|
||||
<Button onPress={continueHandler} size={40} disabled={isDisabled()}>
|
||||
|
|
|
@ -19,3 +19,9 @@ export const Default: Story = {
|
|||
index: 0,
|
||||
},
|
||||
}
|
||||
|
||||
export const OtherWord: Story = {
|
||||
args: {
|
||||
index: 2,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { RootState } from '../../../../redux/store'
|
|||
import {
|
||||
setIsCopyPastedPhrase,
|
||||
setMnemonic,
|
||||
setValidWords,
|
||||
setWord,
|
||||
} from '../../../../redux/ValidatorOnboarding/KeyGeneration/slice'
|
||||
import styles from './AutocompleteInput.module.css'
|
||||
|
@ -18,32 +19,50 @@ const AutocompleteInput = ({ index }: AutocompleteInputProps) => {
|
|||
const [suggestions, setSuggestions] = useState<string[]>([])
|
||||
const [isFocused, setIsFocused] = useState(false)
|
||||
const word = useSelector((state: RootState) => state.keyGeneration.words[index])
|
||||
const isValidWord = useSelector((state: RootState) => state.keyGeneration.validWords[index])
|
||||
const validWords = useSelector((state: RootState) => state.keyGeneration.validWords)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
useEffect(() => {
|
||||
setSuggestions(wordlist.filter(w => w.startsWith(word.toLowerCase())))
|
||||
setSuggestions(getNewSuggestions(word))
|
||||
}, [word])
|
||||
|
||||
const getNewSuggestions = (word: string) => {
|
||||
return wordlist.filter(w => w.startsWith(word.toLowerCase()))
|
||||
}
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (!isFocused) {
|
||||
handleInputFocus()
|
||||
}
|
||||
|
||||
const value = e.target.value
|
||||
const mnemonic = value.trim().split(' ')
|
||||
const mnemonic = value.trim().split(' ').slice(0, 24)
|
||||
const mnemonicLength = mnemonic.length
|
||||
let newValidWords = [...validWords]
|
||||
|
||||
if (mnemonicLength === 1) {
|
||||
dispatch(setWord({ index, word: value }))
|
||||
|
||||
newValidWords[index] = wordlist.includes(value) || getNewSuggestions(value).length > 0
|
||||
} else if (mnemonicLength === 24) {
|
||||
dispatch(setMnemonic(mnemonic))
|
||||
dispatch(setIsCopyPastedPhrase(true))
|
||||
|
||||
mnemonic.forEach((m, i) => {
|
||||
newValidWords[i] = wordlist.includes(m)
|
||||
})
|
||||
} else {
|
||||
for (let i = index; i < mnemonicLength + index; i++) {
|
||||
dispatch(setWord({ index: i, word: mnemonic.shift() || '' }))
|
||||
const mnemonicWord = mnemonic.shift() || ''
|
||||
dispatch(setWord({ index: i, word: mnemonicWord }))
|
||||
newValidWords[i] = wordlist.includes(mnemonicWord)
|
||||
}
|
||||
|
||||
dispatch(setIsCopyPastedPhrase(true))
|
||||
}
|
||||
|
||||
dispatch(setValidWords(newValidWords))
|
||||
}
|
||||
|
||||
const handleSuggestionClick = (e: React.MouseEvent, suggestion: string) => {
|
||||
|
@ -51,6 +70,10 @@ const AutocompleteInput = ({ index }: AutocompleteInputProps) => {
|
|||
|
||||
setIsFocused(false)
|
||||
dispatch(setWord({ index, word: suggestion }))
|
||||
|
||||
let newValidWords = [...validWords]
|
||||
newValidWords[index] = wordlist.includes(suggestion)
|
||||
dispatch(setValidWords(newValidWords))
|
||||
}
|
||||
|
||||
const handleInputFocus = () => {
|
||||
|
@ -59,6 +82,10 @@ const AutocompleteInput = ({ index }: AutocompleteInputProps) => {
|
|||
|
||||
const handleInputBlur = () => {
|
||||
setIsFocused(false)
|
||||
|
||||
let newValidWords = [...validWords]
|
||||
newValidWords[index] = wordlist.includes(word)
|
||||
dispatch(setValidWords(newValidWords))
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -71,7 +98,7 @@ const AutocompleteInput = ({ index }: AutocompleteInputProps) => {
|
|||
onChange={handleInputChange}
|
||||
onFocus={handleInputFocus}
|
||||
onBlur={handleInputBlur}
|
||||
style={inputStyle(index, isFocused)}
|
||||
style={inputStyle(index, isFocused, isValidWord)}
|
||||
/>
|
||||
</div>
|
||||
<div className={isFocused ? styles['suggestion-list'] : ''}>
|
||||
|
@ -92,16 +119,17 @@ const AutocompleteInput = ({ index }: AutocompleteInputProps) => {
|
|||
|
||||
export default AutocompleteInput
|
||||
|
||||
const inputStyle = (index: number, isFocused: boolean) => {
|
||||
const inputStyle = (index: number, isFocused: boolean, isValidWord: boolean) => {
|
||||
const style = {
|
||||
outline: 'none',
|
||||
padding: `12px 16px 12px ${index + 1 < 10 ? '35px' : '45px'}`,
|
||||
border: isValidWord ? '2px solid #f7f8f9' : '2px solid #E53E3E',
|
||||
}
|
||||
|
||||
if (isFocused) {
|
||||
return {
|
||||
...style,
|
||||
border: '2px solid #4360DF',
|
||||
border: isValidWord ? '2px solid #4360DF' : '2px solid #E53E3E',
|
||||
backgroundColor: '#f1f2f4',
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -3,10 +3,14 @@ import { Text } from '@status-im/components'
|
|||
|
||||
import AutocompleteInput from './AutocompleteInput'
|
||||
import KeyGenerationTitle from '../KeyGenerationTitle'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from '../../../../redux/store'
|
||||
|
||||
const ConfirmRecoveryPhrase = () => {
|
||||
const { validWords } = useSelector((state: RootState) => state.keyGeneration)
|
||||
|
||||
return (
|
||||
<YStack space={'$4'} style={{ width: '100%', marginTop: '20px' }}>
|
||||
<YStack space={'$3'} style={{ width: '100%', marginTop: '20px' }}>
|
||||
<KeyGenerationTitle />
|
||||
<Text size={19}>Confirm Recovery Phrase</Text>
|
||||
<Stack
|
||||
|
@ -18,7 +22,7 @@ const ConfirmRecoveryPhrase = () => {
|
|||
marginBottom: '10px',
|
||||
}}
|
||||
>
|
||||
{Array.from({ length: 24 }).map((_, index) => (
|
||||
{validWords.map((_, index) => (
|
||||
<AutocompleteInput key={index} index={index} />
|
||||
))}
|
||||
</Stack>
|
||||
|
|
|
@ -10,34 +10,46 @@ import KeyGeneration from './KeyGeneration/KeyGeneration'
|
|||
import Activation from './Activation/Activation'
|
||||
import ValidatorBoxWrapper from './ValidatorBoxWrapper/ValidatorBoxWrapper'
|
||||
import ClientSetup from './ClientSetup/ClientSetup'
|
||||
import ConsensusSelection from './ValidatorSetup/ConsensusSelection'
|
||||
import ConsensusSelection from './ValidatorSetup/ConsensusClient/ConsensusSelection'
|
||||
import Advisories from './Advisories/Advisories'
|
||||
import ValidatorSetup from './ValidatorSetup/ValidatorSetup'
|
||||
import ValidatorSetupInstall from './ValidatorSetup/ValidatorInstall'
|
||||
import ValidatorSetup from './ValidatorSetup/ValidatorSetup/ValidatorSetup'
|
||||
import ValidatorSetupInstall from './ValidatorSetup/ValidatorInstalling/ValidatorInstall'
|
||||
import ContinueButton from './ContinueButton'
|
||||
import { setIsCopyPastedPhrase } from '../../redux/ValidatorOnboarding/KeyGeneration/slice'
|
||||
import {
|
||||
setIsCopyPastedPhrase,
|
||||
setValidWords,
|
||||
} from '../../redux/ValidatorOnboarding/KeyGeneration/slice'
|
||||
import { RootState } from '../../redux/store'
|
||||
import './layoutGradient.css'
|
||||
import ActivationValidatorSetup from './ValidatorSetup/ActivationValidatorSetup'
|
||||
import ActivationValidatorSetup from './ValidatorSetup/ValidatorActivation/ActivationValidatorSetup'
|
||||
import wordlist from 'web-bip39/wordlists/english'
|
||||
|
||||
const ValidatorOnboarding = () => {
|
||||
const [activeStep, setActiveStep] = useState(0)
|
||||
const [isConfirmPhraseStage, setIsConfirmPhraseStage] = useState(false)
|
||||
const [subStepValidatorSetup, setSubStepValidatorSetup] = useState(0)
|
||||
const isCopyPastedPhrase = useSelector(
|
||||
(state: RootState) => state.keyGeneration.isCopyPastedPhrase,
|
||||
)
|
||||
const { isCopyPastedPhrase, words } = useSelector((state: RootState) => state.keyGeneration)
|
||||
const navigate = useNavigate()
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const changeActiveStep = (step: number) => {
|
||||
setActiveStep(step)
|
||||
removeCopyPastePhraseInfoBox()
|
||||
removeConfirmPhraseStage()
|
||||
}
|
||||
|
||||
const continueHandler = () => {
|
||||
if (activeStep === 4 && isConfirmPhraseStage === false) {
|
||||
setIsConfirmPhraseStage(true)
|
||||
return setIsConfirmPhraseStage(true)
|
||||
} else if (activeStep === 4 && isConfirmPhraseStage === true) {
|
||||
const newValidWords = words.map(w => wordlist.includes(w))
|
||||
dispatch(setValidWords(newValidWords))
|
||||
|
||||
if (newValidWords.every(w => w === true)) {
|
||||
setActiveStep(activeStep + 1)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else if (activeStep === 3 && subStepValidatorSetup < 3) {
|
||||
setSubStepValidatorSetup(subStepValidatorSetup + 1)
|
||||
} else if (activeStep < 5) {
|
||||
|
@ -48,7 +60,9 @@ const ValidatorOnboarding = () => {
|
|||
} else {
|
||||
navigate('/')
|
||||
}
|
||||
|
||||
removeCopyPastePhraseInfoBox()
|
||||
removeConfirmPhraseStage()
|
||||
}
|
||||
|
||||
const removeCopyPastePhraseInfoBox = () => {
|
||||
|
@ -57,6 +71,12 @@ const ValidatorOnboarding = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const removeConfirmPhraseStage = () => {
|
||||
if (isConfirmPhraseStage) {
|
||||
setIsConfirmPhraseStage(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="gradient-wrapper">
|
||||
<YStack
|
||||
|
@ -85,12 +105,34 @@ const ValidatorOnboarding = () => {
|
|||
{activeStep === 3 && subStepValidatorSetup === 3 && <ActivationValidatorSetup />}
|
||||
|
||||
{activeStep === 4 && <KeyGeneration isConfirmPhraseStage={isConfirmPhraseStage} />}
|
||||
{activeStep === 5 && <Activation />}
|
||||
{activeStep === 5 && (
|
||||
<Activation
|
||||
validatorsValue="4"
|
||||
executionSyncStatus1={{
|
||||
text: 'Execution Sync Status',
|
||||
isGaugeIncluded: true,
|
||||
gaugeColor: '$blue',
|
||||
gaugeSynced: 123.524,
|
||||
gaugeTotal: 172.503,
|
||||
}}
|
||||
executionSyncStatus2={{
|
||||
text: 'Execution Sync Status',
|
||||
isGaugeIncluded: true,
|
||||
gaugeColor: '$red',
|
||||
gaugeSynced: 123.524,
|
||||
gaugeTotal: 172.503,
|
||||
}}
|
||||
currentAPRValue="4.40%"
|
||||
estimatedActivationTimeValue="32 Days"
|
||||
validatorQueueValue="92603"
|
||||
/>
|
||||
)}
|
||||
</ValidatorBoxWrapper>
|
||||
<ContinueButton
|
||||
activeStep={activeStep}
|
||||
continueHandler={continueHandler}
|
||||
isConfirmPhraseStage={isConfirmPhraseStage}
|
||||
subStepValidatorSetup={subStepValidatorSetup}
|
||||
/>
|
||||
</YStack>
|
||||
</div>
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
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
|
|
@ -1,7 +1,7 @@
|
|||
import { Stack, YStack } from 'tamagui'
|
||||
import { Text } from '@status-im/components'
|
||||
|
||||
import Icon from '../../../components/General/Icon'
|
||||
import Icon from '../../../../components/General/Icon'
|
||||
|
||||
type ConsensusClientCardProps = {
|
||||
name: string
|
|
@ -18,6 +18,6 @@ type Story = StoryObj<typeof meta>
|
|||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
color:'orange', synced:140000, total:200000, title: 'Synced Files'
|
||||
color: 'orange', synced: 140000, total: 200000, title: 'Synced Files'
|
||||
},
|
||||
}
|
|
@ -2,9 +2,9 @@ import { Stack, XStack, YStack } from 'tamagui'
|
|||
import { ClearIcon } from '@status-im/icons'
|
||||
import { Text } from '@status-im/components'
|
||||
|
||||
import StandardGauge from '../../../components/Charts/StandardGauge'
|
||||
import BorderBox from '../../../components/General/BorderBox'
|
||||
import { formatNumberForGauge } from '../../../utilities'
|
||||
import StandardGauge from '../../../../components/Charts/StandardGauge'
|
||||
import BorderBox from '../../../../components/General/BorderBox'
|
||||
import { formatNumberForGauge } from '../../../../utilities'
|
||||
|
||||
type ConsensusGaugeCardProps = {
|
||||
synced: number
|
|
@ -5,8 +5,8 @@ import { useSelector } from 'react-redux'
|
|||
import PairedDeviceCard from './PairedDeviceCard'
|
||||
import ConsensusGaugeCard from './ConsensusGaugeCard'
|
||||
import ConsensusClientCard from './ConsensusClientCard'
|
||||
import LinkWithArrow from '../../../components/General/LinkWithArrow'
|
||||
import { RootState } from '../../../redux/store'
|
||||
import LinkWithArrow from '../../../../components/General/LinkWithArrow'
|
||||
import { RootState } from '../../../../redux/store'
|
||||
|
||||
const clientIcons = {
|
||||
Nethermind: '/icons/nethermind-circle.png',
|
|
@ -15,5 +15,5 @@ export default meta
|
|||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
args: { },
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import { XStack, Stack, YStack } from 'tamagui'
|
||||
import { Text } from '@status-im/components'
|
||||
import Confetti from 'react-confetti'
|
||||
|
||||
import ActivationCard from '../../Activation/ActivationCard'
|
||||
|
||||
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={'$3'}>
|
||||
<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>
|
||||
</YStack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActivationValidatorSetup
|
||||
|
||||
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,
|
||||
},
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import OsCard from './OsCard'
|
||||
|
||||
const meta = {
|
||||
title: 'ValidatorOnboarding/OsCard',
|
||||
component: OsCard,
|
||||
tags: ['autodocs'],
|
||||
} satisfies Meta<typeof OsCard>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
icon: '/icons/MAC.png',
|
||||
name: 'Mac',
|
||||
isSelected: true,
|
||||
},
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { Stack, YStack } from 'tamagui'
|
||||
import { Text } from '@status-im/components'
|
||||
|
||||
import Icon from '../../../components/General/Icon'
|
||||
import Icon from '../../../../components/General/Icon'
|
||||
|
||||
type OsCardProps = {
|
||||
name: string
|
|
@ -6,7 +6,7 @@ import { useSelector } from 'react-redux'
|
|||
|
||||
import OsCard from './OsCard'
|
||||
import SyntaxHighlighterBox from './SyntaxHighlighter'
|
||||
import { RootState } from '../../../redux/store'
|
||||
import { RootState } from '../../../../redux/store'
|
||||
|
||||
const ValidatorSetupInstall = () => {
|
||||
const [selectedOs, setSelectedOs] = useState('Mac')
|
|
@ -2,9 +2,9 @@ import { Stack, XStack, YStack } from 'tamagui'
|
|||
import { Text } from '@status-im/components'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
||||
import Icon from '../../../components/General/Icon'
|
||||
import { selectClient } from '../../../redux/ValidatorOnboarding/ValidatorSetup/slice'
|
||||
import { RootState } from '../../../redux/store'
|
||||
import Icon from '../../../../components/General/Icon'
|
||||
import { selectClient } from '../../../../redux/ValidatorOnboarding/ValidatorSetup/slice'
|
||||
import { RootState } from '../../../../redux/store'
|
||||
|
||||
type ExecClientCardProps = {
|
||||
name: string
|
||||
|
@ -24,8 +24,8 @@ const ExecClientCard = ({ name, icon, isComingSoon }: ExecClientCardProps) => {
|
|||
border: isComingSoon
|
||||
? '1px solid #F5F6F8'
|
||||
: isSelected
|
||||
? '1px solid #2A4AF5'
|
||||
: '1px solid #DCE0E5',
|
||||
? '1px solid #2A4AF5'
|
||||
: '1px solid #DCE0E5',
|
||||
borderRadius: '16px',
|
||||
padding: '12px 16px',
|
||||
width: '19%',
|
|
@ -1,9 +1,9 @@
|
|||
import { XStack, Stack, Text as TextTam, YStack } from 'tamagui'
|
||||
import { Text } from '@status-im/components'
|
||||
|
||||
import PairedDeviceCard from './PairedDeviceCard'
|
||||
import PairedDeviceCard from '../ConsensusClient/PairedDeviceCard'
|
||||
import ExecClientCard from './ExecClientCard'
|
||||
import LinkWithArrow from '../../../components/General/LinkWithArrow'
|
||||
import LinkWithArrow from '../../../../components/General/LinkWithArrow'
|
||||
|
||||
const ValidatorSetup = () => {
|
||||
return (
|
|
@ -4,6 +4,7 @@ type KeyGenerationState = {
|
|||
words: string[]
|
||||
isCopyPastedPhrase: boolean
|
||||
isRightPhrase: boolean
|
||||
validWords: boolean[]
|
||||
}
|
||||
|
||||
type wordProps = {
|
||||
|
@ -15,6 +16,7 @@ const initialState: KeyGenerationState = {
|
|||
words: Array(24).fill(''),
|
||||
isCopyPastedPhrase: false,
|
||||
isRightPhrase: false,
|
||||
validWords: Array(24).fill(true),
|
||||
}
|
||||
|
||||
const keyGenerationSlice = createSlice({
|
||||
|
@ -35,10 +37,13 @@ const keyGenerationSlice = createSlice({
|
|||
setIsRightPhrase: (state, action: PayloadAction<boolean>) => {
|
||||
state.isRightPhrase = action.payload
|
||||
},
|
||||
setValidWords: (state, action: PayloadAction<boolean[]>) => {
|
||||
state.validWords = action.payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { setWord, setMnemonic, setIsCopyPastedPhrase, setIsRightPhrase } =
|
||||
export const { setWord, setMnemonic, setIsCopyPastedPhrase, setIsRightPhrase, setValidWords } =
|
||||
keyGenerationSlice.actions
|
||||
|
||||
export default keyGenerationSlice.reducer
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rewrites": [
|
||||
{ "source": "/(.*)", "destination": "/" }
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue