1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 12:56:41 +07:00

login mechanism

This commit is contained in:
muerwre 2019-04-04 16:36:50 +07:00
parent 6168841f78
commit 9528e7f699
27 changed files with 528 additions and 96 deletions

View file

@ -1,13 +1,7 @@
import * as React from 'react';
import classnames from 'classnames';
// import * as AutoResponsive from 'autoresponsive-react';
// const ReactGridLayout = require('react-grid-layout');
// import 'react-grid-layout/css/styles.css';
// import 'react-resizable/css/styles.css';
const style = require('./style.scss');
// const Packery = require('react-packery-component')(React);
// http://37.192.131.144/hero/photos/photo-20120825-1532512.jpg
export const TestGrid = () => (
<div className={style.grid_test}>
@ -23,50 +17,3 @@ export const TestGrid = () => (
<div className={classnames([style.cell, style.vert_1, style.hor_1])} key="j" />
</div>
);
// export const TestGrid = () => (
// <ReactGridLayout
// className="layout"
// cols={4}
// rowHeight={256}
// width={1024 + 256}
// layout={layout}
// margin={[0, 0]}
// compactType="vertical"
// verticalCompact
// >
// <div className={style.cell} key="a" />
// <div className={style.cell} key="b" />
// <div className={style.cell} key="c" />
// <div className={style.cell} key="d" />
// <div className={style.cell} key="e" />
// <div className={style.cell} key="f" />
// <div className={style.cell} key="g" />
// </ReactGridLayout>
// );
// export const TestGrid = () => (
// <AutoResponsive
// itemMargin={0}
// containerWidth={1024 + 256}
// itemClassName={style.cell}
// gridWidth={256}
// transitionDuration={0}
// >
// <div style={{ width: 256 * 4, height: 256 * 2 }} className={style.cell} key="a" />
// <div style={{ width: 256, height: 256 * 2 }} className={style.cell} key="b" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="c" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d" />
// <div style={{ width: 256 * 2, height: 256 * 2 }} className={style.cell} key="h" />
// <div style={{ width: 256 * 2, height: 256 }} className={style.cell} key="e" />
// <div style={{ width: 256 * 2, height: 256 }} className={style.cell} key="f" />
// <div style={{ width: 256 * 2, height: 256 }} className={style.cell} key="g" />
// <div style={{ width: 256 * 2, height: 256 }} className={style.cell} key="g1" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d1" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d2" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d3" />
// <div style={{ width: 256, height: 256 }} className={style.cell} key="d4" />
// </AutoResponsive>
// );

View file

@ -14,8 +14,8 @@ $cols: $content_width / $cell;
grid-auto-rows: 256px;
grid-auto-flow: row dense;
grid-column-gap: 4px;
grid-row-gap: 4px;
grid-column-gap: $grid_line;
grid-row-gap: $grid_line;
}
.cell {
@ -25,6 +25,7 @@ $cols: $content_width / $cell;
flex: 0 0;
background: $cell_bg;
@include outer_shadow();
//&::after {
// content: ' ';
// background: transparentize(white, 0.9);

View file

@ -0,0 +1,20 @@
import * as React from 'react';
const style = require('./style.scss');
interface IButtonProps {
children?: string,
label?: string,
onClick?: React.MouseEventHandler,
}
export const Button: React.FunctionComponent<IButtonProps> = ({
children,
label,
onClick = () => {},
}) => (
<div className={style.container} onClick={onClick}>
{label || children || ''}
</div>
);

View file

@ -0,0 +1,14 @@
.container {
height: $input_height;
border-radius: $input_radius;
display: flex;
background: $button_bg_color;
align-items: center;
justify-content: center;
text-transform: uppercase;
font-weight: 600;
font-size: $text_small;
cursor: pointer;
@include outer_shadow();
}

View file

@ -0,0 +1,21 @@
import * as React from 'react';
import classNames = require("classnames");
const style = require('./style.scss');
interface IInfoProps {
text?: string,
children?: string,
level?: string,
}
export const Info: React.FunctionComponent<IInfoProps> = ({
text,
children,
level = 'normal',
}) => (
<div className={classNames(style.container, { [level]: true })}>
{
text || children || ''
}
</div>
);

View file

@ -0,0 +1,28 @@
.container {
min-height: $info_height;
border-radius: $input_radius;
display: flex;
align-items: center;
justify-content: center;
font-size: $text_small;
line-height: 1.2em;
padding: $gap;
background: transparentize(white, 0.9);
&:global(.danger) {
color: white;
background: transparentize($color_red, 0.5);
}
&:global(.warning) {
color: white;
background: transparentize($color_yellow, 0.5);
}
&:global(.primary) {
color: white;
background: transparentize($color_blue, 0.5);
}
}

View file

@ -0,0 +1,38 @@
import * as React from 'react';
const style = require('./style.scss');
interface ITextInputProps {
type?: 'text' | 'password',
placeholder?: string,
label?: string,
value?: string,
onChange: React.ChangeEventHandler,
}
export const TextInput: React.FunctionComponent<ITextInputProps> = ({
type = 'text',
placeholder = '',
label,
onChange = () => {},
value='',
}) => (
<div
className={style.wrapper}
>
{
label &&
<div className={style.label}>{label}</div>
}
<div className={style.container}>
<input
placeholder={placeholder}
className={style.input}
type={type}
onChange={onChange}
value={value}
/>
</div>
</div>
);

View file

@ -0,0 +1,37 @@
.wrapper {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.label {
background: $input_bg_color;
font-size: 10px;
text-transform: uppercase;
font-weight: 600;
padding: 2px $gap;
}
.container {
height: $input_height;
background: $input_bg_color;
border-radius: $input_radius;
flex-direction: row;
flex: 1 0;
display: flex;
align-self: stretch;
align-items: center;
justify-content: center;
@include input_shadow();
}
.input {
outline: none;
background: transparent;
flex: 1;
border: none;
font-size: inherit;
color: white;
padding: 0 $gap;
box-sizing: border-box;
}

View file

@ -0,0 +1,103 @@
import * as React from 'react';
import { TextInput } from "$components/input/TextInput";
import { Button } from "$components/input/Button";
import { connect } from 'react-redux';
import { bindActionCreators } from "redux";
import { userSendLoginRequest, userSetLoginError } from "$redux/user/actions";
import { IUserFormStateLogin, IUserState } from "$redux/user/reducer";
import { Info } from "$components/input/Info";
const login = require('$containers/LoginLayout/style');
const style = require('./style.scss');
interface ILoginFormProps {
error: IUserFormStateLogin['error'],
userSendLoginRequest: typeof userSendLoginRequest,
userSetLoginError: typeof userSetLoginError,
}
interface ILoginFormState {
username: string,
password: string,
}
class Component extends React.PureComponent<ILoginFormProps, ILoginFormState> {
state = {
username: 'user',
password: 'password',
};
sendRequest = () => {
console.log('send?');
this.props.userSendLoginRequest(this.state);
};
changeField = <T extends keyof ILoginFormState>(field: T) => ({ target: { value }}: React.ChangeEvent<HTMLInputElement>) => {
if (this.props.error) this.props.userSetLoginError({ error: null });
this.setState({ [field]: value } as Pick<ILoginFormState, keyof ILoginFormState>);
};
render() {
const { error } = this.props;
const { username, password } = this.state;
return (
<div className={login.form}>
<div className={style.container}>
<div className={style.area_left}>
</div>
<div className={style.area_right}>
<div className={style.area_sign}>
РЕШИТЕЛЬНО<br />ВОЙТИ
</div>
<div className="spc double" />
<div className={style.inputs}>
<TextInput
label="Логин"
value={username}
onChange={this.changeField('username')}
/>
<div className="gap" />
<TextInput
label="Пароль"
type="password"
value={password}
onChange={this.changeField('password')}
/>
<div className="spc double" />
<Button onClick={this.sendRequest}>
Войти
</Button>
{
error &&
<React.Fragment>
<div className="spc" />
<Info>
{error}
</Info>
</React.Fragment>
}
</div>
</div>
</div>
</div>
)
}
}
const mapStateToProps = ({ user: { form_state: { login }}}: { user: IUserState }) => ({ ...login });
const mapDispatchToProps = dispatch => bindActionCreators({
userSendLoginRequest,
userSetLoginError,
}, dispatch);
export const LoginForm = connect(mapStateToProps, mapDispatchToProps)(Component);

View file

@ -0,0 +1,43 @@
.container {
display: grid;
flex: 1;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 1fr;
grid-row-gap: $grid_line;
grid-column-gap: $grid_line;
}
.area_left {
grid-column-end: span 3;
background: $content_bg_color;
padding: $spc;
border-radius: $panel_radius 0 0 $panel_radius;
display: flex;
align-items: center;
justify-content: center;
@include outer_shadow();
}
.area_right {
grid-column-end: span 1;
background: $content_bg_secondary;
padding: $spc;
border-radius: $panel_radius 0 0 $panel_radius;
user-select: none;
@include outer_shadow();
}
.area_sign {
font-size: $text_sign;
font-weight: 800;
line-height: 1.2em;
}
.inputs {
display: flex;
align-items: stretch;
flex-direction: column;
}

View file

@ -1,12 +1,12 @@
import * as React from 'react';
import { Logo } from "$components/main/Logo";
const style = require('./style.scss');
export const Header = () => (
<div className="default_container head_container">
<div className={style.container}>
<div className={style.logo}>
VAULT
</div>
<Logo />
<div className={style.spacer} />
<div className={style.plugs}>
<div>depth</div>

View file

@ -7,11 +7,6 @@
height: 100px;
}
.logo {
font-size: 1.4em;
font-weight: 800;
display: flex;
}
.spacer {
flex: 1;
@ -36,7 +31,12 @@
display: block;
}
&:last-child::after { display: none; }
&:last-child {
padding-right: 0;
&::after { display: none; }
}
}
}

View file

@ -0,0 +1,8 @@
import * as React from 'react';
const style = require('./style.scss');
export const Logo = () => (
<div className={style.logo}>
VAULT
</div>
);

View file

@ -0,0 +1,5 @@
.logo {
font-size: $text_sign;
font-weight: 800;
display: flex;
}