let trendingBooks = [];
let currentHeroIndex = 0;
let heroInterval;
let availableExtensions = [];
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 {
let apiUrl = `/api/search/books?q=${encodeURIComponent(query)}`;
let extensionName = null;
let finalQuery = query;
const parts = query.split(':');
if (parts.length >= 2) {
const potentialExtension = parts[0].trim().toLowerCase();
const foundExtension = availableExtensions.find(ext => ext.toLowerCase() === potentialExtension);
if (foundExtension) {
extensionName = foundExtension;
finalQuery = parts.slice(1).join(':').trim();
if (finalQuery.length === 0) {
renderSearchResults([]);
return;
}
apiUrl = `/api/search/books/${extensionName}?q=${encodeURIComponent(finalQuery)}`;
}
}
const res = await fetch(apiUrl);
const data = await res.json();
const resultsWithExtension = data.results.map(book => {
if (extensionName) {
return { ...book,
isExtensionResult: true,
extensionName: extensionName
};
}
return book;
});
renderSearchResults(resultsWithExtension || []);
} catch (err) {
console.error("Search Error:", err);
renderSearchResults([]);
}
}
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 = Number.isInteger(book.averageScore) ? `${book.averageScore}%` : book.averageScore || 'N/A';
const year = book.seasonYear || (book.startDate ? book.startDate.year : '') || '????';
const format = book.format || 'MANGA';
const item = document.createElement('a');
item.className = 'search-item';
let href;
if (book.isExtensionResult) {
href = `/book/${book.extensionName}/${book.id}`;
} else {
href = `/book/${book.id}`;
}
item.href = href;
item.innerHTML = `
${title}
${rating}
• ${year}
• ${format}
`;
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 resExt = await fetch('/api/extensions/book');
const dataExt = await resExt.json();
if (dataExt.extensions) {
availableExtensions = dataExt.extensions;
console.log("Extensiones disponibles cargadas:", availableExtensions);
}
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();