update pages

This commit is contained in:
fmtabbara
2022-03-21 10:57:48 +00:00
parent 155f8401f1
commit a562984bc5
5 changed files with 196 additions and 46 deletions
@@ -0,0 +1,129 @@
import React, { useContext, useEffect, useState } from 'react';
import { Alert, Button, CircularProgress, Grid, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
import { CopyToClipboard } from '@nymproject/react';
import { useSnackbar } from 'notistack';
import { WordTiles } from '../components';
import { TPages } from '../types';
import { MnemonicInput } from '../components/textfields';
import { SignInContext } from '../context';
import { createPassword } from '../../../requests';
export const CreateMnemonic = ({
page,
onNext,
onPrev,
onComplete,
}: {
page: TPages;
onNext: () => void;
onPrev: () => void;
onComplete: () => void;
}) => {
const [toggle, setToggle] = useState('new');
const [isLoading, setIsLoading] = useState(false);
const { password, mnemonic, mnemonicWords, error, generateMnemonic, validateMnemonic, setMnemonic, setError } =
useContext(SignInContext);
const { enqueueSnackbar } = useSnackbar();
const handleUseExisting = async () => {
setIsLoading(true);
setError(undefined);
try {
await validateMnemonic();
await createPassword({ password, mnemonic });
enqueueSnackbar('Password successfully created', { variant: 'success' });
onComplete();
} catch (e) {
setError(e as string);
setIsLoading(false);
}
};
useEffect(() => {
setError(undefined);
if (toggle === 'new') {
generateMnemonic();
} else {
setMnemonic('');
}
}, [toggle]);
return (
<Grid container spacing={4} justifyContent="center" id={page}>
<Grid item xs={12}>
<Typography sx={{ color: 'common.white', fontWeight: 600 }} textAlign="center">
Write down your mnemonic
</Typography>
</Grid>
{toggle === 'new' && (
<Grid item xs={7}>
<Alert
icon={false}
sx={{ bgcolor: '#18263B', color: '#50ABFF' }}
action={mnemonic && <CopyToClipboard value={mnemonic} tooltip="Copy your mnemonic phrase" />}
>
<Typography>Please store your mnemonic in a safe place</Typography>
<Typography fontWeight={600} textTransform="uppercase">
This is the only way to access your wallet!
</Typography>
</Alert>
</Grid>
)}
<Grid item xs={7}>
<ToggleButtonGroup
fullWidth
value={toggle}
exclusive
onChange={(_: React.MouseEvent<HTMLElement>, value: string) => {
setToggle(value);
}}
>
<ToggleButton value="new">Create new mnemonic</ToggleButton>
<ToggleButton value="existing">Use existing mnemonic</ToggleButton>
</ToggleButtonGroup>
</Grid>
<Grid item xs={toggle === 'new' ? 12 : 7}>
{toggle === 'new' && <WordTiles mnemonicWords={mnemonicWords} showIndex />}
{toggle === 'existing' && (
<MnemonicInput mnemonic={mnemonic} onUpdateMnemonic={(mnc) => setMnemonic(mnc)} error={error} />
)}
</Grid>
<Grid container item spacing={2} justifyContent="center">
<Grid item>
<Button
variant="outlined"
disableElevation
size="large"
onClick={() => {
setError(undefined);
onPrev();
}}
sx={{
color: 'common.white',
border: '1px solid white',
'&:hover': { border: '1px solid white' },
width: 250,
}}
>
Back
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
color="primary"
disableElevation
size="large"
onClick={toggle === 'new' ? onNext : handleUseExisting}
sx={{ width: 250 }}
>
{isLoading ? <CircularProgress size={20} color="inherit" /> : 'Verify mnemonic'}
</Button>
</Grid>
</Grid>
</Grid>
);
};
@@ -1,14 +1,19 @@
import React, { useState } from 'react';
import { Button, FormControl, Grid, IconButton, Stack, TextField } from '@mui/material';
import { VisibilityOff, Visibility } from '@mui/icons-material';
import React, { useContext, useState } from 'react';
import { Button, FormControl, Grid, Stack } from '@mui/material';
import { TPages } from '../types';
import { Subtitle, Title, PasswordStrength } from '../components';
import { PasswordInput } from '../components/textfields';
import { SignInContext } from '../context';
export const CreatePassword = ({ page, onPrev, onNext }: { page: TPages; onNext: () => void; onPrev: () => void }) => {
const [password, setPassword] = useState<string>('');
const [confirmedPassword, setConfirmedPassword] = useState<string>();
const [showConfirmedPassword, setShowConfirmedPassword] = useState(false);
const { password, setPassword } = useContext(SignInContext);
const [confirmedPassword, setConfirmedPassword] = useState<string>('');
const [isStrongPassword, setIsStrongPassword] = useState(false);
const handleOnPrev = () => {
setPassword('');
onPrev();
};
return (
<>
@@ -20,33 +25,25 @@ export const CreatePassword = ({ page, onPrev, onNext }: { page: TPages; onNext:
<FormControl fullWidth>
<Stack spacing={2}>
<>
<PasswordInput password={password} onUpdatePassword={(pswd) => setPassword(pswd)} />
<PasswordStrength password={password} />
<PasswordInput password={password} onUpdatePassword={(pswd) => setPassword(pswd)} label="Password" />
<PasswordStrength password={password} onChange={(isStrong) => setIsStrongPassword(isStrong)} />
</>
<TextField
<PasswordInput
password={confirmedPassword}
onUpdatePassword={(pswd) => setConfirmedPassword(pswd)}
label="Confirm password"
value={confirmedPassword}
onChange={(e) => setConfirmedPassword(e.target.value)}
type={showConfirmedPassword ? 'input' : 'password'}
InputProps={{
endAdornment: (
<IconButton onClick={() => setShowConfirmedPassword((show) => !show)}>
{showConfirmedPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
),
}}
/>
<Button
size="large"
variant="contained"
disabled={password !== confirmedPassword || password.length === 0}
disabled={password !== confirmedPassword || password.length === 0 || !isStrongPassword}
onClick={onNext}
>
Next
</Button>
<Button
size="large"
onClick={onPrev}
onClick={handleOnPrev}
sx={{
color: 'common.white',
border: '1px solid white',
@@ -2,18 +2,19 @@
import React, { useContext, useState } from 'react';
import { Alert, Button, FormControl, Grid, Stack, ToggleButton, ToggleButtonGroup } from '@mui/material';
import { ClientContext } from 'src/context/main';
import { Subtitle } from '../components';
import { Subtitle, MnemonicInput, PasswordInput } from '../components';
import { TPages } from '../types';
import { MnemonicInput, PasswordInput } from '../components/textfields';
type TToggle = 'mnemonic' | 'password';
export const ExistingAccount: React.FC<{ page: TPages; onPrev: () => void; onCreatePassword: () => void }> = ({
onPrev,
onCreatePassword,
}) => {
const [toggle, setToggle] = useState('mnemonic');
const [toggle, setToggle] = useState<TToggle>('mnemonic');
const [password, setPassword] = useState('');
const [mnemonic, setMnemonic] = useState('');
const { setError, logIn } = useContext(ClientContext);
const { setError, logIn, error } = useContext(ClientContext);
return (
<>
@@ -38,7 +39,7 @@ export const ExistingAccount: React.FC<{ page: TPages; onPrev: () => void; onCre
fullWidth
value={toggle}
exclusive
onChange={(e: React.MouseEvent<HTMLElement>, value: string) => {
onChange={(_: React.MouseEvent<HTMLElement>, value: TToggle) => {
setError(undefined);
setToggle(value);
}}
@@ -49,13 +50,23 @@ export const ExistingAccount: React.FC<{ page: TPages; onPrev: () => void; onCre
<FormControl fullWidth>
<Stack spacing={2}>
{toggle === 'mnemonic' && (
<MnemonicInput mnemonic={mnemonic} onUpdateMnemonic={(mnc) => setMnemonic(mnc)} />
<MnemonicInput mnemonic={mnemonic} onUpdateMnemonic={(mnc) => setMnemonic(mnc)} error={error} />
)}
{toggle === 'password' && (
<PasswordInput password={password} onUpdatePassword={(pswd) => setPassword(pswd)} />
<PasswordInput
password={password}
onUpdatePassword={(pswd) => setPassword(pswd)}
label="Password"
error={error}
/>
)}
<Button variant="contained" size="large" fullWidth onClick={() => logIn(mnemonic)}>
<Button
variant="contained"
size="large"
fullWidth
onClick={() => logIn({ type: toggle, value: toggle === 'mnemonic' ? mnemonic : password })}
>
{`Sign in with ${toggle}`}
</Button>
<Button
+1 -1
View File
@@ -1,5 +1,5 @@
export * from './welcome-content';
export * from './create-account';
export * from './create-mnemonic';
export * from './verify-mnemonic';
export * from './create-password';
export * from './existing-account';
@@ -1,25 +1,34 @@
import React, { useEffect, useState } from 'react';
import { Button, Stack } from '@mui/material';
import React, { useContext, useEffect, useState } from 'react';
import { Button, CircularProgress, Stack } from '@mui/material';
import { useSnackbar } from 'notistack';
import { HiddenWords, Subtitle, Title, WordTiles } from '../components';
import { THiddenMnemonicWord, THiddenMnemonicWords, TMnemonicWord, TMnemonicWords, TPages } from '../types';
import { randomNumberBetween } from '../../../utils';
import { SignInContext } from '../context';
import { createPassword } from '../../../requests';
const numberOfRandomWords = 4;
const numberOfRandomWords = 6;
export const VerifyMnemonic = ({
mnemonicWords,
page,
onNext,
onPrev,
}: {
mnemonicWords?: TMnemonicWords;
page: TPages;
onNext: () => void;
onPrev: () => void;
}) => {
export const VerifyMnemonic = ({ page, onNext, onPrev }: { page: TPages; onNext: () => void; onPrev: () => void }) => {
const [randomWords, setRandomWords] = useState<TMnemonicWords>();
const [hiddenRandomWords, setHiddenRandomWords] = useState<THiddenMnemonicWords>();
const [currentSelection, setCurrentSelection] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const { mnemonicWords, mnemonic, password } = useContext(SignInContext);
const { enqueueSnackbar } = useSnackbar();
const storePassword = async () => {
try {
setIsLoading(true);
await createPassword({ mnemonic, password });
enqueueSnackbar('Password successfully created', { variant: 'success' });
} catch (e) {
enqueueSnackbar(e as string, { variant: 'error' });
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (mnemonicWords) {
@@ -59,8 +68,12 @@ export const VerifyMnemonic = ({
variant="contained"
fullWidth
size="large"
disabled={currentSelection !== numberOfRandomWords}
onClick={onNext}
disabled={currentSelection !== numberOfRandomWords || isLoading}
onClick={async () => {
await storePassword();
onNext();
}}
endIcon={isLoading && <CircularProgress />}
>
Next
</Button>