Merge branch 'lab5' into lab6

This commit is contained in:
2025-05-24 20:59:37 +04:00
29 changed files with 5715 additions and 1255 deletions

View File

@@ -15,6 +15,8 @@ function App() {
const [authors] = useState(data.authors);
const [statuses] = useState(data.statuses);
const [editingBook, setEditingBook] = useState(null);
const [statusFilter, setStatusFilter] = useState(""); // пусто — все книги
// Загрузка книг с сервера
useEffect(() => {
@@ -59,6 +61,15 @@ function App() {
});
};
// Фильтрация книг по статусу
const filteredBooks = statusFilter
? books.filter(
book =>
statuses.find(s => String(s.id) === String(book.statusId))?.name === statusFilter
)
: books;
return (
<>
<Navbar />
@@ -92,4 +103,4 @@ function App() {
);
}
export default App;
export default App;

View File

@@ -1,69 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Личный кабинет</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<!-- маска на телефон + звездочки на пароль + длина пароля -->
<body class="bg-dark text-light">
<header class=" py-3 bg-custom-dark">
<div class="container d-flex align-items-center">
<a href="index.html" class="me-3">
<img src="../img/manga.png" alt="ЛОГО" height="50" />
</a>
<h1 class="h5 mb-0 text-light">Личный кабинет</h1>
</div>
</header>
<main class="container my-5">
<div class="row justify-content-center">
<div class="col-md-6 bg-secondary p-4 rounded bg-custom-dark">
<form id="loginForm">
<h2 class="text-center mb-4">
<i class="bi bi-person-circle me-2"></i>Вход в систему
</h2>
<div class="mb-3">
<label for="number" class="form-label">
<i class="bi bi-telephone-fill me-2"></i>Номер телефона
</label>
<input type="tel" class="form-control" id="number" name="number_acc" placeholder="+7 (___) ___-__-__" required>
</div>
<div class="mb-4">
<label for="password" class="form-label">
<i class="bi bi-lock-fill me-2"></i>Пароль
</label>
<input type="password" class="form-control" id="password" name="password_acc" placeholder="Пароль" required minlength="4">
</div>
<div class="d-grid">
<button type="submit" class="btn btn-warning">
<i class="bi bi-box-arrow-in-right me-2"></i>Войти
</button>
</div>
</form>
</div>
</div>
</main>
<footer class="text-center py-4 text-light mt-5 bg-custom-dark">
<p><i class="bi bi-journal-text me-2"></i>Все права защищены, 2025</p>
</footer>
<!-- маска + карточка пользователя -->
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@@ -1,74 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Добавить книгу</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<body class="bg-dark text-light"></body>
<header class=" py-3 bg-custom-dark">
<div class="container d-flex align-items-center">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<h1 class="h5 ms-4 mb-0 text-light">Добавить книгу</h1>
</div>
</header>
<main class="container bg-custom-dark mt-5">
<form id="bookForm">
<input type="hidden" id="bookId" />
<div class="mb-3">
<label for="title" class="form-label">Название книги</label>
<input type="text" id="title" class="form-control" required />
</div>
<div class="mb-3">
<label for="description" class="form-label">Описание книги</label>
<textarea id="description" class="description"></textarea>
</div>
<div class="mb-3">
<label for="authorId" class="form-label">Автор</label>
<select id="authorId" class="form-select" required></select>
</div>
<div class="mb-3">
<label for="statusId" class="form-label">Статус</label>
<select id="statusId" class="form-select" required></select>
</div>
<div class="mb-3">
<label for="cover" class="form-label">Обложка (файл)</label>
<img id="coverPreview" src="" alt="Превью обложки" class="mt-2" style="max-height: 150px; display:none;" />
<input type="file" id="cover" name="cover" accept="image/*" class="form-control"/>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
<button type="button" id="cancelBtn" class="btn btn-secondary ms-2">Отмена</button>
</form>
</main>
<footer class="text-center py-4 text-light mt-5 bg-custom-dark">
<p><i class="bi bi-journal-text me-2"></i>Все права защищены, 2025</p>
</footer>
<script type="module" src="../src/main.js"></script>
<script type="module" src="/mvc/controller.js"></script>
</body>
</html>

View File

@@ -1,62 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Авторство</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="css/style.css" rel="stylesheet">
</head>
<body class="bg-dark text-light">
<!-- Навигация -->
<nav class="navbar navbar-expand-lg navbar-dark bg-custom-dark px-3">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Переключить навигацию">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ms-3" id="navbarNavDropdown">
<ul class="navbar-nav me-auto">
</ul>
<a href="account.html" class="btn btn-outline-warning">Вход</a>
</div>
</nav>
<!-- Информация об авторе -->
<main class="container mt-5">
<div class="row">
<div class="col-md-4 text-center">
<img class="img-fluid rounded" src="img/ХаяоМиядзаки.png" alt="Хаяо Миядзаки">
</div>
<div class="col-md-8">
<h3>Автор: Хаяо Миядзаки</h3>
<p>Посвящено автору и т.п. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur quod harum
voluptate architecto, sit eaque, voluptatibus excepturi deleniti consequatur porro vero dolorem dolorum
vitae laborum libero et veritatis sapiente a?</p>
</div>
</div>
</main>
<!-- Футер -->
<footer class="bg-custom-dark text-light text-center py-4 mt-5">
<p>Спасибо, что посетили наш сайт, если возникли вопросы, обращайтесь к нам на почту <a href="mailto:manga@manga.scom" class="text-warning">manga@manga.scom</a></p>
<p>Если вас интересуют наши соц.сети, то вот они:</p>
<div class="d-flex justify-content-center">
<a href="https://vk.com/ded_moroz1509" class="me-3">
<img src="img/VK0.png" alt="VK" height="30">
</a>
<!-- Добавить другие иконки соцсетей здесь -->
</div>
</footer>
<!-- JS Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -1,97 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Личный кабинет</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body class="bg-dark text-light">
<header class="bg-secondary py-3">
<div class="container d-flex align-items-center">
<a href="index.html" class="me-3">
<img src="../img/manga.png" alt="ЛОГО" height="50" />
</a>
<h1 class="h5 mb-0 text-light">Личный кабинет</h1>
</div>
</header>
<main class="container my-5">
<div class="row justify-content-center">
<div class="col-md-6 bg-secondary p-4 rounded">
<form id="loginForm">
<h2 class="text-center mb-4">
<i class="bi bi-person-circle me-2"></i>Вход в систему
</h2>
<div class="mb-3">
<label for="number" class="form-label">
<i class="bi bi-telephone-fill me-2"></i>Номер телефона
</label>
<input type="tel" class="form-control" id="number" name="number_acc" placeholder="Телефон" required>
</div>
<div class="mb-4">
<label for="password" class="form-label">
<i class="bi bi-lock-fill me-2"></i>Пароль
</label>
<input type="password" class="form-control" id="password" name="password_acc" placeholder="Пароль" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-warning">
<i class="bi bi-box-arrow-in-right me-2"></i>Войти
</button>
</div>
</form>
</div>
</div>
<div class="row justify-content-center mt-5" id="userCards">
<!-- Здесь будут карточки -->
</div>
</main>
<footer class="bg-secondary text-center py-4 text-light mt-5">
<p><i class="bi bi-journal-text me-2"></i>Все права защищены, 2025</p>
</footer>
<script>
document.getElementById("loginForm")?.addEventListener("submit", (e) => {
e.preventDefault();
const number = document.getElementById("number").value;
const password = document.getElementById("password").value;
// типо AJAX
setTimeout(() => {
// создаём карточку пользователя
const card = document.createElement("div");
card.className = "col-md-4 mb-4"; // Класс для каждой карточки
card.innerHTML = `
<div class="card text-dark bg-light">
<div class="card-header">
<i class="bi bi-person-circle me-2"></i>Профиль пользователя
</div>
<div class="card-body">
<h5 class="card-title">Добро пожаловать!</h5>
<p class="card-text"><i class="bi bi-telephone-fill me-2"></i>${number}</p>
<p class="card-text"><i class="bi bi-shield-lock-fill me-2"></i>Пароль: <code>${password}</code></p>
</div>
</div>
`;
// добавляем карточку на страницу
document.getElementById("userCards").appendChild(card);
}, 0);
});
</script>
</body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -1 +0,0 @@
*{margin:0;padding:0}body{background-color:#0f0630;font-family:Arial,Helvetica,sans-serif;color:azure}a{text-decoration:none;color:bisque}div{background-color:#312b46;width:1075px;margin:0 auto 20px}.author{display:flex}.input{width:700px;margin-top:70px}.icons{display:flex;flex-wrap:wrap}.icon{width:150px;margin:0 20px 10px}.card{display:flex}h3{margin-bottom:15px}.read{width:500px;display:block}footer{background-color:#312b46;margin-top:50px;padding:10px;height:150px;color:#a39a57}.menu{display:flex;align-items:center;margin-bottom:50px;background-color:#312b46;padding:10px}.logo img{height:50px}.nav{list-style:none;display:flex;margin-left:20px}.nav li{position:relative;padding:10px}.nav a,.dropdown span{color:bisque;cursor:pointer}.features-menu{display:none;position:absolute;top:100%;left:0;background:#413a58;list-style:none;padding:5px 0;min-width:150px}.features-menu li{padding:5px 10px}.features-menu li a{display:block;color:bisque;padding:5px}.features-menu li a:hover{background:#574f73}.dropdown:hover .features-menu{display:block}.logoVK{margin-top:10px;height:40px}.description-new{padding:10px 20px}@media only screen and (min-width: 100px) and (max-width: 700px){div,.input,.read{width:70%}.menu{padding:0}.nav{margin:0}.icon{padding:0 5px;margin:0 auto 10px}.card,.author{display:block}.img-author,.read img,.card img,.cont-new img{width:100%}}@media only screen and (min-width: 701px) and (max-width: 1400px){div,.input,.read{width:80%}.menu{padding:0}.icon{padding:0 5px}.author{display:block}.img-author,.read img{width:100%}.card-news .card{margin:0 0 15px}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

42
html/dist/author.html vendored
View File

@@ -1,42 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Авторство</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body>
<div class="menu">
<a href="index.html" class="logo">
<img src="/assets/manga-BfLZfEuP.png" alt="ЛОГО">
</a>
<ul class="nav">
<li class="dropdown">
<span>Каталог ▾</span>
<ul class="features-menu">
<li><a href="#">Жанр 1</a></li>
<li><a href="#">Жанр 2</a></li>
<li><a href="#">Жанр 3</a></li>
<li><a href="#">Жанр 4</a></li>
</ul>
</li>
<li class="login"><a href="account.html">вход</a></li>
</ul>
</div>
<div class="author">
<img class="img-author" src="/assets/%D0%A5%D0%B0%D1%8F%D0%BE%D0%9C%D0%B8%D1%8F%D0%B4%D0%B7%D0%B0%D0%BA%D0%B8-DO711Y0K.png" alt="">
<div class="description">
<h3>Автор: Хаяо Миядзаки</h3>
<p>посвящено автору и тп. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequuntur quod harum voluptate architecto, sit eaque, voluptatibus excepturi deleniti consequatur porro vero dolorem dolorum vitae laborum libero et veritatis sapiente a?</p>
</div>
</div>
</body>

129
html/dist/index.html vendored
View File

@@ -1,129 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Манга онлайн</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body>
<div class="menu">
<a href="index.html" class="logo">
<img src="/assets/manga-BfLZfEuP.png" alt="ЛОГО">
</a>
<ul class="nav">
<li class="dropdown">
<span>Каталог ▾</span>
<ul class="features-menu">
<li><a href="#">Жанр 1</a></li>
<li><a href="#">Жанр 2</a></li>
<li><a href="#">Жанр 3</a></li>
<li><a href="#">Жанр 4</a></li>
</ul>
</li>
<li class="login"><a href="account.html">вход</a></li>
</ul>
</div>
<div class="main">
<h3>Наши произведения</h3>
<section class="icons"><!--секция с обложками-->
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
<div class="icon">
<a href="manga.html">
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
</a>
</div>
</section>
</div>
<div class="news">
<h3>Наши новости:</h3>
<section class="card-news"><!--секция с новостями-->
<div class="card">
<a href="news.html">
<img src="/assets/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D1%8C-CEduGkm8.jpg" alt="">
</a>
<div class="description-news">
<h4>Новость 1</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero laborum possimus itaque quibusdam beatae ipsam odit sed? Vel blanditiis repellendus,
ea nam, incidunt odio sit amet sequi nihil, laudantium aspernatur!</p>
</div>
</div>
<div class="card">
<a href="news.html">
<img src="/assets/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D1%8C-CEduGkm8.jpg" alt="">
</a>
<div class="description-news">
<h4>Новость 2</h4>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero laborum possimus itaque quibusdam beatae ipsam odit sed? Vel blanditiis repellendus,
ea nam, incidunt odio sit amet sequi nihil, laudantium aspernatur!</p>
</div>
</div>
</section>
</div>
<footer>
<p>Спасибо, что посетили наш сайт, если возникли вопросы обращайтесь к нам на почту manga@manga.scom</p>
<p>Если вас интерисуют наши соц.сети, то вот они: </p>
<a href="https://vk.com/ded_moroz1509"><img class="logoVK" src="/assets/VK0-CBz5vLzK.png" alt="VK"></a>
</footer>
</body>

42
html/dist/manga.html vendored
View File

@@ -1,42 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Манга</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body>
<div class="menu">
<a href="index.html" class="logo">
<img src="/assets/manga-BfLZfEuP.png" alt="ЛОГО">
</a>
<ul class="nav">
<li class="dropdown">
<span>Каталог ▾</span>
<ul class="features-menu">
<li><a href="#">Жанр 1</a></li>
<li><a href="#">Жанр 2</a></li>
<li><a href="#">Жанр 3</a></li>
<li><a href="#">Жанр 4</a></li>
</ul>
</li>
<li class="login"><a href="account.html">вход</a></li>
</ul>
</div>
<div>
<figure>
<img src="/assets/%D0%B7%D0%B0%D0%B3%D0%BB%D1%83%D1%88%D0%BA%D0%B0-boEbM-7G.jpg" alt="">
<figcaption>Заглушка</figcaption>
</figure>
<p>здесь будет сама инфа о манге</p>
<a href="author.html">про автора</a>
<a href="reading.html">Читать</a>
</div>
</body>

37
html/dist/news.html vendored
View File

@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Новость</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body>
<div class="menu">
<a href="index.html" class="logo">
<img src="/assets/manga-BfLZfEuP.png" alt="ЛОГО">
</a>
<ul class="nav">
<li class="dropdown">
<span>Каталог ▾</span>
<ul class="features-menu">
<li><a href="#">Жанр 1</a></li>
<li><a href="#">Жанр 2</a></li>
<li><a href="#">Жанр 3</a></li>
<li><a href="#">Жанр 4</a></li>
</ul>
</li>
<li class="login"><a href="account.html">вход</a></li>
</ul>
</div>
<div class="cont-new">
<img src="/assets/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D1%8C-CEduGkm8.jpg" alt="">
<p class="description-new">Новость Lorem, ipsum dolor sit amet consectetur adipisicing elit. Beatae exercitationem eligendi error. Architecto voluptatum eaque, nostrum ea a consequuntur, deleniti dolor provident sequi dicta culpa magnam delectus amet distinctio autem?</p>
</div>
</body>

View File

@@ -1,38 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Читать мангу...</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" crossorigin href="/assets/style-Bu611mU5.css">
</head>
<body>
<div class="menu">
<a href="index.html" class="logo">
<img src="/assets/manga-BfLZfEuP.png" alt="ЛОГО">
</a>
<ul class="nav">
<li class="dropdown">
<span>Каталог ▾</span>
<ul class="features-menu">
<li><a href="#">Жанр 1</a></li>
<li><a href="#">Жанр 2</a></li>
<li><a href="#">Жанр 3</a></li>
<li><a href="#">Жанр 4</a></li>
</ul>
</li>
<li class="login"><a href="account.html">вход</a></li>
</ul>
</div>
<div class="read">
<img src="/assets/SL1-Qf4Hoc4q.png" alt="">
<img src="/assets/SL2-DJQ14JgM.png" alt="">
</div>
</body>

View File

@@ -1,116 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Манга онлайн</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="css/style.css" rel="stylesheet">
</head>
<body class="bg-dark">
<!-- Навигация -->
<nav class="navbar navbar-expand-lg navbar-dark bg-custom-dark px-3">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Переключить навигацию">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ms-3" id="navbarNavDropdown">
<ul class="navbar-nav me-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="catalogDropdown" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Каталог
</a>
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="catalogDropdown">
<li><a class="dropdown-item" href="#">Жанр 1</a></li>
<li><a class="dropdown-item" href="#">Жанр 2</a></li>
<li><a class="dropdown-item" href="#">Жанр 3</a></li>
<li><a class="dropdown-item" href="#">Жанр 4</a></li>
</ul>
</li>
</ul>
<a href="account.html" class="btn btn-outline-warning">Вход</a>
</div>
</nav>
<!-- Основное содержимое -->
<div class="container mt-5 bg-custom-dark p-3 rounded">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>Наши произведения</h3>
<a href="add_book.html" class="btn btn-success">
<i class="bi bi-plus-circle me-2"></i>Добавить книгу
</a>
</div>
<div id="booksContainer" class="row row-cols-1 row-cols-md-3 g-3">
<!-- Здесь динамически будут отображаться книги -->
</div>
</div>
<!-- Новости -->
<div class="news mt-5">
<h3 class="text-center">Наши новости:</h3>
<section class="row row-cols-1 row-cols-sm-3 row-cols-md-3 g-4">
<div class="col d-flex justify-content-center">
<div class="card">
<a href="news.html">
<img src="img/новость.jpg" class="card-img-top" alt="Новость 1">
</a>
<div class="card-body">
<h4 class="card-title">Новость 1</h4>
<p class="card-text">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero laborum possimus itaque quibusdam beatae ipsam odit sed? Vel blanditiis repellendus, ea nam, incidunt odio sit amet sequi nihil, laudantium aspernatur!</p>
</div>
</div>
</div>
<div class="col d-flex justify-content-center">
<div class="card">
<a href="news.html">
<img src="img/новость.jpg" class="card-img-top" alt="Новость 2">
</a>
<div class="card-body">
<h4 class="card-title">Новость 2</h4>
<p class="card-text">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero laborum possimus itaque quibusdam beatae ipsam odit sed? Vel blanditiis repellendus, ea nam, incidunt odio sit amet sequi nihil, laudantium aspernatur!</p>
</div>
</div>
</div>
<div class="col d-flex justify-content-center">
<div class="card">
<a href="news.html">
<img src="img/новость.jpg" class="card-img-top" alt="Новость 3">
</a>
<div class="card-body">
<h4 class="card-title">Новость 3</h4>
<p class="card-text">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero laborum possimus itaque quibusdam beatae ipsam odit sed? Vel blanditiis repellendus, ea nam, incidunt odio sit amet sequi nihil, laudantium aspernatur!</p>
</div>
</div>
</div>
</section>
</div>
</div>
<!-- Футер -->
<footer class="bg-custom-dark text-light text-center py-4 mt-5">
<p>Спасибо, что посетили наш сайт, если возникли вопросы, обращайтесь к нам на почту <a href="mailto:manga@manga.scom" class="text-warning">manga@manga.scom</a></p>
<p>Если вас интересуют наши соц.сети, то вот они:</p>
<div class="d-flex justify-content-center">
<a href="https://vk.com/ded_moroz1509" class="me-3">
<img src="img/VK0.png" alt="VK" height="30">
</a>
<!-- Добавьте другие иконки соцсетей здесь -->
</div>
</footer>
<!-- JS Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js"></script>
<script type="module" src="../src/main.js"></script>
</body>
</html>

View File

@@ -1,76 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Манга</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet" />
</head>
<body class="bg-dark text-light d-flex flex-column min-vh-100">
<!-- Навигация -->
<nav class="navbar navbar-expand-lg navbar-dark bg-custom-dark px-3">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Переключить навигацию">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ms-3" id="navbarNavDropdown">
<ul class="navbar-nav me-auto">
</ul>
<a href="account.html" class="btn btn-outline-warning">Вход</a>
</div>
</nav>
<!-- Контент -->
<main class="container my-5 flex-grow-1">
<div class="row justify-content-center">
<div class="col-md-8 text-center">
<figure class="figure">
<img src="img/заглушка.jpg" class="figure-img img-fluid rounded" alt="Заглушка">
<figcaption class="figure-caption text-light">Заглушка</figcaption>
</figure>
<p class="mt-4">Здесь будет сама инфа о манге</p>
<div class="d-flex justify-content-center gap-3 mt-3">
<a href="author.html" class="btn btn-primary"><i class="bi bi-person-lines-fill me-2"></i>Про автора</a>
<a href="reading.html" class="btn btn-success"><i class="bi bi-book me-2"></i>Читать</a>
</div>
</div>
</div>
</main>
<footer class="bg-custom-dark text-light text-center py-4">
<div class="container">
<p>Спасибо, что посетили наш сайт, если возникли вопросы, обращайтесь к нам на почту
<a href="mailto:manga@manga.scom" class="text-warning">manga@manga.scom</a>
</p>
<p>Если вас интересуют наши соц.сети, то вот они:</p>
<div class="d-flex justify-content-center">
<a href="https://vk.com/ded_moroz1509" class="me-3">
<img src="img/VK0.png" alt="VK" height="30">
</a>
</div>
</div>
</footer>
<!-- JS Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<!-- Твой модуль JS -->
<script type="modal" src="/html/src/main.js"></script>
</body>
</html>

View File

@@ -1,16 +0,0 @@
const BASE_URL = "http://localhost:5174"; // Порт json-server
async function request(path, method = "GET", body = null) {
const options = { method, headers: { "Content-Type": "application/json" } };
if (body) options.body = JSON.stringify(body);
const response = await fetch(`${BASE_URL}/${path}`, options);
if (!response.ok) throw new Error(`Ошибка запроса: ${response.status}`);
return response.json();
}
export const getAllItems = (entity) => request(entity);
export const getItem = (entity, id) => request(`${entity}/${id}`);
export const createItem = (entity, data) => request(entity, "POST", data);
export const updateItem = (entity, id, data) => request(`${entity}/${id}`, "PATCH", data);
export const deleteItem = (entity, id) => request(`${entity}/${id}`, "DELETE");

View File

@@ -1,128 +0,0 @@
import model from "./model";
import view from "./view";
const controller = {
// Инициализация главной страницы (index.html)
async initIndexPage() {
await this.loadAuthorsAndStatuses();
await this.loadAndRenderBooks();
// Делегирование событий на контейнер с книгами
const booksContainer = document.getElementById("booksContainer");
if (booksContainer) {
booksContainer.addEventListener("click", async (e) => {
const { id } = e.target.dataset;
if (e.target.classList.contains("delete-btn")) {
if (confirm("Удалить книгу?")) {
try {
await model.deleteBook(id);
view.showAlert("Книга удалена");
await this.loadAndRenderBooks();
} catch (error) {
console.error(error);
view.showAlert("Ошибка при удалении книги", true);
}
}
} else if (e.target.classList.contains("edit-btn")) {
// При редактировании перенаправляем на add_book.html?id=...
window.location.href = `add_book.html?id=${id}`;
}
});
}
},
// Инициализация страницы добавления/редактирования (add_book.html)
async initAddBookPage() {
await this.loadAuthorsAndStatuses();
view.bindCoverInput();
// Если есть id в URL — значит редактирование
const params = new URLSearchParams(window.location.search);
const editingId = params.get("id");
if (editingId) {
try {
const book = await model.getBook(editingId);
view.fillBookForm(book);
document.getElementById("bookId").value = editingId;
} catch (error) {
console.error(error);
view.showAlert("Ошибка при загрузке книги", true);
}
}
// Сохранение формы
const bookForm = document.getElementById("bookForm");
if (bookForm) {
bookForm.addEventListener("submit", async (e) => {
e.preventDefault();
try {
const bookData = await view.getBookFormData();
const id = document.getElementById("bookId").value;
if (id) {
await model.updateBook(id, bookData);
view.showAlert("Книга обновлена");
} else {
await model.addBook(bookData);
view.showAlert("Книга добавлена");
}
view.resetBookForm();
document.getElementById("bookId").value = "";
window.location.href = "index.html";
} catch (error) {
console.error(error);
view.showAlert("Ошибка при сохранении книги", true);
}
});
}
// Кнопка "Отмена"
const cancelBtn = document.getElementById("cancelBtn");
if (cancelBtn) {
cancelBtn.addEventListener("click", () => {
window.location.href = "index.html";
});
}
},
// Загрузка авторов и статусов для селектов
async loadAuthorsAndStatuses() {
try {
const authors = await model.getAuthors();
const statuses = await model.getStatuses();
const authorSelect = document.getElementById("authorId");
const statusSelect = document.getElementById("statusId");
if (authorSelect) view.renderAuthorOptions(authors, authorSelect);
if (statusSelect) view.renderStatusOptions(statuses, statusSelect);
} catch (error) {
console.error(error);
view.showAlert("Ошибка при загрузке авторов или статусов", true);
}
},
// Загрузка и рендер книг на главной
async loadAndRenderBooks() {
try {
const books = await model.getBooks();
const authors = await model.getAuthors();
const statuses = await model.getStatuses();
const booksWithDetails = books.map((book) => {
const author = authors.find((a) => String(a.id) === String(book.authorId));
const status = statuses.find((s) => String(s.id) === String(book.statusId));
return {
...book,
authorName: author ? author.name : "Неизвестен",
statusName: status ? status.name : "Неизвестен",
};
});
const booksContainer = document.getElementById("booksContainer");
if (booksContainer) view.renderBooks(booksWithDetails, booksContainer);
} catch (error) {
console.error(error);
view.showAlert("Ошибка при загрузке книг", true);
}
},
};
export default controller;

View File

@@ -1,39 +0,0 @@
import { getAllItems, getItem, createItem, updateItem, deleteItem } from "./api/client";
export default {
// Книги
getBooks() {
return getAllItems("books");
},
getBook(id) {
return getItem("books", id);
},
addBook(book) {
return createItem("books", book);
},
updateBook(id, data) {
return updateItem("books", id, data);
},
deleteBook(id) {
return deleteItem("books", id);
},
// Авторы
getAuthors() {
return getAllItems("authors");
},
// Статусы
getStatuses() {
return getAllItems("statuses");
},
addStatus(status) {
return createItem("statuses", status);
},
updateStatus(id, data) {
return updateItem("statuses", id, data);
},
deleteStatus(id) {
return deleteItem("statuses", id);
},
};

View File

@@ -1,148 +0,0 @@
const view = {
renderAuthorOptions(authors, selectElement) {
selectElement.innerHTML = '<option value="">Выберите автора</option>';
authors.forEach((author) => {
const option = document.createElement("option");
option.value = author.id;
option.textContent = author.name;
selectElement.appendChild(option);
});
},
renderStatusOptions(statuses, selectElement) {
selectElement.innerHTML = '<option value="">Выберите статус</option>';
statuses.forEach((status) => {
const option = document.createElement("option");
option.value = status.id;
option.textContent = status.name;
selectElement.appendChild(option);
});
},
renderBooks(books, container) {
container.innerHTML = "";
books.forEach((book) => {
// определяем класс для статуса
let statusClass = "text-muted fw-bold";
switch ((book.statusName || "").toLowerCase()) {
case "вышла":
statusClass = "text-success fw-bold";
break;
case "не вышла":
statusClass = "text-danger fw-bold";
break;
case "не переведена":
statusClass = "text-warning fw-bold";
break;
case "прочитана":
statusClass = "text-primary fw-bold";
break;
default:
statusClass = "text-muted fw-bold";
break;
}
const div = document.createElement("div");
div.className = "card mb-3";
div.innerHTML = `
<a href="manga.html">
<img src="${book.cover || "img/заглушка.jpg"}" class="card-img-top shadow mt-2" alt="Обложка книги" style="max-height:300px; object-fit:contain; ">
</a>
<div class="card-body">
<h5 class="card-title">${book.title}</h5>
<p class="card-text">${book.description}</p>
<p class="card-text"><small class="text-muted">Автор: ${book.authorName || "Неизвестен"}</small></p>
<p class="card-text"><small class="${statusClass}">Статус: ${book.statusName || "Неизвестен"}</small></p>
<button data-id="${book.id}" class="btn btn-danger btn-sm delete-btn">Удалить</button>
<a href="add_book.html?id=${book.id}" class="btn btn-warning btn-sm edit-btn">Редактировать</a>
</div>`;
container.appendChild(div);
});
},
bindCoverInput() {
const coverInput = document.getElementById("cover");
const coverPreview = document.getElementById("coverPreview");
coverInput.addEventListener("change", () => {
const file = coverInput.files[0];
if (!file) {
coverPreview.style.display = "none";
coverPreview.src = "";
return;
}
const reader = new FileReader();
reader.onload = (e) => {
coverPreview.src = e.target.result;
coverPreview.style.display = "block";
};
reader.readAsDataURL(file);
});
},
async getBookFormData() {
const coverInput = document.getElementById("cover");
let coverData = "";
if (coverInput.files.length > 0) {
coverData = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error("Ошибка чтения файла обложки"));
reader.readAsDataURL(coverInput.files[0]);
});
} else {
// Если форма редактирования, и файл не поменяли, можно брать существующий cover (или пустую строку)
coverData = document.getElementById("cover").dataset.currentCover || "";
}
return {
title: document.getElementById("title").value.trim(),
description: document.getElementById("description").value.trim(),
authorId: parseInt(document.getElementById("authorId").value, 10),
statusId: parseInt(document.getElementById("statusId").value, 10),
cover: coverData,
};
},
fillBookForm(book) {
document.getElementById("title").value = book.title || "";
document.getElementById("description").value = book.description || "";
document.getElementById("authorId").value = book.authorId || "";
document.getElementById("statusId").value = book.statusId || "";
// Запоминаем текущую обложку в дата-атрибут для использования при сохранении
const coverInput = document.getElementById("cover");
coverInput.value = ""; // Очистить input файл
coverInput.dataset.currentCover = book.cover || "";
// Показываем превью
const coverPreview = document.getElementById("coverPreview");
if (book.cover) {
coverPreview.src = book.cover;
coverPreview.style.display = "block";
} else {
coverPreview.style.display = "none";
}
},
resetBookForm() {
document.getElementById("bookForm").reset();
const coverPreview = document.getElementById("coverPreview");
coverPreview.style.display = "none";
coverPreview.src = "";
},
showAlert(message, isError = false) {
alert(isError ? `Ошибка: ${message}` : `Успех: ${message}`);
},
confirm(message) {
return new Promise((resolve) => {
const result = confirm(message);
resolve(result);
});
},
};
export default view;

