Files
LibraryAPI/library_service/templates/edit_book.html

287 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}{% block content %}
<style>
.typing-cursor::after {
content: '▋';
display: inline-block;
vertical-align: bottom;
animation: blink 1s step-end infinite;
margin-left: 2px;
opacity: 0.7;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.fade-in {
animation: fadeIn 0.3s ease-in-out forwards;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<div class="container mx-auto p-4 max-w-3xl">
<div class="bg-white rounded-lg shadow-md p-6 md:p-8">
<div class="mb-8 border-b border-gray-100 pb-4">
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-3">
<svg class="w-8 h-8 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path>
</svg>
<span>Редактирование книги</span>
</h1>
<p class="text-gray-500 mt-2 text-sm ml-11">Измените информацию о книге, управляйте авторами и жанрами.</p>
</div>
<div id="loader" class="animate-pulse space-y-4">
<div class="h-12 bg-gray-200 rounded w-full"></div>
<div class="h-32 bg-gray-200 rounded w-full"></div>
<div class="h-12 bg-gray-200 rounded w-1/3"></div>
</div>
<form id="edit-book-form" class="hidden space-y-6">
<div id="ai-widget" class="hidden border border-gray-200 rounded-lg bg-white shadow-sm transition-shadow hover:shadow-md">
<div class="bg-gray-50 border-b border-gray-200 px-4 py-2.5 flex justify-between items-center select-none rounded-t-lg">
<div class="flex items-center gap-2.5">
<div class="relative group">
<div id="ai-logo" class="cursor-pointer p-1 bg-white border border-gray-200 rounded shadow-sm">
<svg class="w-5 h-5 text-gray-800" fill="currentColor" viewBox="0 0 24 24">
<rect x="2" y="19" width="20" height="3" rx="0.8" fill="currentColor" opacity="0.9"/>
<path d="M12 17V7c0 0-2.5-2-6-2-1.8 0-3 .4-3.5.6V17c.8-.3 2-.5 3.5-.5 3.2 0 6 1.5 6 1.5z"
fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
<path d="M12 17V7c0 0 2.5-2 6-2 1.8 0 3 .4 3.5.6V17c-.8-.3-2-.5-3.5-.5-3.2 0-6 1.5-6 1.5z"
fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
<circle cx="12" cy="2.8" r="2" fill="currentColor"/>
<circle cx="7.5" cy="3.8" r="1" fill="currentColor"/>
<circle cx="16.5" cy="3.8" r="1" fill="currentColor"/>
<line x1="10.2" y1="3" x2="8.4" y2="3.6" stroke="currentColor" stroke-width="1"/>
<line x1="13.8" y1="3" x2="15.6" y2="3.6" stroke="currentColor" stroke-width="1"/>
</svg>
</div>
<div class="absolute bottom-full left-1/2 -translate-x-1/2 mb-2
px-3 py-1.5 rounded-md
bg-gray-900 text-white text-[11px] font-medium
whitespace-nowrap
opacity-0 invisible
group-hover:opacity-100 group-hover:visible
transition-all duration-200 ease-out
pointer-events-none
select-none">
Сбросить чат
<div class="absolute top-full left-1/2 -translate-x-1/2
border-4 border-transparent border-t-gray-900"></div>
</div>
</div>
<span class="text-xs font-bold text-gray-700 tracking-[0.15em] uppercase">ИИ-помощник</span>
</div>
<div class="flex items-center gap-2">
<span class="text-[10px] font-mono uppercase text-gray-400" id="ai-status-text">Готов</span>
<span class="relative flex h-2 w-2">
<span id="ai-status-ping" class="hidden animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
<span id="ai-status-dot" class="relative inline-flex rounded-full h-2 w-2 bg-gray-300 transition-colors duration-300"></span>
</span>
</div>
</div>
<div id="ai-log-container" class="hidden border-b border-gray-100 bg-white max-h-80 overflow-y-auto">
<div id="ai-log-entries"></div>
</div>
<div class="flex relative bg-white rounded-b-lg">
<input
type="text"
id="ai-input"
class="flex-1 px-4 py-3.5 text-sm text-gray-900 placeholder-gray-400 bg-transparent focus:outline-none focus:bg-gray-50 transition-colors"
placeholder="Напишите задачу (например: 'Придумай драматичное описание')..."
autocomplete="off"
/>
<div class="flex border-l border-gray-100 items-center rounded-br-lg overflow-hidden">
<button type="button" id="ai-btn-stop"
class="hidden px-5 py-2 h-full bg-white text-red-600 text-xs font-bold tracking-widest hover:bg-red-50 transition-colors flex items-center gap-2">
<span>СТОП</span>
<span class="block w-2 h-2 bg-red-600 rounded-sm"></span>
</button>
<button type="button" id="ai-btn-run"
class="group px-6 py-2 h-full bg-white text-gray-900 text-xs font-bold tracking-widest hover:bg-gray-900 hover:text-white transition-all duration-300 flex items-center gap-2">
<span>СТАРТ</span>
<svg class="w-3 h-3 transition-transform group-hover:translate-x-0.5"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</button>
</div>
</div>
</div>
<div>
<label for="book-title" class="block text-sm font-semibold text-gray-700 mb-2">
Название книги <span class="text-red-500">*</span>
</label>
<input type="text" id="book-title" name="title" required maxlength="255"
class="w-full border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-gray-400 transition"
placeholder="Название книги..." />
<div class="flex justify-end mt-1">
<span id="title-counter" class="text-xs text-gray-400">0/255</span>
</div>
</div>
<div>
<label for="book-description" class="block text-sm font-semibold text-gray-700 mb-2">Описание</label>
<textarea id="book-description" name="description" rows="5" maxlength="2000"
class="w-full border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-gray-400 resize-none transition"
placeholder="Краткое описание сюжета..."></textarea>
<div class="flex justify-end mt-1">
<span id="desc-counter" class="text-xs text-gray-400">0/2000</span>
</div>
</div>
<div>
<label for="book-page-count" class="block text-sm font-semibold text-gray-700 mb-2">Количество страниц</label>
<input type="number" id="book-page-count" name="page_count" min="1"
class="w-full border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-gray-400 transition"
placeholder="Укажите количество страниц" />
</div>
<div>
<label for="book-status" class="block text-sm font-semibold text-gray-700 mb-2">Статус</label>
<select id="book-status" name="status"
class="w-full border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-gray-400 transition bg-white">
<option value="active">Доступна</option>
<option value="borrowed">Выдана</option>
<option value="reserved">Забронирована</option>
<option value="restoration">На реставрации</option>
<option value="written_off">Списана</option>
</select>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-white p-4 rounded-lg border border-gray-200">
<h2 class="text-sm font-semibold text-gray-700 mb-3 flex items-center justify-between">
<span>Авторы</span>
<span id="authors-count" class="text-xs text-gray-400 font-normal"></span>
</h2>
<div id="current-authors-container" class="flex flex-wrap gap-2 mb-3 min-h-[32px]"></div>
<div class="relative">
<input type="text" id="author-search-input" placeholder="Добавить автора..."
class="w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-gray-400" autocomplete="off" />
<div id="author-dropdown" class="hidden absolute z-50 w-full bg-white border border-gray-200 rounded-lg shadow-lg max-h-48 overflow-y-auto mt-1"></div>
</div>
</div>
<div class="bg-white p-4 rounded-lg border border-gray-200">
<h2 class="text-sm font-semibold text-gray-700 mb-3 flex items-center justify-between">
<span>Жанры</span>
<span id="genres-count" class="text-xs text-gray-400 font-normal"></span>
</h2>
<div id="current-genres-container" class="flex flex-wrap gap-2 mb-3 min-h-[32px]"></div>
<div class="relative">
<input type="text" id="genre-search-input" placeholder="Добавить жанр..."
class="w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-gray-400" autocomplete="off" />
<div id="genre-dropdown" class="hidden absolute z-50 w-full bg-white border border-gray-200 rounded-lg shadow-lg max-h-48 overflow-y-auto mt-1"></div>
</div>
</div>
</div>
<div class="flex flex-col sm:flex-row gap-3 pt-6 border-t border-gray-100">
<button type="submit" id="submit-btn"
class="flex-1 flex justify-center items-center px-6 py-3 bg-green-600 text-white font-bold rounded-lg hover:bg-green-700 focus:outline-none focus:ring-4 focus:ring-green-300 transition disabled:opacity-50 disabled:cursor-not-allowed">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span id="submit-text">Сохранить изменения</span>
<svg id="loading-spinner" class="hidden animate-spin ml-2 h-5 w-5 text-white" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
<a id="cancel-btn" href="#"
class="flex-1 flex justify-center items-center px-6 py-3 bg-white border border-gray-300 text-gray-700 font-medium rounded-lg hover:bg-gray-50 transition text-center">
Отмена
</a>
</div>
</form>
<div id="danger-zone" class="hidden mt-8 pt-6 border-t border-red-200">
<h3 class="text-lg font-bold text-red-600 mb-2 flex items-center gap-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
Опасная зона
</h3>
<p class="text-sm text-gray-600 mb-4">Удаление книги необратимо. Все связи с авторами и жанрами будут удалены.</p>
<button id="delete-btn"
class="inline-flex items-center px-4 py-2 bg-white border border-red-300 text-red-600 font-medium rounded-lg hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-red-300 transition">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
Удалить книгу
</button>
</div>
</div>
</div>
<div id="delete-modal" class="hidden fixed inset-0 bg-gray-900 bg-opacity-60 overflow-y-auto h-full w-full z-50 flex items-center justify-center">
<div class="relative p-5 border w-full max-w-md shadow-lg rounded-lg bg-white">
<div class="mt-3 text-center">
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4">
<svg class="h-6 w-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
</div>
<h3 class="text-lg leading-6 font-medium text-gray-900">Удалить книгу?</h3>
<div class="mt-2 px-7 py-3">
<p class="text-sm text-gray-500">
Вы уверены, что хотите удалить книгу
<span id="modal-book-title" class="font-bold text-gray-800"></span>? Это действие нельзя отменить.
</p>
</div>
<div class="flex gap-3 mt-4 justify-center">
<button id="confirm-delete-btn"
class="px-4 py-2 bg-red-600 text-white text-base font-medium rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 flex items-center">
<span>Удалить</span>
<svg id="delete-spinner" class="hidden animate-spin ml-2 h-4 w-4 text-white" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
<button id="cancel-delete-btn"
class="px-4 py-2 bg-white text-gray-700 border border-gray-300 text-base font-medium rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-200">
Отмена
</button>
</div>
</div>
</div>
</div>
<div id="success-modal" class="hidden fixed inset-0 bg-gray-900 bg-opacity-60 overflow-y-auto h-full w-full z-50 flex items-center justify-center">
<div class="relative p-5 border w-full max-w-md shadow-lg rounded-lg bg-white">
<div class="mt-3 text-center">
<div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100 mb-4">
<svg class="h-6 w-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
</div>
<h3 class="text-lg leading-6 font-medium text-gray-900">Изменения сохранены!</h3>
<div class="mt-2 px-7 py-3">
<p class="text-sm text-gray-500">
Книга <span id="success-book-title" class="font-bold text-gray-800"></span> успешно обновлена.
</p>
</div>
<div class="flex gap-3 mt-4 justify-center">
<a id="success-link-btn" href="#"
class="px-4 py-2 bg-gray-600 text-white text-base font-medium rounded-lg hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500">
Перейти к книге
</a>
<button id="success-close-btn"
class="px-4 py-2 bg-white text-gray-700 border border-gray-300 text-base font-medium rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-200">
Продолжить
</button>
</div>
</div>
</div>
</div>
{% endblock %}{% block scripts %}
<script src="/static/page/edit_book.js"></script>
{% endblock %}