$(document).ready(() => { let allLoans = []; let booksCache = new Map(); init(); function init() { const user = window.getUser(); if (!user) { Utils.showToast("Необходима авторизация", "error"); window.location.href = "/auth"; return; } loadLoans(); } async function loadLoans() { try { const data = await Api.get("/api/loans/?page=1&size=100"); allLoans = data.loans; const bookIds = [...new Set(allLoans.map((loan) => loan.book_id))]; await loadBooks(bookIds); renderLoans(); } catch (error) { console.error("Failed to load loans", error); Utils.showToast("Ошибка загрузки выдач", "error"); } } async function loadBooks(bookIds) { const promises = bookIds.map(async (bookId) => { if (!booksCache.has(bookId)) { try { const book = await Api.get(`/api/books/${bookId}`); booksCache.set(bookId, book); } catch (error) { console.error(`Failed to load book ${bookId}`, error); } } }); await Promise.all(promises); } function renderLoans() { const reservations = allLoans.filter( (loan) => !loan.returned_at && getBookStatus(loan.book_id) === "reserved", ); const activeLoans = allLoans.filter( (loan) => !loan.returned_at && getBookStatus(loan.book_id) === "borrowed", ); const returned = allLoans.filter((loan) => loan.returned_at !== null); renderReservations(reservations); renderActiveLoans(activeLoans); renderReturned(returned); } function getBookStatus(bookId) { const book = booksCache.get(bookId); return book ? book.status : null; } function renderReservations(reservations) { const $container = $("#reservations-container"); $("#reservations-count").text(reservations.length); $container.empty(); if (reservations.length === 0) { $container.html( '
Нет активных бронирований
', ); return; } reservations.forEach((loan) => { const book = booksCache.get(loan.book_id); if (!book) return; const borrowedDate = new Date(loan.borrowed_at).toLocaleDateString( "ru-RU", ); const dueDate = new Date(loan.due_date).toLocaleDateString("ru-RU"); const $card = $(`
${Utils.escapeHtml(book.title)}

Авторы: ${book.authors.map((a) => a.name).join(", ") || "Не указаны"}

Дата бронирования: ${borrowedDate}

Срок возврата: ${dueDate}

Забронирована
`); $card.find(".cancel-reservation-btn").on("click", function () { const loanId = $(this).data("loan-id"); const bookId = $(this).data("book-id"); cancelReservation(loanId, bookId); }); $container.append($card); }); } function renderActiveLoans(activeLoans) { const $container = $("#active-loans-container"); $("#active-loans-count").text(activeLoans.length); $container.empty(); if (activeLoans.length === 0) { $container.html( '
Нет активных выдач
', ); return; } activeLoans.forEach((loan) => { const book = booksCache.get(loan.book_id); if (!book) return; const borrowedDate = new Date(loan.borrowed_at).toLocaleDateString( "ru-RU", ); const dueDate = new Date(loan.due_date).toLocaleDateString("ru-RU"); const isOverdue = new Date(loan.due_date) < new Date(); const $card = $(`
${Utils.escapeHtml(book.title)}

Авторы: ${book.authors.map((a) => a.name).join(", ") || "Не указаны"}

Дата выдачи: ${borrowedDate}

Срок возврата: ${dueDate}

Выдана ${isOverdue ? 'Просрочена' : ""}
`); $container.append($card); }); } function renderReturned(returned) { const $container = $("#returned-container"); $("#returned-count").text(returned.length); $container.empty(); if (returned.length === 0) { $container.html( '
Нет возвращенных книг
', ); return; } returned.forEach((loan) => { const book = booksCache.get(loan.book_id); if (!book) return; const borrowedDate = new Date(loan.borrowed_at).toLocaleDateString( "ru-RU", ); const returnedDate = new Date(loan.returned_at).toLocaleDateString( "ru-RU", ); const dueDate = new Date(loan.due_date).toLocaleDateString("ru-RU"); const $card = $(`
${Utils.escapeHtml(book.title)}

Авторы: ${book.authors.map((a) => a.name).join(", ") || "Не указаны"}

Дата выдачи: ${borrowedDate}

Срок возврата: ${dueDate}

Дата возврата: ${returnedDate}

Возвращена
`); $container.append($card); }); } async function cancelReservation(loanId, bookId) { if (!confirm("Вы уверены, что хотите отменить бронирование?")) { return; } try { await Api.delete(`/api/loans/${loanId}`); Utils.showToast("Бронирование отменено", "success"); allLoans = allLoans.filter((loan) => loan.id !== loanId); const book = booksCache.get(bookId); if (book) { book.status = "active"; booksCache.set(bookId, book); } renderLoans(); } catch (error) { console.error(error); Utils.showToast(error.message || "Ошибка отмены бронирования", "error"); } } });