diff --git a/library_service/routers/__init__.py b/library_service/routers/__init__.py
index 7661a50..624e55e 100644
--- a/library_service/routers/__init__.py
+++ b/library_service/routers/__init__.py
@@ -11,9 +11,9 @@ from .misc import router as misc_router
api_router = APIRouter()
# Подключение всех маршрутов
-api_router.include_router(auth_router)
-api_router.include_router(authors_router)
-api_router.include_router(books_router)
-api_router.include_router(genres_router)
-api_router.include_router(relationships_router)
api_router.include_router(misc_router)
+api_router.include_router(auth_router, prefix="/api")
+api_router.include_router(authors_router, prefix="/api")
+api_router.include_router(books_router, prefix="/api")
+api_router.include_router(genres_router, prefix="/api")
+api_router.include_router(relationships_router, prefix="/api")
diff --git a/library_service/routers/misc.py b/library_service/routers/misc.py
index b00687d..678305d 100644
--- a/library_service/routers/misc.py
+++ b/library_service/routers/misc.py
@@ -34,6 +34,13 @@ async def root(request: Request, app=Depends(get_app)):
return templates.TemplateResponse(request, "index.html", get_info(app))
+@router.get("/auth", include_in_schema=False)
+async def root(request: Request, app=Depends(get_app)):
+ """Эндпоинт страницы авторизации"""
+ return templates.TemplateResponse(request, "auth.html", get_info(app))
+
+
+
@router.get("/api", include_in_schema=False)
async def root(request: Request, app=Depends(get_app)):
"""Страница с сылками на документацию API"""
diff --git a/library_service/static/script.js b/library_service/static/script.js
index 4cb272f..48e6c97 100644
--- a/library_service/static/script.js
+++ b/library_service/static/script.js
@@ -1,135 +1,115 @@
-// Load authors and genres asynchronously
-Promise.all([
- fetch("/authors").then((response) => response.json()),
- fetch("/genres").then((response) => response.json()),
-])
- .then(([authorsData, genresData]) => {
- // Populate authors dropdown
- const dropdown = document.getElementById("author-dropdown");
- authorsData.authors.forEach((author) => {
- const div = document.createElement("div");
- div.className = "p-2 hover:bg-gray-100 cursor-pointer";
- div.setAttribute("data-value", author.name);
- div.textContent = author.name;
- dropdown.appendChild(div);
- });
+$(document).ready(function () {
+ Promise.all([
+ fetch("/authors").then((response) => response.json()),
+ fetch("/genres").then((response) => response.json()),
+ ])
+ .then(([authorsData, genresData]) => {
+ const $dropdown = $("#author-dropdown");
+ authorsData.authors.forEach((author) => {
+ const $div = $("
", {
+ class: "p-2 hover:bg-gray-100 cursor-pointer",
+ "data-value": author.name,
+ text: author.name,
+ });
+ $dropdown.append($div);
+ });
- // Populate genres list
- const list = document.getElementById("genres-list");
- genresData.genres.forEach((genre) => {
- const li = document.createElement("li");
- li.className = "mb-1";
- li.innerHTML = `
+ const $list = $("#genres-list");
+ genresData.genres.forEach((genre) => {
+ const $li = $("
", { class: "mb-1" });
+ $li.html(`
- `;
- list.appendChild(li);
+ `);
+ $list.append($li);
+ });
+
+ initializeAuthorDropdown();
+ })
+ .catch((error) => console.error("Error loading data:", error));
+
+ function initializeAuthorDropdown() {
+ const $authorSearchInput = $("#author-search-input");
+ const $authorDropdown = $("#author-dropdown");
+ const $selectedAuthorsContainer = $("#selected-authors-container");
+ const $dropdownItems = $authorDropdown.find("[data-value]");
+ let selectedAuthors = new Set();
+
+ const updateDropdownHighlights = () => {
+ $dropdownItems.each(function () {
+ const value = $(this).data("value");
+ $(this).toggleClass("bg-gray-200", selectedAuthors.has(value));
+ });
+ };
+
+ const renderSelectedAuthors = () => {
+ $selectedAuthorsContainer.children().not("#author-search-input").remove();
+
+ selectedAuthors.forEach((author) => {
+ const $authorChip = $("", {
+ class:
+ "flex items-center bg-gray-200 text-gray-800 text-sm font-medium px-2.5 py-0.5 rounded-full",
+ });
+ $authorChip.html(`
+ ${author}
+
+ `);
+ $selectedAuthorsContainer.append($authorChip);
+ });
+ updateDropdownHighlights();
+ };
+
+ $authorSearchInput.on("focus", () => {
+ $authorDropdown.removeClass("hidden");
});
- initializeAuthorDropdown();
- })
- .catch((error) => console.error("Error loading data:", error));
-
-function initializeAuthorDropdown() {
- const authorSearchInput = document.getElementById("author-search-input");
- const authorDropdown = document.getElementById("author-dropdown");
- const selectedAuthorsContainer = document.getElementById(
- "selected-authors-container",
- );
- const dropdownItems = authorDropdown.querySelectorAll("[data-value]");
- let selectedAuthors = new Set();
-
- // Function to update highlights in dropdown
- const updateDropdownHighlights = () => {
- dropdownItems.forEach((item) => {
- const value = item.dataset.value;
- if (selectedAuthors.has(value)) {
- item.classList.add("bg-gray-200");
- } else {
- item.classList.remove("bg-gray-200");
- }
+ $authorSearchInput.on("input", function () {
+ const query = $(this).val().toLowerCase();
+ $dropdownItems.each(function () {
+ const text = $(this).text().toLowerCase();
+ $(this).css("display", text.includes(query) ? "block" : "none");
+ });
+ $authorDropdown.removeClass("hidden");
});
- };
- // Function to render selected authors
- const renderSelectedAuthors = () => {
- Array.from(selectedAuthorsContainer.children).forEach((child) => {
- if (child.id !== "author-search-input") {
- child.remove();
+ $(document).on("click", function (event) {
+ if (
+ !$selectedAuthorsContainer.is(event.target) &&
+ !$selectedAuthorsContainer.has(event.target).length &&
+ !$authorDropdown.is(event.target) &&
+ !$authorDropdown.has(event.target).length
+ ) {
+ $authorDropdown.addClass("hidden");
}
});
- selectedAuthors.forEach((author) => {
- const authorChip = document.createElement("span");
- authorChip.className =
- "flex items-center bg-gray-200 text-gray-800 text-sm font-medium px-2.5 py-0.5 rounded-full";
- authorChip.innerHTML = `
- ${author}
-
- `;
- selectedAuthorsContainer.insertBefore(authorChip, authorSearchInput);
- });
- updateDropdownHighlights();
- };
-
- // Handle input focus to show dropdown
- authorSearchInput.addEventListener("focus", () => {
- authorDropdown.classList.remove("hidden");
- });
-
- // Handle input for filtering
- authorSearchInput.addEventListener("input", () => {
- const query = authorSearchInput.value.toLowerCase();
- dropdownItems.forEach((item) => {
- const text = item.textContent.toLowerCase();
- item.style.display = text.includes(query) ? "block" : "none";
- });
- authorDropdown.classList.remove("hidden");
- });
-
- // Handle clicks outside to hide dropdown
- document.addEventListener("click", (event) => {
- if (
- !selectedAuthorsContainer.contains(event.target) &&
- !authorDropdown.contains(event.target)
- ) {
- authorDropdown.classList.add("hidden");
- }
- });
-
- // Handle author selection from dropdown
- authorDropdown.addEventListener("click", (event) => {
- const selectedValue = event.target.dataset.value;
- if (selectedValue) {
+ $authorDropdown.on("click", "[data-value]", function () {
+ const selectedValue = $(this).data("value");
if (selectedAuthors.has(selectedValue)) {
selectedAuthors.delete(selectedValue);
} else {
selectedAuthors.add(selectedValue);
}
- authorSearchInput.value = "";
+ $authorSearchInput.val("");
renderSelectedAuthors();
- authorSearchInput.focus();
- }
- });
+ $authorSearchInput.focus();
+ });
- // Handle removing selected author chip
- selectedAuthorsContainer.addEventListener("click", (event) => {
- if (event.target.closest("button")) {
- const authorToRemove = event.target.closest("button").dataset.author;
+ $selectedAuthorsContainer.on("click", "button", function () {
+ const authorToRemove = $(this).data("author");
selectedAuthors.delete(authorToRemove);
renderSelectedAuthors();
- authorSearchInput.focus();
- }
- });
+ $authorSearchInput.focus();
+ });
- // Initial render and highlights (without auto-focus)
- renderSelectedAuthors();
-}
+ renderSelectedAuthors();
+ }
+});
diff --git a/library_service/templates/api.html b/library_service/templates/api.html
index a1307fa..17ed01c 100644
--- a/library_service/templates/api.html
+++ b/library_service/templates/api.html
@@ -50,11 +50,12 @@
Current Time: {{ server_time }}
Status: {{ status }}