mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
added request code dialog
This commit is contained in:
parent
c0c832d158
commit
6dcb21e9e4
18 changed files with 292 additions and 88 deletions
|
@ -1,7 +1,8 @@
|
|||
import React, { FC, MouseEventHandler, useEffect, useRef } from 'react';
|
||||
import React, { FC, MouseEventHandler, useEffect, useRef, ReactElement } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { enableBodyScroll, disableBodyScroll } from 'body-scroll-lock';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { LoaderCircle } from '~/components/input/LoaderCircle';
|
||||
|
||||
interface IProps {
|
||||
children: React.ReactChild;
|
||||
|
@ -11,6 +12,8 @@ interface IProps {
|
|||
size?: 'medium' | 'big';
|
||||
width?: number;
|
||||
error?: string;
|
||||
is_loading?: boolean;
|
||||
overlay?: ReactElement;
|
||||
|
||||
onOverlayClick?: MouseEventHandler<HTMLDivElement>;
|
||||
onRefCapture?: (ref: any) => void;
|
||||
|
@ -25,6 +28,8 @@ const BetterScrollDialog: FC<IProps> = ({
|
|||
width = 600,
|
||||
error,
|
||||
onClose,
|
||||
is_loading,
|
||||
overlay = null,
|
||||
}) => {
|
||||
const ref = useRef(null);
|
||||
|
||||
|
@ -51,7 +56,15 @@ const BetterScrollDialog: FC<IProps> = ({
|
|||
{error && <div className={styles.error}>{error}</div>}
|
||||
</div>
|
||||
|
||||
{footer && <div className={styles.header}>{footer}</div>}
|
||||
{!!is_loading && (
|
||||
<div className={styles.shade}>
|
||||
<LoaderCircle size={48} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{overlay}
|
||||
|
||||
{footer && <div className={styles.footer}>{footer}</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -109,3 +109,31 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@keyframes appear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.shade {
|
||||
position: absolute;
|
||||
background: transparentize($content_bg, 0.3);
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: $radius;
|
||||
animation: appear 1s forwards;
|
||||
|
||||
svg {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,12 +67,7 @@ const LoginDialogUnconnected: FC<IProps> = ({
|
|||
const buttons = useMemo(
|
||||
() => (
|
||||
<Group className={styles.footer}>
|
||||
<Button
|
||||
className={styles.secondary_button}
|
||||
iconLeft="vk"
|
||||
type="button"
|
||||
onClick={onSocialLogin}
|
||||
>
|
||||
<Button color="outline" iconLeft="vk" type="button" onClick={onSocialLogin}>
|
||||
<span>Вконтакте</span>
|
||||
</Button>
|
||||
|
||||
|
@ -88,7 +83,7 @@ const LoginDialogUnconnected: FC<IProps> = ({
|
|||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<BetterScrollDialog width={260} error={error} onClose={onRequestClose} footer={buttons}>
|
||||
<BetterScrollDialog width={300} error={error} onClose={onRequestClose} footer={buttons}>
|
||||
<Padder>
|
||||
<div className={styles.wrap}>
|
||||
<Group>
|
||||
|
@ -98,7 +93,12 @@ const LoginDialogUnconnected: FC<IProps> = ({
|
|||
|
||||
<InputText title="Пароль" handler={setPassword} value={password} type="password" />
|
||||
|
||||
<Button className={styles.forgot_button} type="button" onClick={onRestoreRequest}>
|
||||
<Button
|
||||
color="link"
|
||||
type="button"
|
||||
onClick={onRestoreRequest}
|
||||
className={styles.forgot_button}
|
||||
>
|
||||
Вспомнить пароль
|
||||
</Button>
|
||||
</Group>
|
||||
|
|
|
@ -28,9 +28,7 @@ $vk_color: $secondary_color;
|
|||
}
|
||||
|
||||
.forgot_button {
|
||||
background: $content_bg;
|
||||
box-shadow: none;
|
||||
color: $secondary_color;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
|
|
|
@ -1,33 +1,101 @@
|
|||
import React, { FC, useState, useMemo, useCallback } from 'react';
|
||||
import React, { FC, useState, useMemo, useCallback, useEffect } from 'react';
|
||||
import { IDialogProps } from '~/redux/types';
|
||||
import { connect } from 'react-redux';
|
||||
import { BetterScrollDialog } from '../BetterScrollDialog';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { InputText } from '~/components/input/InputText';
|
||||
import { Button } from '~/components/input/Button';
|
||||
import styles from './styles.scss';
|
||||
|
||||
const mapStateToProps = () => ({});
|
||||
const mapDispatchToProps = {};
|
||||
import * as AUTH_ACTIONS from '~/redux/auth/actions';
|
||||
import pick from 'ramda/es/pick';
|
||||
import { selectAuthRestore } from '~/redux/auth/selectors';
|
||||
import { LoaderCircle } from '~/components/input/LoaderCircle';
|
||||
import { ERROR_LITERAL } from '~/constants/errors';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
restore: selectAuthRestore(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = pick(['authRequestRestoreCode', 'authSetRestore'], AUTH_ACTIONS);
|
||||
|
||||
type IProps = IDialogProps & ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||
|
||||
const RestoreRequestDialogUnconnected: FC<IProps> = ({}) => {
|
||||
const RestoreRequestDialogUnconnected: FC<IProps> = ({
|
||||
restore: { error, is_loading, is_succesfull },
|
||||
authSetRestore,
|
||||
onRequestClose,
|
||||
authRequestRestoreCode,
|
||||
}) => {
|
||||
const [field, setField] = useState();
|
||||
|
||||
const onSubmit = useCallback(event => {
|
||||
event.preventDefault();
|
||||
}, []);
|
||||
const onSubmit = useCallback(
|
||||
event => {
|
||||
event.preventDefault();
|
||||
|
||||
const buttons = useMemo(() => <Button>Восстановить</Button>, []);
|
||||
if (!field) return;
|
||||
|
||||
authRequestRestoreCode(field);
|
||||
},
|
||||
[authRequestRestoreCode, field]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (error || is_succesfull) {
|
||||
authSetRestore({ error: null, is_succesfull: false });
|
||||
}
|
||||
}, [field]);
|
||||
|
||||
const buttons = useMemo(
|
||||
() => (
|
||||
<Group className={styles.buttons}>
|
||||
<Button>Восстановить</Button>
|
||||
</Group>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
const header = useMemo(() => <div className={styles.illustration}>ILLUSTRATE ME</div>, []);
|
||||
|
||||
const overlay = useMemo(
|
||||
() =>
|
||||
is_succesfull ? (
|
||||
<Group className={styles.shade}>
|
||||
<Icon icon="check" size={64} />
|
||||
|
||||
<div>Проверьте почту, мы отправили на неё код</div>
|
||||
|
||||
<div />
|
||||
|
||||
<Button color="secondary" onClick={onRequestClose}>
|
||||
Отлично!
|
||||
</Button>
|
||||
</Group>
|
||||
) : null,
|
||||
[is_succesfull]
|
||||
);
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<BetterScrollDialog footer={buttons}>
|
||||
<Group>
|
||||
<InputText title="Имя или email" value={field} handler={setField} />
|
||||
<BetterScrollDialog
|
||||
header={header}
|
||||
footer={buttons}
|
||||
width={300}
|
||||
onClose={onRequestClose}
|
||||
is_loading={is_loading}
|
||||
error={error && ERROR_LITERAL[error]}
|
||||
overlay={overlay}
|
||||
>
|
||||
<div className={styles.wrap}>
|
||||
<Group>
|
||||
<InputText title="Имя или email" value={field} handler={setField} autoFocus />
|
||||
|
||||
<div>Введите имя пользователя или адрес почты. Мы пришлем ссылку для сброса пароля.</div>
|
||||
</Group>
|
||||
<div className={styles.text}>
|
||||
Введите имя пользователя или адрес почты. Мы пришлем ссылку для сброса пароля.
|
||||
</div>
|
||||
</Group>
|
||||
</div>
|
||||
</BetterScrollDialog>
|
||||
</form>
|
||||
);
|
||||
|
|
47
src/containers/dialogs/RestoreRequestDialog/styles.scss
Normal file
47
src/containers/dialogs/RestoreRequestDialog/styles.scss
Normal file
|
@ -0,0 +1,47 @@
|
|||
.wrap {
|
||||
padding: $gap $gap $gap * 4;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
padding: $gap;
|
||||
}
|
||||
|
||||
.text {
|
||||
font: $font_14_regular;
|
||||
padding: $gap;
|
||||
color: darken(white, 50%);
|
||||
}
|
||||
|
||||
.illustration {
|
||||
min-height: 160px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font: $font_18_semibold;
|
||||
}
|
||||
|
||||
.shade {
|
||||
@include outer_shadow();
|
||||
|
||||
background: $content_bg;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: $radius;
|
||||
padding: $gap * 2;
|
||||
box-sizing: border-box;
|
||||
text-transform: uppercase;
|
||||
font: $font_18_semibold;
|
||||
text-align: center;
|
||||
color: $wisegreen;
|
||||
|
||||
svg {
|
||||
fill: $wisegreen;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue