let trendingBooks = []; let currentHeroIndex = 0; let heroInterval; window.addEventListener('scroll', () => { const nav = document.getElementById('navbar'); if (window.scrollY > 50) nav.classList.add('scrolled'); else nav.classList.remove('scrolled'); }); const searchInput = document.getElementById('search-input'); const searchResults = document.getElementById('search-results'); let searchTimeout; searchInput.addEventListener('input', (e) => { const query = e.target.value; clearTimeout(searchTimeout); if (query.length < 2) { searchResults.classList.remove('active'); searchResults.innerHTML = ''; searchInput.style.borderRadius = '99px'; return; } searchTimeout = setTimeout(() => { fetchBookSearch(query); }, 300); }); document.addEventListener('click', (e) => { if (!e.target.closest('.search-wrapper')) { searchResults.classList.remove('active'); searchInput.style.borderRadius = '99px'; } }); async function fetchBookSearch(query) { try { const res = await fetch(`/api/search/books?q=${encodeURIComponent(query)}`); const data = await res.json(); renderSearchResults(data.results || []); } catch (err) { console.error("Search Error:", err); renderSearchResults([]); } } function createSlug(text) { if (!text) return ''; return text .toLowerCase() .trim() .replace(/-/g, '--') .replace(/\s+/g, '-') .replace(/[^a-z0-9\-]/g, ''); } function renderSearchResults(results) { searchResults.innerHTML = ''; if (!results || results.length === 0) { searchResults.innerHTML = '
No results found
'; } else { results.forEach(book => { const title = book.title.english || book.title.romaji || "Unknown"; const img = (book.coverImage && (book.coverImage.medium || book.coverImage.large)) || ''; const rating = book.averageScore ? `${book.averageScore}%` : 'N/A'; const year = book.seasonYear || (book.startDate ? book.startDate.year : '') || '????'; const format = book.format || 'MANGA'; let href; if (book.isExtensionResult) { const titleSlug = createSlug(title); href = `/book/${book.extensionName}/${titleSlug}`; } else { href = `/book/${book.id}`; } const extName = book.extensionName.charAt(0).toUpperCase() + book.extensionName.slice(1); const extPill = book.isExtensionResult ? `${extName}` : ''; const item = document.createElement('a'); item.className = 'search-item'; item.href = href; item.innerHTML = ` ${title}
${title}
${rating} • ${year} • ${format} ${extPill}
`; searchResults.appendChild(item); }); } searchResults.classList.add('active'); searchInput.style.borderRadius = '12px 12px 0 0'; } function scrollCarousel(id, direction) { const container = document.getElementById(id); if(container) { const scrollAmount = container.clientWidth * 0.75; container.scrollBy({ left: direction * scrollAmount, behavior: 'smooth' }); } } async function init() { try { const res = await fetch('/api/books/trending'); const data = await res.json(); if (data.results && data.results.length > 0) { trendingBooks = data.results; updateHeroUI(trendingBooks[0]); renderList('trending', trendingBooks); startHeroCycle(); } const resPop = await fetch('/api/books/popular'); const dataPop = await resPop.json(); if (dataPop.results) renderList('popular', dataPop.results); } catch (e) { console.error("Books Error:", e); } } function startHeroCycle() { if(heroInterval) clearInterval(heroInterval); heroInterval = setInterval(() => { if(trendingBooks.length > 0) { currentHeroIndex = (currentHeroIndex + 1) % trendingBooks.length; updateHeroUI(trendingBooks[currentHeroIndex]); } }, 8000); } function updateHeroUI(book) { if(!book) return; const title = book.title.english || book.title.romaji; const desc = book.description || "No description available."; const poster = (book.coverImage && (book.coverImage.extraLarge || book.coverImage.large)) || ''; const banner = book.bannerImage || poster; document.getElementById('hero-title').innerText = title; document.getElementById('hero-desc').innerHTML = desc; document.getElementById('hero-score').innerText = (book.averageScore || '?') + '% Score'; document.getElementById('hero-year').innerText = (book.startDate && book.startDate.year) ? book.startDate.year : '????'; document.getElementById('hero-type').innerText = book.format || 'MANGA'; const heroPoster = document.getElementById('hero-poster'); if(heroPoster) heroPoster.src = poster; const bg = document.getElementById('hero-bg-media'); if(bg) bg.src = banner; const readBtn = document.getElementById('read-btn'); if (readBtn) { readBtn.onclick = () => window.location.href = `/book/${book.id}`; } } function renderList(id, list) { const container = document.getElementById(id); container.innerHTML = ''; list.forEach(book => { const title = book.title.english || book.title.romaji; const cover = book.coverImage ? book.coverImage.large : ''; const score = book.averageScore || '--'; const type = book.format || 'Book'; const el = document.createElement('div'); el.className = 'card'; el.onclick = () => { window.location.href = `/book/${book.id}`; }; el.innerHTML = `

${title}

${score}% • ${type}

`; container.appendChild(el); }); } init();