Добавление количества страниц книгам

This commit is contained in:
2026-01-23 01:31:50 +03:00
parent 1e0c3478a1
commit 7c3074e8fe
15 changed files with 152 additions and 21 deletions
+14 -2
View File
@@ -1,43 +1,55 @@
"""Модуль DTO-моделей книг"""
from typing import List
from pydantic import ConfigDict
from sqlmodel import SQLModel
from sqlmodel import SQLModel, Field
from library_service.models.enums import BookStatus
class BookBase(SQLModel):
"""Базовая модель книги"""
title: str
description: str
page_count: int = Field(gt=0)
model_config = ConfigDict( # pyright: ignore
json_schema_extra={
"example": {"title": "book_title", "description": "book_description"}
"example": {
"title": "book_title",
"description": "book_description",
"page_count": 1,
}
}
)
class BookCreate(BookBase):
"""Модель книги для создания"""
pass
class BookUpdate(SQLModel):
"""Модель книги для обновления"""
title: str | None = None
description: str | None = None
page_count: int | None = None
status: BookStatus | None = None
class BookRead(BookBase):
"""Модель книги для чтения"""
id: int
status: BookStatus
class BookList(SQLModel):
"""Список книг"""
books: List[BookRead]
total: int
+3
View File
@@ -37,6 +37,7 @@ class BookWithAuthors(SQLModel):
id: int
title: str
description: str
page_count: int
authors: List[AuthorRead] = Field(default_factory=list)
@@ -46,6 +47,7 @@ class BookWithGenres(SQLModel):
id: int
title: str
description: str
page_count: int
status: BookStatus | None = None
genres: List[GenreRead] = Field(default_factory=list)
@@ -56,6 +58,7 @@ class BookWithAuthorsAndGenres(SQLModel):
id: int
title: str
description: str
page_count: int
status: BookStatus | None = None
authors: List[AuthorRead] = Field(default_factory=list)
genres: List[GenreRead] = Field(default_factory=list)
+6
View File
@@ -234,6 +234,12 @@ $(document).ready(() => {
function renderBook(book) {
$("#book-title").text(book.title);
$("#book-id").text(`ID: ${book.id}`);
if (book.page_count && book.page_count > 0) {
$("#book-page-count-value").text(book.page_count);
$("#book-page-count-text").removeClass("hidden");
} else {
$("#book-page-count-text").addClass("hidden");
}
$("#book-authors-text").text(
book.authors.map((a) => a.name).join(", ") || "Автор неизвестен",
);
+5
View File
@@ -180,6 +180,11 @@ $(document).ready(() => {
clone.querySelector(".book-title").textContent = book.title;
clone.querySelector(".book-authors").textContent =
book.authors.map((a) => a.name).join(", ") || "Автор неизвестен";
if (book.page_count && book.page_count > 0) {
const pageEl = clone.querySelector(".book-page-count");
pageEl.querySelector(".page-count-value").textContent = book.page_count;
pageEl.classList.remove("hidden");
}
clone.querySelector(".book-desc").textContent = book.description || "";
const statusConfig = getStatusConfig(book.status);
@@ -235,18 +235,25 @@ $(document).ready(() => {
const title = $("#book-title").val().trim();
const description = $("#book-description").val().trim();
const pageCount = parseInt($("#book-page-count").val()) || null;
if (!title) {
Utils.showToast("Введите название книги", "error");
return;
}
if (!parseInt(pageCount)) {
Utils.showToast("Введите количество страниц", "error");
return;
}
setLoading(true);
try {
const bookPayload = {
title: title,
description: description || null,
page_count: pageCount ? parseInt(pageCount) : null,
};
const createdBook = await Api.post("/api/books/", bookPayload);
+4
View File
@@ -23,6 +23,7 @@ $(document).ready(() => {
const $titleInput = $("#book-title");
const $descInput = $("#book-description");
const $statusSelect = $("#book-status");
const $pagesInput = $("#book-page-count");
const $submitBtn = $("#submit-btn");
const $submitText = $("#submit-text");
const $loadingSpinner = $("#loading-spinner");
@@ -69,6 +70,7 @@ $(document).ready(() => {
function populateForm(book) {
$titleInput.val(book.title);
$descInput.val(book.description || "");
$pagesInput.val(book.page_count);
$statusSelect.val(book.status);
updateCounters();
}
@@ -329,6 +331,7 @@ $(document).ready(() => {
const title = $titleInput.val().trim();
const description = $descInput.val().trim();
const pages = $pagesInput.val();
const status = $statusSelect.val();
if (!title) {
@@ -340,6 +343,7 @@ $(document).ready(() => {
if (title !== originalBook.title) payload.title = title;
if (description !== (originalBook.description || ""))
payload.description = description || null;
if (pageCount !== originalBook.page_count) payload.page_count = pages;
if (status !== originalBook.status) payload.status = status;
if (Object.keys(payload).length === 0) {
+2 -2
View File
@@ -19,8 +19,8 @@ const StorageHelper = {
const Utils = {
escapeHtml: (text) => {
if (!text) return "";
return text.replace(
if (text === null || text === undefined) return "";
return String(text).replace(
/[&<>"']/g,
(m) =>
({
+4
View File
@@ -107,6 +107,10 @@
id="book-authors-text"
class="text-lg text-gray-600 font-medium mb-6"
></p>
<p id="book-page-count-text" class="text-sm text-gray-500 mb-6 hidden">
<span class="font-medium">Количество страниц:</span>
<span id="book-page-count-value"></span>
</p>
<div class="prose prose-gray max-w-none mb-8">
<h3
class="text-sm font-bold text-gray-400 uppercase tracking-wider mb-2"
+4
View File
@@ -152,6 +152,10 @@
<span class="font-medium">Авторы:</span>
<span class="book-authors"></span>
</p>
<p class="book-page-count text-sm text-gray-600 mb-2 hidden">
<span class="font-medium">Страниц:</span>
<span class="page-count-value"></span>
</p>
<p
class="book-desc text-gray-700 text-sm mb-2 line-clamp-3"
></p>
@@ -69,6 +69,22 @@
>
</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 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">
+17
View File
@@ -78,6 +78,23 @@
</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"