lab4 maybe it is end

This commit is contained in:
Zakharov_Rostislav 2023-12-04 22:25:03 +04:00
parent dd89094f85
commit 196ce072ba
18 changed files with 529 additions and 28 deletions

View File

@ -13,6 +13,24 @@
"name": "Лирическое стихотворение" "name": "Лирическое стихотворение"
} }
], ],
"authors": [
{
"id": 1,
"name": "Пушкин А. С."
},
{
"id": 2,
"name": "Державин Г. Р."
},
{
"id": 3,
"name": "Квинт Гораций Флакк"
},
{
"id": 4,
"name": "Карамзин Н. М."
}
],
"books": [ "books": [
{ {
"categoriesId": "3", "categoriesId": "3",
@ -46,23 +64,5 @@
"image": "", "image": "",
"id": 4 "id": 4
} }
],
"authors": [
{
"id": 1,
"name": "Пушкин А. С."
},
{
"id": 2,
"name": "Державин Г. Р."
},
{
"id": 3,
"name": "Квинт Гораций Флакк"
},
{
"id": 4,
"name": "Карамзин Н. М."
}
] ]
} }

View File

@ -12,7 +12,7 @@ const App = ({ routes }) => {
<Container className='p-2' as="main" fluid> <Container className='p-2' as="main" fluid>
<Outlet /> <Outlet />
</Container> </Container>
<Footer /> <Footer/>
</> </>
); );
}; };

View File

@ -5,7 +5,7 @@ body{
font-size: 1.5em; font-size: 1.5em;
} }
.library-button{ .lib-btn{
background-color: #e8b8e8; background-color: #e8b8e8;
color: #000000; color: #000000;
font-size: 1em; font-size: 1em;
@ -13,12 +13,16 @@ body{
border: #e8b8e8; border: #e8b8e8;
} }
.library-button:hover{ .lib-btn:hover{
background-color: #bf80e6; background-color: #bf80e6;
color: #000000; color: #000000;
font-weight: bold; font-weight: bold;
} }
.lib-table{
color: #000000;
}
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
} }

View File

@ -6,13 +6,75 @@ import App from './App.jsx';
import './index.css'; import './index.css';
import ErrorPage from './pages/ErrorPage.jsx'; import ErrorPage from './pages/ErrorPage.jsx';
import MainPage from './pages/MainPage.jsx'; import MainPage from './pages/MainPage.jsx';
import UserPage from './pages/UserPage.jsx';
import AdminPage from './pages/AdminPage.jsx';
import BooksTable from './pages/BooksTable.jsx';
import CategoriesTable from './pages/CategoriesTable.jsx';
import AuthorsTable from './pages/AuthorsTable.jsx';
import UserHistory from './pages/UserHistory.jsx';
import UserFavorities from './pages/UserFavorities.jsx';
import RegPage from './pages/RegPage.jsx';
import LoginPage from './pages/LoginPage.jsx';
import BookEdit from './pages/BookEdit.jsx';
import CategoryEdit from './pages/CategoryEdit.jsx';
import AuthorEdit from './pages/AuthorEdit.jsx';
const routes = [ const routes = [
{ {
index: true, index: true,
path: '/', path: '/',
element: <MainPage />, element: <MainPage/>,
title: 'Главная страница', title: 'Главная',
},
{
path: '/login-page',
element: <LoginPage/>,
title: 'Войти',
},
{
path: '/user-page',
element: <UserPage/>,
title: 'Личный кабинет',
},
{
path: '/admin-page',
element: <AdminPage/>,
},
{
path: '/books-table',
element: <BooksTable/>,
},
{
path: '/categories-table',
element: <CategoriesTable/>,
},
{
path: '/authors-table',
element: <AuthorsTable/>,
},
{
path: '/user-history',
element: <UserHistory/>,
},
{
path: '/user-favorities',
element: <UserFavorities/>,
},
{
path: '/reg-page',
element: <RegPage/>,
},
{
path: '/book-edit',
element: <BookEdit/>,
},
{
path: '/category-edit',
element: <CategoryEdit/>,
},
{
path: '/author-edit',
element: <AuthorEdit/>,
}, },
]; ];

View File