View File

@@ -1,62 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Новость</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<body class="bg-dark">
<!-- Навигация -->
<nav class="navbar navbar-expand-lg navbar-dark bg-custom-dark px-3">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Переключить навигацию">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ms-3" id="navbarNavDropdown">
<ul class="navbar-nav me-auto">
</ul>
<a href="account.html" class="btn btn-outline-warning">Вход</a>
</div>
</nav>
<div class="container container-news mt-4">
<div class="row">
<div class="col-12">
<div class="card">
<img src="img/новость.jpg" class="card-img-top" alt="Новость">
<div class="card-body">
<h5 class="card-title">Новость</h5>
<p class="card-text">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Beatae exercitationem eligendi error.
Architecto voluptatum eaque, nostrum ea a consequuntur, deleniti dolor provident sequi dicta culpa
magnam delectus amet distinctio autem?
</p>
</div>
</div>
</div>
</div>
</div>
<footer class="bg-custom-dark text-center py-4 text-light mt-5 bg-custom-dark">
<p><i class="bi bi-journal-text me-2"></i>Все права защищены, 2025</p>
</footer>
<!-- Подключаем Bootstrap JS и Popper -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js"></script>
</body>
</html>

View File

@@ -1,61 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Читать мангу...</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="css/style.css" rel="stylesheet">
</head>
<body class="bg-dark text-light">
<!-- Навигация -->
<nav class="navbar navbar-expand-lg navbar-dark bg-custom-dark px-3">
<a class="navbar-brand" href="index.html">
<img src="img/manga.png" alt="ЛОГО" height="50">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Переключить навигацию">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ms-3" id="navbarNavDropdown">
<ul class="navbar-nav me-auto">
</ul>
<a href="account.html" class="btn btn-outline-warning">Вход</a>
</div>
</nav>
<!-- Чтение манги -->
<div class="container mt-5">
<div class="row">
<div class="col-12 text-center">
<h3>Читать мангу...</h3>
<div class="d-flex justify-content-center">
<img class="img-reading mx-2" src="img/SL1.png" alt="Манга страница 1">
<img class="img-reading mx-2" src="img/SL2.png" alt="Манга страница 2">
</div>
</div>
</div>
</div>
<!-- Футер -->
<footer class="bg-custom-dark text-light text-center py-4 mt-5">
<p>Спасибо, что посетили наш сайт, если возникли вопросы, обращайтесь к нам на почту <a href="mailto:manga@manga.scom" class="text-warning">manga@manga.scom</a></p>
<p>Если вас интересуют наши соц.сети, то вот они:</p>
<div class="d-flex justify-content-center">
<a href="https://vk.com/ded_moroz1509" class="me-3">
<img src="img/VK0.png" alt="VK" height="30">
</a>
<!-- Добавить другие иконки соцсетей здесь -->
</div>
</footer>
<!-- JS Bootstrap -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -1,17 +0,0 @@
import "bootstrap";
import "bootstrap-icons/font/bootstrap-icons.css";
import "bootstrap/dist/css/bootstrap.min.css";
import Inputmask from "inputmask";
import controller from "../mvc/controller";
document.addEventListener("DOMContentLoaded", () => {
const phoneInput = document.getElementById("number");
if (phoneInput) {
Inputmask("+7 (999) 999-99-99").mask(phoneInput);
}
if (document.getElementById("booksContainer")) {
controller.initIndexPage();
} else if (document.getElementById("bookForm")) {
controller.initAddBookPage();
}
});

5672
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
package.json Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "int-prog",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "npm-run-all --parallel backend vite",
"vite": "vite",
"build": "vite build",
"serve": "http-server -p 3000 ./html/",
"backend": "json-server ./html/database/data.json -p 5174",
"prod": "npm-run-all build serve --parallel backend serve",
"lint": "eslint . --ext js --report-unused-disable-directives --max-warnings 0"
},
"dependencies": {
"bootstrap": "5.3.3",
"bootstrap-icons": "^1.11.3",
"inputmask": "^5.0.9"
},
"devDependencies": {
"eslint": "8.56.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "10.0.2",
"eslint-plugin-html": "8.1.2",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-prettier": "5.2.3",
"http-server": "14.1.1",
"json-server": "^1.0.0-beta.3",
"npm-run-all": "4.1.5",
"vite": "6.2.0"
}
}