let user = null; const $ = id => document.getElementById(id); // DATA STORAGE const db = { getUsers: () => JSON.parse(localStorage.getItem('users')) || [{ username: 'admin', email: 'admin@library.com', password: 'admin123', fullname: 'Administrator', isAdmin: true }], saveUsers: u => localStorage.setItem('users', JSON.stringify(u)), getBooks: () => JSON.parse(localStorage.getItem('books')) || [ { id: 1, title: 'To Kill a Mockingbird', author: 'Harper Lee', genre: 'Fiction', quantity: 3, borrowedBy: [] }, { id: 2, title: '1984', author: 'George Orwell', genre: 'Dystopian', quantity: 2, borrowedBy: [] }, { id: 3, title: 'Pride and Prejudice', author: 'Jane Austen', genre: 'Romance', quantity: 2, borrowedBy: [] }, { id: 4, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', genre: 'Classic', quantity: 3, borrowedBy: [] }, { id: 5, title: 'The Hobbit', author: 'J. R. R. Tolkien', genre: 'Fantasy', quantity: 2, borrowedBy: [] }, { id: 6, title: 'The Catcher in the Rye', author: 'J. D. Salinger', genre: 'Fiction', quantity: 2, borrowedBy: [] }, { id: 7, title: 'The Alchemist', author: 'Paulo Coelho', genre: 'Adventure', quantity: 2, borrowedBy: [] }, { id: 8, title: 'Harry Potter and the Sorcerer\'s Stone', author: 'J. K. Rowling', genre: 'Fantasy', quantity: 4, borrowedBy: [] }, { id: 9, title: 'The Lord of the Rings', author: 'J. R. R. Tolkien', genre: 'Fantasy', quantity: 2, borrowedBy: [] }, { id: 10, title: 'The Hunger Games', author: 'Suzanne Collins', genre: 'Dystopian', quantity: 3, borrowedBy: [] }, { id: 11, title: 'The Book Thief', author: 'Markus Zusak', genre: 'Historical Fiction', quantity: 2, borrowedBy: [] }, { id: 12, title: 'The Chronicles of Narnia', author: 'C. S. Lewis', genre: 'Fantasy', quantity: 2, borrowedBy: [] }, { id: 13, title: 'Brave New World', author: 'Aldous Huxley', genre: 'Dystopian', quantity: 2, borrowedBy: [] }, { id: 14, title: 'The Fault in Our Stars', author: 'John Green', genre: 'Romance', quantity: 3, borrowedBy: [] }, { id: 15, title: 'The Da Vinci Code', author: 'Dan Brown', genre: 'Mystery', quantity: 2, borrowedBy: [] }, { id: 16, title: 'The Shining', author: 'Stephen King', genre: 'Horror', quantity: 2, borrowedBy: [] }, { id: 17, title: 'The Girl with the Dragon Tattoo', author: 'Stieg Larsson', genre: 'Crime', quantity: 2, borrowedBy: [] }, { id: 18, title: 'Moby-Dick', author: 'Herman Melville', genre: 'Adventure', quantity: 1, borrowedBy: [] }, { id: 19, title: 'The Road', author: 'Cormac McCarthy', genre: 'Post-Apocalyptic', quantity: 2, borrowedBy: [] }, { id: 20, title: 'Jane Eyre', author: 'Charlotte Brontë', genre: 'Romance', quantity: 2, borrowedBy: [] } ], saveBooks: b => localStorage.setItem('books', JSON.stringify(b)), getHistory: () => JSON.parse(localStorage.getItem('history')) || [], saveHistory: h => localStorage.setItem('history', JSON.stringify(h)) }; // HELPERS const getUser = n => db.getUsers().find(u => u.username === n); const addHistory = (id, title, action, details) => { const h = db.getHistory(); h.push({ id: Date.now(), username: user.username, bookId: id, bookTitle: title, action, timestamp: new Date().toISOString(), ...details }); db.saveHistory(h); }; const getBorrowed = b => b.borrowedBy.filter(x => !x.returnDate).length; const getAvailable = b => b.quantity - getBorrowed(b); const formatDate = d => new Date(d).toLocaleDateString(); const userRecord = (b, u) => b.borrowedBy.find(x => x.user === u && !x.returnDate); // INIT window.addEventListener('DOMContentLoaded', () => { // Clear old data with ISBN and reset to new format with genres const oldBooks = JSON.parse(localStorage.getItem('books') || '[]'); if (oldBooks.length > 0 && oldBooks[0].isbn) { localStorage.removeItem('books'); localStorage.removeItem('history'); } user = localStorage.getItem('currentUser') ? getUser(localStorage.getItem('currentUser')) : { username: 'guest', fullname: 'Gast', isAdmin: false }; $('welcome-sidebar').innerText = user.fullname; if (user.isAdmin) $('tab-admin').style.display = 'flex'; switchTab('dashboard'); }); // AUTHEN const handleRegister = () => { const [u, e, p, f] = [$('register-username').value, $('register-email').value, $('register-password').value, $('register-fullname').value].map(x => x.trim()); if (!u || !e || !p || !f) return alert('Bitte alle Felder ausfüllen'); if (getUser(u)) return alert('Benutzer existiert bereits'); db.getUsers().push({ username: u, email: e, password: p, fullname: f, isAdmin: false, registeredDate: new Date().toISOString() }); db.saveUsers(db.getUsers()); alert('Erfolg! Du kannst dich jetzt anmelden.'); toggleAuthForm(); [$('register-username'), $('register-email'), $('register-password'), $('register-fullname')].forEach(x => x.value = ''); }; const handleLogin = () => { const [u, p] = [$('login-username').value.trim(), $('login-password').value.trim()]; if (!u || !p) return alert('Bitte Anmeldedaten eingeben'); const userData = getUser(u); if (!userData || userData.password !== p) return alert('Ungültige Anmeldedaten'); user = userData; localStorage.setItem('currentUser', u); $('login-username').value = ''; $('login-password').value = ''; $('auth-section').classList.add('hidden'); $('welcome-sidebar').innerText = user.fullname; if (user.isAdmin) $('tab-admin').style.display = 'flex'; switchTab('dashboard'); }; const logout = () => { localStorage.removeItem('currentUser'); user = { username: 'guest', fullname: 'Gast', isAdmin: false }; $('welcome-sidebar').innerText = 'Gast'; $('tab-admin').style.display = 'none'; $('auth-section').classList.remove('hidden'); switchTab('dashboard'); }; const toggleAuthForm = () => { $('login-form').classList.toggle('hidden'); $('register-form').classList.toggle('hidden'); }; // BOOKS const borrowBook = bid => { const books = db.getBooks(); const book = books.find(b => b.id === bid); if (!book || userRecord(book, user.username) || getAvailable(book) <= 0) return alert('Kann nicht ausgeliehen werden'); const due = new Date(); due.setDate(due.getDate() + 14); book.borrowedBy.push({ user: user.username, borrowDate: new Date().toISOString(), dueDate: due.toISOString(), returnDate: null }); db.saveBooks(books); addHistory(book.id, book.title, 'BORROWED', { dueDate: due.toISOString() }); render(); }; const returnBook = bid => { const books = db.getBooks(); const book = books.find(b => b.id === bid); const record = userRecord(book, user.username); if (!record) return alert('Nicht ausgeliehen'); record.returnDate = new Date().toISOString(); db.saveBooks(books); addHistory(book.id, book.title, 'RETURNED'); render(); }; const addBookAdmin = () => { const [t, a, g, q] = [$('admin-title').value.trim(), $('admin-author').value.trim(), $('admin-genre').value.trim(), parseInt($('admin-quantity').value) || 1]; if (!t || !a || !g) return alert('Bitte alle Felder ausfüllen'); const books = db.getBooks(); const existing = books.find(b => b.title === t); if (existing) existing.quantity += q; else books.push({ id: Date.now(), title: t, author: a, genre: g, quantity: q, borrowedBy: [] }); db.saveBooks(books); [$('admin-title'), $('admin-author'), $('admin-genre'), $('admin-quantity')].forEach(x => x.value = x === $('admin-quantity') ? '1' : ''); renderAdminBooks(); }; // UI const switchTab = t => { document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden')); document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active')); $(t + '-tab').classList.remove('hidden'); $('tab-' + t).classList.add('active'); if (t === 'books') populateGenreFilter(); ({ books: renderBooks, 'my-books': renderMyBooks, history: renderHistory, admin: renderAdminBooks, dashboard: updateDashboard }[t] || (() => {}))(); }; const updateDashboard = () => { const newsItems = [ { id: 1, title: 'Neuerscheinung: Die Mitternachtsbibliothek', subtitle: 'Matt Haig', desc: 'Eine fesselnde moderne Fantasy über die Entscheidungen, die wir nie getroffen haben. Jetzt verfügbar!' }, { id: 2, title: 'Autogrammstunde', subtitle: 'Brandon Sanderson Tour 2024', desc: 'Nimm teil an einer exklusiven Signierstunde mit Bestsellerautor Brandon Sanderson am 15. März um 18 Uhr.' }, { id: 3, title: 'Neuerscheinung', subtitle: 'Project Hail Mary - Andy Weir', desc: 'Erscheint am 28. Februar! Jetzt vorbestellen für dieses epische Sci-Fi-Abenteuer.' }, { id: 4, title: 'Neu im Bestand: Fourth Wing', subtitle: 'Rebecca Yarros', desc: 'Drachenreiter, Magie und epische Romantik. Diese Fantasy-Sensation jetzt in unserer Sammlung!' }, { id: 5, title: 'Autoren-Spotlight', subtitle: 'Colleen Hoover Kollektion', desc: 'Wir haben unseren Romance-Bereich um die vollständigen Werke von Colleen Hoover erweitert.' }, { id: 6, title: 'Lese-Challenge 2024', subtitle: 'Mach mit in der Community', desc: 'Lies 12 Bücher in diesem Jahr! Gewinne exklusive Lesezeichen und Bibliotheks-Preise.' }, { id: 7, title: 'Valentinstag-Special', subtitle: 'Romantische Bücher', desc: 'Entdecke unsere Auswahl an Liebesromanen und erhalte 20% Rabatt, wenn du 3 oder mehr ausleihst!' }, { id: 8, title: 'Beliebt jetzt', subtitle: 'Verity von Colleen Hoover', desc: 'Der meistgelesene Thriller, den Leser nicht aus der Hand legen können. Nur begrenzt verfügbar!' } ]; const persistedIds = JSON.parse(localStorage.getItem('newsItemsOrder') || 'null'); const selectedIds = Array.isArray(persistedIds) && persistedIds.length ? persistedIds : newsItems.slice(0, 6).map(i => i.id); if (!persistedIds) { localStorage.setItem('newsItemsOrder', JSON.stringify(selectedIds)); } const news = selectedIds.map(id => newsItems.find(i => i.id === id)).filter(Boolean); $('news-container').innerHTML = news.map(n => `
${n.subtitle}
${n.desc}
Autor: ${b.author}
Genre: ${b.genre}
Verfügbar: ${avail}/${b.quantity}
Fällig: ${formatDate(rec.dueDate)}
` : (avail > 0 ? `` : '')}Autor: ${b.author}
Ausgeliehen: ${formatDate(b.record.borrowDate)}
Fällig: ${formatDate(b.record.dueDate)}
${overdue ? 'ÜBERFÄLLIG
' : ''}| Datum | Titel | Aktion | Fällig |
|---|---|---|---|
| ${formatDate(e.timestamp)} | ${e.bookTitle} | ${e.action === 'BORROWED' ? 'Ausgeliehen' : 'Zurückgegeben'} | ${e.dueDate ? formatDate(e.dueDate) : '-'} |
${x.user} (${formatDate(x.dueDate)}) ${new Date(x.dueDate) < new Date() ? 'ÜBERFÄLLIG' : ''}
`).join(''); return `Autor: ${b.author}
Genre: ${b.genre}
Gesamt: ${b.quantity} | Verfügbar: ${getAvailable(b)} | Ausgeliehen: ${borrowed}
${details ? `