@ -0,0 +1,23 @@
import { Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const AdminPage = () => {
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Страница администратора.
</h1>
<p className="mt-2 text-md-start text-center">
Здесь вы можете просмотреть существующие книги,
категории и авторов, а также добавить новых.
</p>
<div className="d-grid gap-2 mt-2 d-md-flex justify-content-md-start">
<Button as={Link} to="/books-table" className='lib-btn'>Таблица книг</Button>
<Button as={Link} to="/categories-table" className='lib-btn'>Страница категорий</Button>
<Button as={Link} to="/authors-table" className='lib-btn'>Таблица авторов</Button>
</div>
</>
);
};
export default AdminPage;

View File

@ -0,0 +1,59 @@
import { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
const AuthorEdit = () => {
const [validated, setValidated] = useState(false);
const navigate = useNavigate();
const handleSubmit = (event) => {
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
setValidated(true);
};
return (
<>
<h1 className='mt-2 text-center'>
Добавление/редактирование автора.
</h1>
<div className="text-center">
<img id="image-preview" src="https://via.placeholder.com/200" alt="placeholder"/>
</div>
<Form id="books-form" noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-2" controlId="author">
<Form.Label htmlFor="author" className="form-label">Автор</Form.Label>
<Form.Select name='selected' required>
</Form.Select>
</Form.Group>
<Form.Group className="mb-2" controlId="name">
<Form.Label>Название</Form.Label>
<Form.Control type="text" name="name" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="country">
<Form.Label>Страна</Form.Label>
<Form.Control type="text" name="country" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="birthYear">
<Form.Label>Год рождения</Form.Label>
<Form.Control type="text" name="birthYear" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="deathYear">
<Form.Label>Год смерти</Form.Label>
<Form.Control type="text" name="deathYear" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="file">
<Form.Label>Изображение</Form.Label>
<Form.Control type="file" name="image" accept="image/*"/>
</Form.Group>
<div className="d-grid gap-2 mt-4 d-md-flex justify-content-md-center">
<Button className="lib-btn" onClick={() => navigate(-1)}>Назад</Button>
<Button className="lib-btn" type="submit" variant="primary">Сохранить</Button>
</div>
</Form>
</>
);
};
export default AuthorEdit;

View File

@ -0,0 +1,27 @@
import { Button, Table } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const AuthorsTable = () => {
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Таблица авторов.
</h1>
<Button as={Link} to="/author-edit" className='lib-btn'>Добавить автора</Button>
<Table className="mt-2 lib-table" striped>
<thead>
<th scope="col"></th>
<th scope="col" className="w-25">Имя</th>
<th scope="col" className="w-25">Страна</th>
<th scope="col" className="w-25">Год рождения</th>
<th scope="col" className="w-25">Год смерти</th>
<th scope="col"></th>
<th scope="col"></th>
</thead>
<tbody></tbody>
</Table>
</>
);
};
export default AuthorsTable;

View File

@ -0,0 +1,56 @@
import { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
const BookEdit = () => {
const [validated, setValidated] = useState(false);
const navigate = useNavigate();
const handleSubmit = (event) => {
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
setValidated(true);
};
return (
<>
<h1 className='mt-2 text-center'>
Добавление/редактирование книги.
</h1>
<div className="text-center">
<img id="image-preview" src="https://via.placeholder.com/200" alt="placeholder"/>
</div>
<Form id="books-form" noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-2" controlId="author">
<Form.Label htmlFor="author" className="form-label">Автор</Form.Label>
<Form.Select name='selected' required>
</Form.Select>
</Form.Group>
<Form.Group className="mb-2" controlId="name">
<Form.Label>Название</Form.Label>
<Form.Control type="text" name="name" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="category">
<Form.Label htmlFor="category" className="form-label">Категория</Form.Label>
<Form.Select name='selected' required>
</Form.Select>
</Form.Group>
<Form.Group className="mb-2" controlId="year">
<Form.Label>Год издания</Form.Label>
<Form.Control type="text" name="year" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="file">
<Form.Label>Изображение</Form.Label>
<Form.Control type="file" name="image" accept="image/*"/>
</Form.Group>
<div className="d-grid gap-2 mt-4 d-md-flex justify-content-md-center">
<Button className="lib-btn" onClick={() => navigate(-1)}>Назад</Button>
<Button className="lib-btn" type="submit" variant="primary">Сохранить</Button>
</div>
</Form>
</>
);
};
export default BookEdit;

View File

@ -0,0 +1,28 @@
import { Button, Table } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const BooksTable = () => {
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Таблица книг.
</h1>
<Button as={Link} to="/book-edit" className='lib-btn'>Добавить книгу</Button>
<Table className="mt-2 lib-table" striped>
<thead>
<th scope="col"></th>
<th scope="col" className="w-25">Автор</th>
<th scope="col" className="w-25">Название</th>
<th scope="col" className="w-25">Категория</th>
<th scope="col" className="w-25">Год издания</th>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
</thead>
<tbody></tbody>
</Table>
</>
);
};
export default BooksTable;

