-
Notifications
You must be signed in to change notification settings - Fork 411
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Seedless Onboarding]: Add password recovery modal design (#2653)
* feat: Add password recovery modal design * fix: Close modal on login * fix: Extend disabled state, add progress bar * fix: Close connection popover when password recovery opens * fix: Move logic from useEffect into login handler * refactor: Reuse PasswordInput
- Loading branch information
1 parent
0140ec0
commit 8500cdf
Showing
8 changed files
with
136 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 86 additions & 50 deletions
136
src/components/common/ConnectWallet/PasswordRecovery.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,106 @@ | ||
import { MPC_WALLET_EVENTS } from '@/services/analytics/events/mpcWallet' | ||
import { VisibilityOff, Visibility } from '@mui/icons-material' | ||
import { | ||
DialogContent, | ||
Typography, | ||
TextField, | ||
IconButton, | ||
FormControlLabel, | ||
Checkbox, | ||
Button, | ||
Box, | ||
Divider, | ||
Grid, | ||
LinearProgress, | ||
FormControl, | ||
} from '@mui/material' | ||
import { useState } from 'react' | ||
import ModalDialog from '../ModalDialog' | ||
import Track from '../Track' | ||
import { FormProvider, useForm } from 'react-hook-form' | ||
import PasswordInput from '@/components/settings/SignerAccountMFA/PasswordInput' | ||
|
||
type PasswordFormData = { | ||
password: string | ||
} | ||
|
||
export const PasswordRecovery = ({ | ||
recoverFactorWithPassword, | ||
onSuccess, | ||
}: { | ||
recoverFactorWithPassword: (password: string, storeDeviceFactor: boolean) => Promise<void> | ||
onSuccess: (() => void) | undefined | ||
}) => { | ||
const [showPassword, setShowPassword] = useState(false) | ||
const [recoveryPassword, setRecoveryPassword] = useState<string>('') | ||
const [storeDeviceFactor, setStoreDeviceFactor] = useState(false) | ||
|
||
const formMethods = useForm<PasswordFormData>({ | ||
mode: 'all', | ||
defaultValues: { | ||
password: '', | ||
}, | ||
}) | ||
|
||
const { handleSubmit, formState, setError } = formMethods | ||
|
||
const onSubmit = async (data: PasswordFormData) => { | ||
try { | ||
await recoverFactorWithPassword(data.password, storeDeviceFactor) | ||
onSuccess?.() | ||
} catch (e) { | ||
setError('password', { type: 'custom', message: 'Incorrect password' }) | ||
} | ||
} | ||
|
||
const isDisabled = formState.isSubmitting | ||
|
||
return ( | ||
<ModalDialog open dialogTitle="Enter your recovery password" hideChainIndicator> | ||
<DialogContent> | ||
<Box> | ||
<Typography> | ||
This browser is not registered with your Account yet. Please enter your recovery password to restore access | ||
to this Account. | ||
</Typography> | ||
<Box mt={2} display="flex" flexDirection="column" alignItems="baseline" gap={2}> | ||
<TextField | ||
label="Recovery password" | ||
type={showPassword ? 'text' : 'password'} | ||
value={recoveryPassword} | ||
onChange={(event) => { | ||
setRecoveryPassword(event.target.value) | ||
}} | ||
InputProps={{ | ||
endAdornment: ( | ||
<IconButton | ||
aria-label="toggle password visibility" | ||
onClick={() => setShowPassword((prev) => !prev)} | ||
edge="end" | ||
> | ||
{showPassword ? <VisibilityOff /> : <Visibility />} | ||
</IconButton> | ||
), | ||
}} | ||
/> | ||
<FormControlLabel | ||
control={<Checkbox checked={storeDeviceFactor} onClick={() => setStoreDeviceFactor((prev) => !prev)} />} | ||
label="Do not ask again on this device" | ||
/> | ||
<Track {...MPC_WALLET_EVENTS.RECOVER_PASSWORD}> | ||
<Button | ||
variant="contained" | ||
onClick={() => recoverFactorWithPassword(recoveryPassword, storeDeviceFactor)} | ||
> | ||
Submit | ||
</Button> | ||
</Track> | ||
</Box> | ||
</Box> | ||
</DialogContent> | ||
</ModalDialog> | ||
<FormProvider {...formMethods}> | ||
<form onSubmit={handleSubmit(onSubmit)}> | ||
<Grid container justifyContent="center" alignItems="center"> | ||
<Grid item xs={12} md={5} p={2}> | ||
<Typography variant="h2" fontWeight="bold" mb={3}> | ||
Verify your account | ||
</Typography> | ||
<Box bgcolor="background.paper" borderRadius={1}> | ||
<LinearProgress | ||
color="secondary" | ||
sx={{ borderTopLeftRadius: '6px', borderTopRightRadius: '6px', opacity: isDisabled ? 1 : 0 }} | ||
/> | ||
<Box p={4}> | ||
<Typography variant="h6" fontWeight="bold" mb={0.5}> | ||
Enter security password | ||
</Typography> | ||
<Typography> | ||
This browser is not registered with your Account yet. Please enter your recovery password to restore | ||
access to this Account. | ||
</Typography> | ||
</Box> | ||
<Divider /> | ||
<Box p={4} display="flex" flexDirection="column" alignItems="baseline" gap={1}> | ||
<FormControl fullWidth> | ||
<PasswordInput | ||
name="password" | ||
label="Recovery password" | ||
helperText={formState.errors['password']?.message} | ||
disabled={isDisabled} | ||
required | ||
/> | ||
</FormControl> | ||
<FormControlLabel | ||
disabled={isDisabled} | ||
control={ | ||
<Checkbox checked={storeDeviceFactor} onClick={() => setStoreDeviceFactor((prev) => !prev)} /> | ||
} | ||
label="Do not ask again on this device" | ||
/> | ||
</Box> | ||
<Divider /> | ||
<Box p={4} display="flex" justifyContent="flex-end"> | ||
<Track {...MPC_WALLET_EVENTS.RECOVER_PASSWORD}> | ||
<Button variant="contained" type="submit" disabled={isDisabled}> | ||
Submit | ||
</Button> | ||
</Track> | ||
</Box> | ||
</Box> | ||
</Grid> | ||
</Grid> | ||
</form> | ||
</FormProvider> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters