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

This commit is contained in:
Ivana Andersson 2023-09-11 11:07:20 +03:00
commit f3e852a204
31 changed files with 370 additions and 164 deletions

View File

@ -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",
},
}

View File

@ -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,
},
}

View File

@ -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,
},
}

View File

@ -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()}>

View File

@ -19,3 +19,9 @@ export const Default: Story = {
index: 0,
},
}
export const OtherWord: Story = {
args: {
index: 2,
},
}

View File

@ -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 {

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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'
},
}

View File

@ -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

View File

@ -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',

View File

@ -15,5 +15,5 @@ export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {},
args: { },
}

View File

@ -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,
},
}

View File

@ -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,
},
}

View File

@ -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

View File

@ -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')

View File

@ -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%',

View File

@ -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 (

View File

@ -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

5
vercel.json Normal file
View File

@ -0,0 +1,5 @@
{
"rewrites": [
{ "source": "/(.*)", "destination": "/" }
]
}