View File

@ -0,0 +1,25 @@
import { Button, Table } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const CategoriesTable = () => {
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Таблица категорий.
</h1>
<Button as={Link} to="/category-edit" className='lib-btn'>Добавить категорию</Button>
<Table className="mt-2 lib-table" striped>
<thead>
<th scope="col"></th>
<th scope="col" className="w-25">Категория</th>
<th scope="col" className="w-25">Описание</th>
<th scope="col"></th>
<th scope="col"></th>
</thead>
<tbody></tbody>
</Table>
</>
);
};
export default CategoriesTable;

View File

@ -0,0 +1,39 @@
import { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
const CategoryEdit = () => {
const [validated, setValidated] = useState(false);
const navigate = useNavigate();
const handleSubmit = (event) => {
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
setValidated(true);
};
return (
<>
<h1 className='mt-2 text-center'>
Добавление/редактирование категории.
</h1>
<Form id="books-form" noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-2" controlId="name">
<Form.Label>Название</Form.Label>
<Form.Control type="text" name="name" required/>
</Form.Group>
<Form.Group className="mb-2" controlId="info">
<Form.Label>Описание</Form.Label>
<Form.Control type="text" name="info" required/>
</Form.Group>
<div className="d-grid gap-2 mt-4 d-md-flex justify-content-md-center">
<Button className="lib-btn" onClick={() => navigate(-1)}>Назад</Button>
<Button className="lib-btn" type="submit" variant="primary">Сохранить</Button>
</div>
</Form>
</>
);
};
export default CategoryEdit;

View File

@ -3,14 +3,13 @@ import { useNavigate } from 'react-router-dom';
const ErrorPage = () => { const ErrorPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<Container fluid className="p-2 row justify-content-center"> <Container fluid className="p-2 row justify-content-center">
<Container className='col-md-6'> <Container className='col-md-6'>
<Alert variant="danger"> <Alert variant="danger">
Страница не найдена Страница не найдена
</Alert> </Alert>
<Button className="w-25 mt-2 library-button" onClick={() => navigate(-1)}>Назад</Button> <Button className="w-25 mt-2 lib-btn" onClick={() => navigate(-1)}>Назад</Button>
</Container> </Container>
</Container> </Container>
); );

View File

