Team Ai
Apppublic

leetcoder2008/libraryspark

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
app.py243 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Books - LibrarySpark</title>7    <link rel="icon" type="image/x-icon" href="/static/favicon.ico">8    <link rel="stylesheet" href="style.css">9    <script src="https://cdn.tailwindcss.com"></script>10    <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>11    <script>12        tailwind.config = {13            theme: {14                extend: {15                    colors: {16                        primary: {17                            50: '#eff6ff',18                            100: '#dbeafe',19                            200: '#bfdbfe',20                            300: '#93c5fd',21                            400: '#60a5fa',22                            500: '#3b82f6',23                            600: '#2563eb',24                            700: '#1d4ed8',25                            800: '#1e40af',26                            900: '#1e3a8a',27                        },28                        secondary: {29                            50: '#f0fdf4',30                            100: '#dcfce7',31                            200: '#bbf7d0',32                            300: '#86efac',33                            400: '#4ade80',34                            500: '#22c55e',35                            600: '#16a34a',36                            700: '#15803d',37                            800: '#166534',38                            900: '#14532d',39                        }40                    }41                }42            }43        }44    </script>45</head>46<body class="bg-gray-50 min-h-screen">47    <custom-navbar></custom-navbar>48    49    <div class="container mx-auto px-4 py-8">50        <div class="flex justify-between items-center mb-8">51            <h1 class="text-3xl font-bold text-gray-800">Library Books</h1>52            <button id="add-book-btn" class="btn-primary flex items-center">53                <i data-feather="plus" class="mr-2"></i> Add Book54            </button>55        </div>56 57        <!-- Books Grid -->58        <div id="books-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">59            <!-- Books will be loaded here dynamically -->60        </div>61 62        <!-- Pagination -->63        <div id="pagination" class="flex justify-center mt-8 space-x-2">64            <!-- Pagination buttons will be added here -->65        </div>66    </div>67 68    <!-- Add Book Modal -->69    <div id="add-book-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">70        <div class="bg-white rounded-xl p-6 w-full max-w-md">71            <div class="flex justify-between items-center mb-4">72                <h2 class="text-xl font-bold">Add New Book</h2>73                <button id="close-modal" class="text-gray-500 hover:text-gray-700">74                    <i data-feather="x"></i>75                </button>76            </div>77            <form id="add-book-form">78                <div class="mb-4">79                    <label class="block text-gray-700 mb-2" for="title">Title</label>80                    <input type="text" id="title" name="title" class="w-full px-3 py-2 border rounded-lg" required>81                </div>82                <div class="mb-4">83                    <label class="block text-gray-700 mb-2" for="author">Author</label>84                    <input type="text" id="author" name="author" class="w-full px-3 py-2 border rounded-lg" required>85                </div>86                <div class="mb-4">87                    <label class="block text-gray-700 mb-2" for="isbn">ISBN</label>88                    <input type="text" id="isbn" name="isbn" class="w-full px-3 py-2 border rounded-lg" required>89                </div>90                <div class="mb-4">91                    <label class="block text-gray-700 mb-2" for="genre">Genre</label>92                    <input type="text" id="genre" name="genre" class="w-full px-3 py-2 border rounded-lg">93                </div>94                <div class="mb-4">95                    <label class="block text-gray-700 mb-2" for="copies">Total Copies</label>96                    <input type="number" id="copies" name="total_copies" class="w-full px-3 py-2 border rounded-lg" value="1" min="1" required>97                </div>98                <div class="flex justify-end space-x-3">99                    <button type="button" id="cancel-modal" class="px-4 py-2 text-gray-600 hover:text-gray-800">Cancel</button>100                    <button type="submit" class="btn-primary">Add Book</button>101                </div>102            </form>103        </div>104    </div>105 106    <custom-footer></custom-footer>107 108    <script src="components/navbar.js"></script>109    <script src="components/footer.js"></script>110    <script src="script.js"></script>111    <script>112        feather.replace();113        114        // DOM Elements115        const booksContainer = document.getElementById('books-container');116        const paginationContainer = document.getElementById('pagination');117        const addBookModal = document.getElementById('add-book-modal');118        const addBookBtn = document.getElementById('add-book-btn');119        const closeModal = document.getElementById('close-modal');120        const cancelModal = document.getElementById('cancel-modal');121        const addBookForm = document.getElementById('add-book-form');122        123        // Current page state124        let currentPage = 1;125        126        // Load books127        function loadBooks(page = 1) {128            fetch(`/api/books?page=${page}&per_page=9`)129                .then(response => response.json())130                .then(data => {131                    displayBooks(data.books);132                    setupPagination(data.pages, data.current_page);133                })134                .catch(error => console.error('Error loading books:', error));135        }136        137        // Display books in grid138        function displayBooks(books) {139            booksContainer.innerHTML = '';140            141            books.forEach(book => {142                const bookCard = document.createElement('div');143                bookCard.className = 'bg-white rounded-xl shadow-md overflow-hidden border border-gray-100';144                bookCard.innerHTML = `145                    <div class="p-6">146                        <div class="flex justify-between items-start mb-4">147                            <div>148                                <h3 class="text-xl font-bold text-gray-800">${book.title}</h3>149                                <p class="text-gray-600">by ${book.author}</p>150                            </div>151                            <span class="bg-primary-100 text-primary-800 text-xs font-semibold px-2.5 py-0.5 rounded">152                                ${book.genre || 'N/A'}153                            </span>154                        </div>155                        <div class="flex justify-between items-center">156                            <div>157                                <p class="text-sm text-gray-500">ISBN: ${book.isbn}</p>158                                <p class="text-sm mt-1">159                                    <span class="font-medium">${book.available_copies}</span> of 160                                    <span class="font-medium">${book.total_copies}</span> available161                                </p>162                            </div>163                            <button class="checkout-btn btn-primary text-sm" data-book-id="${book.id}">164                                Checkout165                            </button>166                        </div>167                    </div>168                `;169                booksContainer.appendChild(bookCard);170            });171            172            // Add event listeners to checkout buttons173            document.querySelectorAll('.checkout-btn').forEach(button => {174                button.addEventListener('click', function() {175                    const bookId = this.getAttribute('data-book-id');176                    alert(`Checkout functionality for book ID ${bookId} would go here`);177                });178            });179        }180        181        // Setup pagination182        function setupPagination(totalPages, currentPage) {183            paginationContainer.innerHTML = '';184            185            for (let i = 1; i <= totalPages; i++) {186                const button = document.createElement('button');187                button.className = `px-3 py-1 rounded ${i === currentPage ? 'bg-primary-500 text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300'}`;188                button.textContent = i;189                button.addEventListener('click', () => loadBooks(i));190                paginationContainer.appendChild(button);191            }192        }193        194        // Modal event listeners195        addBookBtn.addEventListener('click', () => {196            addBookModal.classList.remove('hidden');197        });198        199        closeModal.addEventListener('click', () => {200            addBookModal.classList.add('hidden');201        });202        203        cancelModal.addEventListener('click', () => {204            addBookModal.classList.add('hidden');205        });206        207        // Handle form submission208        addBookForm.addEventListener('submit', function(e) {209            e.preventDefault();210            211            const formData = new FormData(this);212            const bookData = {};213            formData.forEach((value, key) => {214                bookData[key] = value;215            });216            217            fetch('/api/books', {218                method: 'POST',219                headers: {220                    'Content-Type': 'application/json',221                },222                body: JSON.stringify(bookData)223            })224            .then(response => response.json())225            .then(data => {226                alert('Book added successfully!');227                addBookModal.classList.add('hidden');228                loadBooks(currentPage);229                addBookForm.reset();230            })231            .catch(error => {232                console.error('Error adding book:', error);233                alert('Error adding book. Please try again.');234            });235        });236        237        // Load books on page load238        document.addEventListener('DOMContentLoaded', () => {239            loadBooks();240        });241    </script>242</body>243</html>