Added wrapper component for admin submodule, added basic styles for it
This commit is contained in:
parent
7007672cb3
commit
ca6c639052
14
src/App.tsx
14
src/App.tsx
@ -9,8 +9,7 @@ import { queryIsEmpty } from './components/navigation/Navbar/utils';
|
|||||||
import SubjectList from './views/SubjectList';
|
import SubjectList from './views/SubjectList';
|
||||||
import { ILoadingState, IFilterQuery } from './types';
|
import { ILoadingState, IFilterQuery } from './types';
|
||||||
import NothingFound from './views/NothingFound';
|
import NothingFound from './views/NothingFound';
|
||||||
import UploadForm from './views/Admin/UploadForm';
|
import Admin from './views/Admin';
|
||||||
import LogInForm from './views/Admin/LogInForm';
|
|
||||||
|
|
||||||
const useDidUpdate: typeof useEffect = (func, dependencies) => {
|
const useDidUpdate: typeof useEffect = (func, dependencies) => {
|
||||||
const didMountRef = useRef(false);
|
const didMountRef = useRef(false);
|
||||||
@ -72,15 +71,8 @@ const App = () => {
|
|||||||
setLoading={setLoading}
|
setLoading={setLoading}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/u">
|
<Route path="/a">
|
||||||
<UploadForm setLoading={setLoading} token={token} setToken={setToken} />
|
<Admin token={token} setToken={setToken} setLoading={setLoading} />
|
||||||
</Route>
|
|
||||||
<Route path="/l">
|
|
||||||
<LogInForm
|
|
||||||
setLoading={setLoading}
|
|
||||||
token={token}
|
|
||||||
setToken={setToken}
|
|
||||||
/>
|
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="*">
|
<Route path="*">
|
||||||
<NothingFound setLoading={setLoading} />
|
<NothingFound setLoading={setLoading} />
|
||||||
|
@ -9,11 +9,11 @@ const genName = (
|
|||||||
return error.toString();
|
return error.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path === '/u') {
|
if (path === '/a/u') {
|
||||||
return 'Upload form';
|
return 'Upload form';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path === '/l') {
|
if (path === '/a/l') {
|
||||||
return 'login';
|
return 'login';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@
|
|||||||
height: 6vh;
|
height: 6vh;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
width: 75vw;
|
width: 75vw;
|
||||||
|
color: rgb(54, 54, 69);
|
||||||
font-size: 2.5vh;
|
font-size: 2.5vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { Dispatch, SetStateAction, useEffect } from 'react';
|
import React, { Dispatch, SetStateAction, useEffect } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { ILoadingState } from '../../../types';
|
import { ILoadingState } from '../../../types';
|
||||||
import { handleFormSubmit } from '../../../utils';
|
import { handleFormSubmit } from '../../../utils';
|
||||||
import { handleSuccessfulLogin } from './handlers';
|
import { handleSuccessfulLogin } from './handlers';
|
||||||
|
import './main.css';
|
||||||
|
|
||||||
type props = {
|
type props = {
|
||||||
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
||||||
@ -16,14 +18,17 @@ const LogInForm: React.FC<props> = ({ setLoading, token, setToken }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading({ fetching: false, error: '' });
|
setLoading({ fetching: false, error: '' });
|
||||||
if (token) {
|
if (token) {
|
||||||
historyPush('/u');
|
historyPush('/a/u');
|
||||||
}
|
}
|
||||||
}, [setLoading, historyPush, token]);
|
}, [setLoading, historyPush, token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
|
id="logIn"
|
||||||
onSubmit={(e) =>
|
onSubmit={(e) =>
|
||||||
handleFormSubmit(e, 'api/login', (res: Response) => handleSuccessfulLogin(res, setToken))
|
handleFormSubmit(e, 'api/login', (res: Response) =>
|
||||||
|
handleSuccessfulLogin(res, setToken)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<label htmlFor="">Имя пользователя</label>
|
<label htmlFor="">Имя пользователя</label>
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
#logIn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
padding: 2vh;
|
||||||
|
padding-top: 5vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logIn input {
|
||||||
|
height: 6vh;
|
||||||
|
border: none;
|
||||||
|
border-radius: 1000px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 2vh;
|
||||||
|
width: 100%;
|
||||||
|
margin: 1vh 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logIn input[type='submit'] {
|
||||||
|
background-color: rgb(255, 109, 109);
|
||||||
|
color: white;
|
||||||
|
}
|
@ -5,6 +5,7 @@ import Select from '../../../components/uploadForm/Select';
|
|||||||
import { ILoadingState } from '../../../types';
|
import { ILoadingState } from '../../../types';
|
||||||
import { handleFormSubmit } from '../../../utils';
|
import { handleFormSubmit } from '../../../utils';
|
||||||
import selectOptions from './selectOptions.json';
|
import selectOptions from './selectOptions.json';
|
||||||
|
import './main.css';
|
||||||
|
|
||||||
type props = {
|
type props = {
|
||||||
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
||||||
@ -16,62 +17,54 @@ const UploadForm: React.FC<props> = ({ setLoading, token, setToken }) => {
|
|||||||
const { push: historyPush } = useHistory();
|
const { push: historyPush } = useHistory();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading({ fetching: false, error: '' });
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
historyPush('/l');
|
historyPush('/a/l');
|
||||||
}
|
}
|
||||||
}, [setLoading, historyPush, token]);
|
}, [setLoading, historyPush, token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<form
|
||||||
<form
|
id="uploadForm"
|
||||||
onSubmit={(e) =>
|
onSubmit={(e) =>
|
||||||
handleFormSubmit(e, 'api/card/create', undefined, {
|
handleFormSubmit(e, 'api/card/create', undefined, {
|
||||||
Authorization: `Token ${localStorage.token}`
|
Authorization: `Token ${localStorage.token}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<label htmlFor="title">Название</label>
|
<label htmlFor="title">Название</label>
|
||||||
<input type="text" name="title" />
|
<input type="text" name="title" />
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
label="Преподаватель"
|
label="Преподаватель"
|
||||||
name="teacher"
|
name="teacher"
|
||||||
options={selectOptions.teacher}
|
options={selectOptions.teacher}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
label="Тип задания"
|
label="Тип задания"
|
||||||
name="type_num"
|
name="type_num"
|
||||||
options={selectOptions.type_num}
|
options={selectOptions.type_num}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
label="Класс"
|
label="Класс"
|
||||||
name="class_num"
|
name="class_num"
|
||||||
options={selectOptions.class_num}
|
options={selectOptions.class_num}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
label="Предмет"
|
label="Предмет"
|
||||||
name="predmet_type"
|
name="predmet_type"
|
||||||
options={selectOptions.predmet_type}
|
options={selectOptions.predmet_type}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<label htmlFor="image">Файл</label>
|
<label htmlFor="image">Файл</label>
|
||||||
|
<aside>
|
||||||
<input type="file" name="image" id="image" />
|
<input type="file" name="image" id="image" />
|
||||||
|
</aside>
|
||||||
|
|
||||||
<input type="submit" value="Отправить" />
|
<input type="submit" value="Отправить" />
|
||||||
</form>
|
</form>
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
localStorage.removeItem('token');
|
|
||||||
setToken(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Выход
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
#uploadForm {
|
||||||
|
padding: 2vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadForm>input,
|
||||||
|
#uploadForm>select,
|
||||||
|
#uploadForm>aside {
|
||||||
|
height: 6vh;
|
||||||
|
border: none;
|
||||||
|
border-radius: 1000px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 2vh;
|
||||||
|
appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
background-color: white;
|
||||||
|
margin: 1vh 0;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadForm aside {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadFrom input[type='file'] {}
|
@ -1,7 +1,66 @@
|
|||||||
import React from 'react';
|
import React, { Dispatch, SetStateAction, useEffect } from 'react';
|
||||||
|
import { Link, Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
|
||||||
|
|
||||||
const Admin: React.FC = () => {
|
import { ILoadingState } from '../../types';
|
||||||
return <div></div>;
|
import LogInForm from './LogInForm';
|
||||||
|
import UploadForm from './UploadForm';
|
||||||
|
import './main.css';
|
||||||
|
|
||||||
|
type props = {
|
||||||
|
token: string | null;
|
||||||
|
setToken: Dispatch<SetStateAction<string | null>>;
|
||||||
|
setLoading: Dispatch<SetStateAction<ILoadingState>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Admin: React.FC<props> = ({ token, setToken, setLoading }) => {
|
||||||
|
const { path, url } = useRouteMatch();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoading({ fetching: false, error: '' });
|
||||||
|
}, [setLoading]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="admin">
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Link to={`${url}/u`}>Добавить</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link to={`${url}/r`}>Удалить</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
setToken(null);
|
||||||
|
}}
|
||||||
|
id="logSwitch"
|
||||||
|
>
|
||||||
|
<Link to={`${url}/l`}>Выход</Link>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
<Switch>
|
||||||
|
<Route path={`${path}/u`}>
|
||||||
|
<UploadForm
|
||||||
|
setLoading={setLoading}
|
||||||
|
token={token}
|
||||||
|
setToken={setToken}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route path={`${path}/l`}>
|
||||||
|
<LogInForm
|
||||||
|
setLoading={setLoading}
|
||||||
|
token={token}
|
||||||
|
setToken={setToken}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route path={`${path}/`}>
|
||||||
|
<Redirect to={`${path}/l`} />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Admin;
|
export default Admin;
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
#admin {
|
||||||
|
min-height: calc(79.5vh + 20px);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav {
|
||||||
|
background-color: white;
|
||||||
|
padding: 2vh;
|
||||||
|
padding-top: calc(20px + 0.75vh);
|
||||||
|
margin-top: -20px;
|
||||||
|
border-radius: 0 0 20px 20px;
|
||||||
|
height: 16vmax;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav li {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav li a {
|
||||||
|
color: rgb(255, 109, 109);
|
||||||
|
border-bottom: 1px solid rgb(255, 109, 109);
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav li a,
|
||||||
|
#admin nav #logSwitch a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav #logSwitch {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgb(255, 109, 109);
|
||||||
|
border: none;
|
||||||
|
padding: 1.5vh;
|
||||||
|
height: 6vh;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 2.5vh;
|
||||||
|
right: 2vh;
|
||||||
|
top: calc((16vmax + 20px - 6vh) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#admin nav #logSwitch a {
|
||||||
|
color: white;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user