@ -0,0 +1,45 @@
import { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const LoginPage = () => {
const [validated, setValidated] = useState(false);
const handleSubmit = (event) => {
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
setValidated(true);
};
return (
<>
<h1 className='mt-2 text-center'>
Вход в аккаунт.
</h1>
<div className="row justify-content-center">
<Form className="col-md-6 m-0" noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-2" controlId="email">
<Form.Label>E-mail</Form.Label>
<Form.Control type="email" name="email" placeholder="name@example.ru" required />
<Form.Control.Feedback>Почта заполнена</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Почта не заполнена</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-2" controlId="password">
<Form.Label>Пароль</Form.Label>
<Form.Control type="password" name="password" required />
<Form.Control.Feedback>Пароль заполнен</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Пароль не заполнен</Form.Control.Feedback>
</Form.Group>
<div className="d-grid gap-2 mt-4 d-md-flex justify-content-md-center">
<Button className="lib-btn" type="submit">Отправить</Button>
<Button as={Link} to="/reg-page" className="lib-btn">У меня нет аккаунта</Button>
</div>
</Form>
</div>
</>
);
};
export default LoginPage;

View File

@ -5,7 +5,7 @@ const MainPage = () => {
return ( return (
<> <>
<h1 className='mt-2 text-md-start text-center'> <h1 className='mt-2 text-md-start text-center'>
Пример web-страницы. Добро пожаловать!
</h1> </h1>
<p className="mt-2 text-md-start text-center"> <p className="mt-2 text-md-start text-center">
Здесь вы обязательно найдете нужные вам книги. Здесь вы обязательно найдете нужные вам книги.
@ -15,8 +15,8 @@ const MainPage = () => {
Там же вы можете посмотреть вашу Историю чтения. Там же вы можете посмотреть вашу Историю чтения.
</p> </p>
<div className="d-grid gap-2 mt-2 d-md-flex justify-content-md-start"> <div className="d-grid gap-2 mt-2 d-md-flex justify-content-md-start">
<Button as={Link} to="/user-page.html" className='library-button'>Личный кабинет</Button> <Button as={Link} to="/user-page" className='lib-btn'>Личный кабинет</Button>
<Button as={Link} to="/search.html" className='library-button'>Поиск</Button> <Button as={Link} to="/search" className='lib-btn'>Поиск</Button>
</div> </div>
</> </>
); );

View File

@ -0,0 +1,55 @@
import { useState } from 'react';
import { Button, Form } from 'react-bootstrap';
const RegPage = () => {
const [validated, setValidated] = useState(false);
const handleSubmit = (event) => {
const form = event.currentTarget;
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
setValidated(true);
};
return (
<>
<h1 className='mt-2 text-center'>
Создание аккаунта.
</h1>
<div className="row justify-content-center">
<Form className="col-md-6 m-0" noValidate validated={validated} onSubmit={handleSubmit}>
<Form.Group className="mb-2" controlId="name">
<Form.Label>Никнейм</Form.Label>
<Form.Control type="text" name="name" required />
<Form.Control.Feedback>Никнейм заполнен</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Никнейм не заполнен</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-2" controlId="email">
<Form.Label>E-mail</Form.Label>
<Form.Control type="email" name="email" placeholder="name@example.ru" required />
<Form.Control.Feedback>Почта заполнена</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Почта не заполнена</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-2" controlId="password">
<Form.Label>Пароль</Form.Label>
<Form.Control type="password" name="password" required />
<Form.Control.Feedback>Пароль заполнен</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Пароль не заполнен</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-2" controlId="password">
<Form.Label>Повторите пароль</Form.Label>
<Form.Control type="password" name="password" required />
<Form.Control.Feedback>Пароль повторен</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">Пароль не повторен</Form.Control.Feedback>
</Form.Group>
<div className="d-grid gap-2 mt-4 d-md-flex justify-content-md-center">
<Button className="lib-btn" type="submit">Отправить</Button>
</div>
</Form>
</div>
</>
);
};
export default RegPage;

View File

@ -0,0 +1,28 @@
import { Button, Table } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
const UserFavorities = () => {
const navigate = useNavigate();
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Избранное.
</h1>
<Button className="w-25 mt-2 lib-btn" onClick={() => navigate(-1)}>Назад</Button>
<Table className="mt-2 lib-table" striped>
<thead>
<th scope="col"></th>
<th scope="col" className="w-25">Автор</th>
<th scope="col" className="w-25">Название</th>
<th scope="col" className="w-25">Категория</th>
<th scope="col" className="w-25">Год издания</th>
<th scope="col"></th>
<th scope="col"></th>
</thead>
<tbody></tbody>
</Table>
</>
);
};
export default UserFavorities;

View File

@ -0,0 +1,29 @@
import { Button, Table } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
const UserHistory = () => {
const navigate = useNavigate();
return (
<>
<h1 className='mt-2 text-md-start text-center'>
История.
</h1>
<Button className="w-25 mt-2 lib-btn" onClick={() => navigate(-1)}>Назад</Button>
<Table className="mt-2 lib-table" striped>
<thead>
<th scope="col"></th>
<th scope="col" className="w-25">Автор</th>
<th scope="col" className="w-25">Название</th>
<th scope="col" className="w-25">Категория</th>
<th scope="col" className="w-25">Год издания</th>
<th scope="col" className="w-25">Время чтения</th>
<th scope="col"></th>
<th scope="col"></th>
</thead>
<tbody></tbody>
</Table>
</>
);
};
export default UserHistory;

View File

@ -0,0 +1,22 @@
import { Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
const UserPage = () => {
return (
<>
<h1 className='mt-2 text-md-start text-center'>
Ваш личный кабинет.
</h1>
<p className="mt-2 text-md-start text-center">
Здесь вы можете посмотреть вашу Историю чтения и Избранные книги.
</p>
<div className="d-grid gap-2 mt-2 d-md-flex justify-content-md-start">
<Button as={Link} to="/user-favorities" className='lib-btn'>Избранное</Button>
<Button as={Link} to="/user-history" className='lib-btn'>История</Button>
<Button as={Link} to="/admin-page" className='lib-btn'>Страница администратора</Button>
</div>
</>
);
};
export default UserPage;