1
0
Fork 0
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:
Fedor Katurov 2019-11-25 16:08:22 +07:00
parent c0c832d158
commit 6dcb21e9e4
18 changed files with 292 additions and 88 deletions

View file

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

View file

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

View file

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

View file

@ -28,9 +28,7 @@ $vk_color: $secondary_color;
}
.forgot_button {
background: $content_bg;
box-shadow: none;
color: $secondary_color;
opacity: 0.5;
}
.buttons {

View file

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

View 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;
}
}