mirror of
https://github.com/EDeev/web-dev.git
synced 2026-06-17 05:21:01 +03:00
199 lines
9 KiB
HTML
199 lines
9 KiB
HTML
{% extends 'base.html' %}
|
|
{% from 'macros.html' import rating_badge %}
|
|
{% block title %}Главная — Электронная библиотека{% endblock %}
|
|
|
|
{% block content %}
|
|
<h2 class="mb-3">Каталог книг</h2>
|
|
|
|
{# ── Форма поиска (Вариант 3) ────────────────────────────────────────────── #}
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<strong>Поиск книг</strong>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="get" action="{{ url_for('index') }}">
|
|
<div class="row g-2">
|
|
<div class="col-md-4">
|
|
<label class="form-label">Название</label>
|
|
<input type="text" class="form-control" name="title" value="{{ q_title }}">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label">Автор</label>
|
|
<input type="text" class="form-control" name="author" value="{{ q_author }}">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="form-label">Страниц от</label>
|
|
<input type="number" class="form-control" name="pages_from" value="{{ q_pages_from }}" min="1">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="form-label">Страниц до</label>
|
|
<input type="number" class="form-control" name="pages_to" value="{{ q_pages_to }}" min="1">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Жанр</label>
|
|
<select class="form-select" name="genres" multiple size="4">
|
|
{% for genre in all_genres %}
|
|
<option value="{{ genre.id }}"
|
|
{% if genre.id in q_genres %}selected{% endif %}>
|
|
{{ genre.name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
<div class="form-text">Ctrl — несколько жанров</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Год</label>
|
|
<select class="form-select" name="years" multiple size="4">
|
|
{% for row in all_years %}
|
|
<option value="{{ row.year }}"
|
|
{% if row.year in q_years %}selected{% endif %}>
|
|
{{ row.year }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
<div class="form-text">Ctrl — несколько лет</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3 d-flex gap-2">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="bi bi-search"></i> Найти
|
|
</button>
|
|
<a href="{{ url_for('index') }}" class="btn btn-outline-secondary">Сбросить</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
{# ── Список книг ─────────────────────────────────────────────────────────── #}
|
|
{% if books %}
|
|
<div class="table-responsive">
|
|
<table class="table table-striped align-middle">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Обложка</th>
|
|
<th>Название</th>
|
|
<th>Жанр(ы)</th>
|
|
<th>Год</th>
|
|
<th>Средняя оценка</th>
|
|
<th>Рецензий</th>
|
|
<th>Действия</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for book in books %}
|
|
<tr>
|
|
<td>
|
|
{% if book.cover_filename %}
|
|
<img src="{{ url_for('uploaded_file', filename=book.cover_filename) }}"
|
|
class="cover-thumb rounded" alt="обложка">
|
|
{% else %}
|
|
<div class="cover-thumb bg-secondary rounded d-flex align-items-center justify-content-center text-white">
|
|
<i class="bi bi-book"></i>
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td><strong>{{ book.title }}</strong><br>
|
|
<small class="text-muted">{{ book.author }}</small>
|
|
</td>
|
|
<td><small>{{ book.genres or '—' }}</small></td>
|
|
<td>{{ book.year }}</td>
|
|
<td>
|
|
{% if book.avg_rating is not none %}
|
|
{{ rating_badge(book.avg_rating) }}
|
|
{% else %}
|
|
<span class="text-muted">—</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ book.review_count }}</td>
|
|
<td>
|
|
<a href="{{ url_for('book_view', book_id=book.id) }}"
|
|
class="btn btn-sm btn-outline-primary" title="Просмотр">
|
|
<i class="bi bi-eye"></i>
|
|
</a>
|
|
{% if current_user and current_user.role_name in ['администратор', 'модератор'] %}
|
|
<a href="{{ url_for('book_edit', book_id=book.id) }}"
|
|
class="btn btn-sm btn-outline-secondary" title="Редактировать">
|
|
<i class="bi bi-pencil"></i>
|
|
</a>
|
|
{% endif %}
|
|
{% if current_user and current_user.role_name == 'администратор' %}
|
|
<button type="button" class="btn btn-sm btn-outline-danger"
|
|
title="Удалить"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#deleteModal"
|
|
data-book-id="{{ book.id }}"
|
|
data-book-title="{{ book.title }}">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{# ── Пагинация ────────────────────────────────────────────────────────────── #}
|
|
{% if total_pages > 1 %}
|
|
<nav>
|
|
<ul class="pagination justify-content-center">
|
|
{% for p in range(1, total_pages + 1) %}
|
|
<li class="page-item {% if p == page %}active{% endif %}">
|
|
<a class="page-link"
|
|
href="{{ url_for('index', page=p,
|
|
title=q_title, author=q_author,
|
|
pages_from=q_pages_from, pages_to=q_pages_to,
|
|
genres=q_genres, years=q_years) }}">{{ p }}</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</nav>
|
|
{% endif %}
|
|
|
|
{% else %}
|
|
<div class="alert alert-info">Книги не найдены</div>
|
|
{% endif %}
|
|
|
|
{% if current_user and current_user.role_name == 'администратор' %}
|
|
<div class="mt-3">
|
|
<a href="{{ url_for('book_add') }}" class="btn btn-success">
|
|
<i class="bi bi-plus-circle"></i> Добавить книгу
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# ── Модальное окно удаления ──────────────────────────────────────────────── #}
|
|
<div class="modal fade" id="deleteModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Удаление книги</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p id="deleteMessage"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<form id="deleteForm" method="post">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Нет</button>
|
|
<button type="submit" class="btn btn-danger">Да</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
const deleteModal = document.getElementById('deleteModal');
|
|
deleteModal.addEventListener('show.bs.modal', function(event) {
|
|
const btn = event.relatedTarget;
|
|
const bookId = btn.dataset.bookId;
|
|
const bookTitle = btn.dataset.bookTitle;
|
|
document.getElementById('deleteMessage').textContent =
|
|
'Вы уверены, что хотите удалить книгу «' + bookTitle + '»?';
|
|
document.getElementById('deleteForm').action = '/book/' + bookId + '/delete';
|
|
});
|
|
</script>
|
|
{% endblock %}
|