mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: yup validator & some refactor in layout
This commit is contained in:
parent
846d96473f
commit
cd27d81ccd
46
package-lock.json
generated
46
package-lock.json
generated
@ -2062,6 +2062,11 @@
|
|||||||
"@hapi/hoek": "^8.3.0"
|
"@hapi/hoek": "^8.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@hookform/resolvers": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.8.0.tgz",
|
||||||
|
"integrity": "sha512-ALlr0Bg6zDHdRsdqkwfWGPMnIxP4hqMRPvFDHp7lWXQeA7rKykto3cWqQQh1s0PzX043RHwMB6OHVPMwFJqwxg=="
|
||||||
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
||||||
@ -9816,6 +9821,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
},
|
},
|
||||||
|
"lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||||
|
},
|
||||||
"lodash._reinterpolate": {
|
"lodash._reinterpolate": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||||
@ -10283,6 +10293,11 @@
|
|||||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"nanoclone": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
|
||||||
|
},
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.1.25",
|
"version": "3.1.25",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
|
||||||
@ -12176,6 +12191,11 @@
|
|||||||
"react-is": "^16.8.1"
|
"react-is": "^16.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"property-expr": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg=="
|
||||||
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@ -14808,6 +14828,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||||
},
|
},
|
||||||
|
"toposort": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||||
|
},
|
||||||
"tough-cookie": {
|
"tough-cookie": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||||
@ -16695,6 +16720,27 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||||
|
},
|
||||||
|
"yup": {
|
||||||
|
"version": "0.32.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz",
|
||||||
|
"integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.10.5",
|
||||||
|
"@types/lodash": "^4.14.165",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
|
"lodash-es": "^4.17.15",
|
||||||
|
"nanoclone": "^0.2.1",
|
||||||
|
"property-expr": "^2.0.4",
|
||||||
|
"toposort": "^2.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
"@chakra-ui/react": "^1.0.0",
|
"@chakra-ui/react": "^1.0.0",
|
||||||
"@emotion/react": "^11.0.0",
|
"@emotion/react": "^11.0.0",
|
||||||
"@emotion/styled": "^11.0.0",
|
"@emotion/styled": "^11.0.0",
|
||||||
|
"@hookform/resolvers": "^2.8.0",
|
||||||
"@testing-library/jest-dom": "^5.9.0",
|
"@testing-library/jest-dom": "^5.9.0",
|
||||||
"@testing-library/react": "^10.2.1",
|
"@testing-library/react": "^10.2.1",
|
||||||
"@testing-library/user-event": "^12.0.2",
|
"@testing-library/user-event": "^12.0.2",
|
||||||
@ -27,7 +28,8 @@
|
|||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"typescript": "^3.9.5",
|
"typescript": "^3.9.5",
|
||||||
"web-vitals": "^0.2.2"
|
"web-vitals": "^0.2.2",
|
||||||
|
"yup": "^0.32.9"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { MdAccountCircle, MdVpnKey } from 'react-icons/md';
|
|
||||||
import { FormControl, FormLabel, InputGroup, Input, InputLeftElement, Button, Icon } from '@chakra-ui/react';
|
|
||||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
|
||||||
import useLoginQuery from 'hooks/useLoginQuery';
|
|
||||||
|
|
||||||
type AuthInputs = {
|
|
||||||
login: string;
|
|
||||||
password: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AuthForm: React.FC = () => {
|
|
||||||
const { register, reset, handleSubmit } = useForm<AuthInputs>();
|
|
||||||
const { login, loading } = useLoginQuery();
|
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<AuthInputs> = async data => {
|
|
||||||
try {
|
|
||||||
await login(data.login, data.password);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
|
||||||
<FormControl isRequired={true}>
|
|
||||||
<FormLabel>Login</FormLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<InputLeftElement children={<Icon as={MdAccountCircle} />} />
|
|
||||||
<Input type='text' placeholder='Type your login' {...register('login', { required: true })} />
|
|
||||||
</InputGroup>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl mt={5} isRequired={true}>
|
|
||||||
<FormLabel>Password</FormLabel>
|
|
||||||
<InputGroup>
|
|
||||||
<InputLeftElement children={<Icon as={MdVpnKey} />} />
|
|
||||||
<Input type='password' placeholder='********' {...register('password', { required: true })} />
|
|
||||||
</InputGroup>
|
|
||||||
</FormControl>
|
|
||||||
<Button
|
|
||||||
loadingText='Logging in...'
|
|
||||||
isLoading={loading}
|
|
||||||
type='submit'
|
|
||||||
colorScheme='blue'
|
|
||||||
variant='outline'
|
|
||||||
width='full'
|
|
||||||
mt={4}
|
|
||||||
>
|
|
||||||
Log in
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthForm;
|
|
||||||
93
src/components/Forms/Auth/AuthForm.tsx
Normal file
93
src/components/Forms/Auth/AuthForm.tsx
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { MdAccountCircle, MdSchool, MdVpnKey } from 'react-icons/md';
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
InputGroup,
|
||||||
|
Input,
|
||||||
|
InputLeftElement,
|
||||||
|
Button,
|
||||||
|
Icon,
|
||||||
|
Text,
|
||||||
|
Flex,
|
||||||
|
Box,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
import useLoginQuery from 'hooks/useLoginQuery';
|
||||||
|
import LoginValidatorSchema from 'validators/LoginValidatorSchema';
|
||||||
|
|
||||||
|
type AuthInputType = {
|
||||||
|
login: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthForm: React.FC = () => {
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
handleSubmit,
|
||||||
|
} = useForm<AuthInputType>({
|
||||||
|
resolver: yupResolver(LoginValidatorSchema),
|
||||||
|
});
|
||||||
|
const { login, loading } = useLoginQuery();
|
||||||
|
|
||||||
|
const onSubmit: SubmitHandler<AuthInputType> = data => {
|
||||||
|
login(data.login, data.password).finally(() => reset());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box w='full' maxW='450px' borderWidth='1px' borderRadius='lg' p='8'>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Flex justifyContent='center' alignItems='center'>
|
||||||
|
<Box w='full'>
|
||||||
|
<Box textAlign='center'>
|
||||||
|
<Flex justifyContent='center'>
|
||||||
|
<Box as={MdSchool} color='blue.500' size='64px' />
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>Login</FormLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<InputLeftElement children={<Icon as={MdAccountCircle} />} />
|
||||||
|
<Input type='text' placeholder='Login' {...register('login')} isInvalid={errors.login ? true : false} />
|
||||||
|
</InputGroup>
|
||||||
|
<Text as='small' color='red.500'>
|
||||||
|
{errors.login?.message}
|
||||||
|
</Text>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl mt={5}>
|
||||||
|
<FormLabel>Password</FormLabel>
|
||||||
|
<InputGroup>
|
||||||
|
<InputLeftElement children={<Icon as={MdVpnKey} />} />
|
||||||
|
<Input
|
||||||
|
type='password'
|
||||||
|
placeholder='******'
|
||||||
|
{...register('password')}
|
||||||
|
isInvalid={errors.password ? true : false}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
<Text as='small' color='red.500'>
|
||||||
|
{errors.password?.message}
|
||||||
|
</Text>
|
||||||
|
</FormControl>
|
||||||
|
<Button
|
||||||
|
loadingText='Logging in...'
|
||||||
|
isLoading={loading}
|
||||||
|
type='submit'
|
||||||
|
colorScheme='blue'
|
||||||
|
variant='outline'
|
||||||
|
width='full'
|
||||||
|
mt={4}
|
||||||
|
>
|
||||||
|
Log in
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AuthForm;
|
||||||
41
src/components/Forms/User/UpdateUserContactsForm.tsx
Normal file
41
src/components/Forms/User/UpdateUserContactsForm.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { MdSave } from 'react-icons/md';
|
||||||
|
import { Box, Heading, Stack } from '@chakra-ui/layout';
|
||||||
|
import { FormControl, FormHelperText } from '@chakra-ui/form-control';
|
||||||
|
import { Input } from '@chakra-ui/input';
|
||||||
|
import { Button } from '@chakra-ui/button';
|
||||||
|
|
||||||
|
const UpdateUserContactsForm: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Box as='form'>
|
||||||
|
<Box borderRadius='md' borderWidth='1px' padding='20px'>
|
||||||
|
<Heading as='h3' size='lg'>
|
||||||
|
My Contacts
|
||||||
|
</Heading>
|
||||||
|
<Stack spacing='5px' margin='20px 0'>
|
||||||
|
<FormControl id='tel'>
|
||||||
|
<FormHelperText color='gray.500'>Telephone</FormHelperText>
|
||||||
|
<Input type='number' size='md' variant='flushed' placeholder='123-456-7890' />
|
||||||
|
</FormControl>
|
||||||
|
<FormControl id='twitter'>
|
||||||
|
<FormHelperText color='gray.500'>Twitter</FormHelperText>
|
||||||
|
<Input type='text' size='md' variant='flushed' placeholder='https://twitter.com/id' />
|
||||||
|
</FormControl>
|
||||||
|
<FormControl id='telegram'>
|
||||||
|
<FormHelperText color='gray.500'>Telegram</FormHelperText>
|
||||||
|
<Input type='text' size='md' variant='flushed' placeholder='@tag' />
|
||||||
|
</FormControl>
|
||||||
|
<FormControl id='vk'>
|
||||||
|
<FormHelperText color='gray.500'>VKontakte</FormHelperText>
|
||||||
|
<Input type='text' size='md' variant='flushed' placeholder='https://vk.com/id' />
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
<Button colorScheme='blue' mt='4' type='submit' size='md' variant='outline' rightIcon={<MdSave />}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UpdateUserContactsForm;
|
||||||
66
src/components/User/UserAccountInfo.tsx
Normal file
66
src/components/User/UserAccountInfo.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Box, Heading, Stack, Flex, StackDivider, Text, Button } from '@chakra-ui/react';
|
||||||
|
import { IUser } from 'interfaces';
|
||||||
|
|
||||||
|
type UserAccountInfoPropsType = {
|
||||||
|
user: IUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserAccountInfo: React.FC<UserAccountInfoPropsType> = ({ user }) => {
|
||||||
|
return (
|
||||||
|
<Box borderRadius='md' borderWidth='1px' padding='20px'>
|
||||||
|
<Heading as='h3' size='lg'>
|
||||||
|
Account information
|
||||||
|
</Heading>
|
||||||
|
<Stack spacing='10px' mt='20px' divider={<StackDivider />}>
|
||||||
|
<Flex>
|
||||||
|
<Box>
|
||||||
|
<Text as='small' color='gray.500'>
|
||||||
|
First Name
|
||||||
|
</Text>
|
||||||
|
<Text fontWeight='medium' fontSize='lg'>
|
||||||
|
{user.first_name}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex>
|
||||||
|
<Box>
|
||||||
|
<Text as='small' color='gray.500'>
|
||||||
|
Last Name
|
||||||
|
</Text>
|
||||||
|
<Text fontWeight='medium' fontSize='lg'>
|
||||||
|
{user.last_name}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex justifyContent='space-between' alignItems='center'>
|
||||||
|
<Box>
|
||||||
|
<Text as='small' color='gray.500'>
|
||||||
|
Email
|
||||||
|
</Text>
|
||||||
|
<Text fontWeight='medium' fontSize='lg'>
|
||||||
|
{user.email}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Button>Edit</Button>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex justifyContent='space-between' alignItems='center'>
|
||||||
|
<Box>
|
||||||
|
<Text as='small' color='gray.500'>
|
||||||
|
Password
|
||||||
|
</Text>
|
||||||
|
<Text fontWeight='medium' fontSize='lg'>
|
||||||
|
**********
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Button>Change</Button>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserAccountInfo;
|
||||||
@ -53,6 +53,7 @@ const useLoginQuery = () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.error(error);
|
||||||
handleError(error);
|
handleError(error);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -3,11 +3,10 @@ import Helmet from 'react-helmet';
|
|||||||
import { Redirect } from 'react-router-dom';
|
import { Redirect } from 'react-router-dom';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { IPageProps } from 'interfaces';
|
import { IPageProps } from 'interfaces';
|
||||||
import { Flex, Box } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
import { useRootStore } from 'hooks/useRootStore';
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
import { MdSchool } from 'react-icons/md';
|
|
||||||
|
|
||||||
import AuthForm from 'components/Auth/AuthForm';
|
import AuthForm from 'components/Forms/Auth/AuthForm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auth page
|
* Auth page
|
||||||
@ -25,16 +24,7 @@ const AuthPage: React.FC<IPageProps> = () => {
|
|||||||
<title>Auth</title>
|
<title>Auth</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Flex minHeight='100vh' align='center' justifyContent='center' padding='5'>
|
<Flex minHeight='100vh' align='center' justifyContent='center' padding='5'>
|
||||||
<Box p={8} width='full' maxWidth='450px' borderWidth={1} borderRadius={8}>
|
|
||||||
<Box textAlign='center'>
|
|
||||||
<Flex justifyContent='center'>
|
|
||||||
<Box as={MdSchool} color='blue.500' size='64px' />
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<AuthForm />
|
<AuthForm />
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,27 +6,21 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
Text,
|
Text,
|
||||||
Stack,
|
|
||||||
Button,
|
|
||||||
StackDivider,
|
|
||||||
FormControl,
|
|
||||||
Input,
|
|
||||||
Tabs,
|
Tabs,
|
||||||
TabList,
|
TabList,
|
||||||
Tab,
|
Tab,
|
||||||
TabPanels,
|
TabPanels,
|
||||||
TabPanel,
|
TabPanel,
|
||||||
FormHelperText,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
import { MdSave } from 'react-icons/md';
|
|
||||||
|
|
||||||
import { IPageProps } from 'interfaces';
|
import { IPageProps } from 'interfaces';
|
||||||
import { useRootStore } from 'hooks/useRootStore';
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import UserBadge from 'components/User/UserBadge';
|
import UserBadge from 'components/User/UserBadge';
|
||||||
import LoadingProfilePage from 'components/Loading/LoadingProfilePage';
|
import LoadingProfilePage from 'components/Loading/LoadingProfilePage';
|
||||||
|
import UserAccountInfo from 'components/User/UserAccountInfo';
|
||||||
|
import UpdateUserContactsForm from 'components/Forms/User/UpdateUserContactsForm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile page
|
* Profile page
|
||||||
@ -110,92 +104,11 @@ const ProfilePage: React.FC<IPageProps> = ({ title }) => {
|
|||||||
<Tab>My contacts</Tab>
|
<Tab>My contacts</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
{/* Account info */}
|
|
||||||
<TabPanel padding='10px 0' mt='20px'>
|
<TabPanel padding='10px 0' mt='20px'>
|
||||||
<Box borderRadius='md' borderWidth='1px' padding='20px'>
|
<UserAccountInfo user={userStore.me} />
|
||||||
<Heading as='h3' size='lg'>
|
|
||||||
Account information
|
|
||||||
</Heading>
|
|
||||||
<Stack spacing='10px' mt='20px' divider={<StackDivider />}>
|
|
||||||
<Flex>
|
|
||||||
<Box>
|
|
||||||
<Text as='small' color='gray.500'>
|
|
||||||
First Name
|
|
||||||
</Text>
|
|
||||||
<Text fontWeight='medium' fontSize='lg'>
|
|
||||||
{userStore.me.first_name}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex>
|
|
||||||
<Box>
|
|
||||||
<Text as='small' color='gray.500'>
|
|
||||||
Last Name
|
|
||||||
</Text>
|
|
||||||
<Text fontWeight='medium' fontSize='lg'>
|
|
||||||
{userStore.me.last_name}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex justifyContent='space-between' alignItems='center'>
|
|
||||||
<Box>
|
|
||||||
<Text as='small' color='gray.500'>
|
|
||||||
Email
|
|
||||||
</Text>
|
|
||||||
<Text fontWeight='medium' fontSize='lg'>
|
|
||||||
{userStore.me.email}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<Button>Edit</Button>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex justifyContent='space-between' alignItems='center'>
|
|
||||||
<Box>
|
|
||||||
<Text as='small' color='gray.500'>
|
|
||||||
Password
|
|
||||||
</Text>
|
|
||||||
<Text fontWeight='medium' fontSize='lg'>
|
|
||||||
**********
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<Button>Change</Button>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
{/* Contacts */}
|
|
||||||
<TabPanel padding='10px 0' mt='20px'>
|
<TabPanel padding='10px 0' mt='20px'>
|
||||||
<Box as='form'>
|
<UpdateUserContactsForm />
|
||||||
<Box borderRadius='md' borderWidth='1px' padding='20px'>
|
|
||||||
<Heading as='h3' size='lg'>
|
|
||||||
My Contacts
|
|
||||||
</Heading>
|
|
||||||
<Stack spacing='5px' margin='20px 0'>
|
|
||||||
<FormControl id='tel'>
|
|
||||||
<FormHelperText color='gray.500'>Telephone</FormHelperText>
|
|
||||||
<Input type='number' size='md' variant='flushed' placeholder='123-456-7890' />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl id='twitter'>
|
|
||||||
<FormHelperText color='gray.500'>Twitter</FormHelperText>
|
|
||||||
<Input type='text' size='md' variant='flushed' placeholder='https://twitter.com/id' />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl id='telegram'>
|
|
||||||
<FormHelperText color='gray.500'>Telegram</FormHelperText>
|
|
||||||
<Input type='text' size='md' variant='flushed' placeholder='@tag' />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl id='vk'>
|
|
||||||
<FormHelperText color='gray.500'>VKontakte</FormHelperText>
|
|
||||||
<Input type='text' size='md' variant='flushed' placeholder='https://vk.com/id' />
|
|
||||||
</FormControl>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
<Button colorScheme='blue' mt='4' type='submit' size='md' variant='outline' rightIcon={<MdSave />}>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
8
src/validators/LoginValidatorSchema.ts
Normal file
8
src/validators/LoginValidatorSchema.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
|
const LoginValidatorSchema = yup.object().shape({
|
||||||
|
login: yup.string().required('Login is required'),
|
||||||
|
password: yup.string().min(6, 'Password must be at least 6 characters').required('Password is required'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default LoginValidatorSchema;
|
||||||
Loading…
x
Reference in New Issue
Block a user