// MangaVerse Dark - Main Script class MangaApp { constructor() { this.currentPage = 1; this.chaptersPerPage = 12; this.init(); } init() { this.loadTrending(); this.loadPopularAdditions(); this.loadNewChapters(); this.loadRecommendedLists(); this.loadBlogPosts(); this.initializeCarousels(); this.initializeFilters(); } // API helper async fetchMangaData(endpoint, params = {}) { try { const queryString = new URLSearchParams(params).toString(); const response = await fetch(`https://api.jikan.moe/v4/${endpoint}?${queryString}`); if (!response.ok) throw new Error('API request failed'); return await response.json(); } catch (error) { console.error('Error fetching manga data:', error); return { data: [] }; } } // Trending Section - 2-row grid, landscape cards async loadTrending() { const container = document.getElementById('trending-grid'); const data = await this.fetchMangaData('manga', { order_by: 'popularity', sort: 'desc', limit: 6 }); if (!data.data || data.data.length === 0) { container.innerHTML = this.generateSkeletons(6); return; } container.innerHTML = data.data.map((manga, index) => `
${manga.title}
${manga.type || 'Manga'}

${manga.title}

`).join(''); } // Popular Additions - Horizontal scroll, portrait cards with metadata async loadPopularAdditions() { const container = document.getElementById('popular-carousel'); const data = await this.fetchMangaData('manga', { order_by: 'score', sort: 'desc', limit: 8 }); if (!data.data || data.data.length === 0) { container.innerHTML = this.generateSkeletons(8, 'portrait'); return; } container.innerHTML = data.data.map((manga, index) => `
${manga.title}
${(manga.genres?.slice(0, 2) || []).map(genre => ` ${genre.name} `).join('')}

${manga.title}

${manga.chapters || '??'} capítulos ${this.formatNumber(manga.scored_by || Math.floor(Math.random() * 50000) + 1000)}
${this.formatNumber(Math.floor(manga.members * 0.1) || Math.floor(Math.random() * 10000) + 500)} ${manga.score || 'N/A'}
`).join(''); // Re-render feather icons for new content feather.replace(); } // New Chapters - Two-column list view async loadNewChapters() { const container = document.getElementById('chapters-list'); const data = await this.fetchMangaData('manga', { order_by: 'start_date', sort: 'desc', limit: 20 }); if (!data.data || data.data.length === 0) { container.innerHTML = this.generateListSkeletons(12); return; } const chapters = data.data.flatMap(manga => { const chapterCount = manga.chapters || Math.floor(Math.random() * 80) + 10; const latestChapter = Math.floor(Math.random() * chapterCount) + 1; return [{ manga_id: manga.mal_id, title: manga.title, chapter: latestChapter, timestamp: this.generateRandomTimestamp(), scan_group: this.getRandomScanGroup(), thumbnail: manga.images?.jpg?.image_url }]; }); this.renderChapters(chapters.slice(0, this.chaptersPerPage)); this.setupChapterPagination(chapters.length); } renderChapters(chapters) { const container = document.getElementById('chapters-list'); container.innerHTML = chapters.map(chapter => `
${chapter.title}

${chapter.title}

Capítulo ${chapter.chapter} ${chapter.scan_group} ${chapter.timestamp}
Nuevo
`).join(''); feather.replace(); } // Recommended Lists - Horizontal scroll loadRecommendedLists() { const container = document.getElementById('lists-carousel'); const lists = [ { name: 'Fantasía Épica', count: 33, color: 'purple', icon: 'sword' }, { name: 'Romance Shoujo', count: 28, color: 'pink', icon: 'heart' }, { name: 'Cyberpunk', count: 15, color: 'blue', icon: 'cpu' }, { name: 'Misterio Psicológico', count: 22, color: 'gray', icon: 'eye' }, { name: 'Aventura Isekai', count: 41, color: 'green', icon: 'compass' }, { name: 'Horror Gore', count: 18, color: 'red', icon: 'alert-triangle' }, { name: 'Slice of Life', count: 35, color: 'yellow', icon: 'coffee' }, { name: 'Deportes', count: 12, color: 'orange', icon: 'activity' } ]; container.innerHTML = lists.map(list => `

${list.name}

${list.count} obras

`).join(''); feather.replace(); } // Blog Section - 3-column grid loadBlogPosts() { const container = document.getElementById('blog-grid'); const posts = [ { title: 'Los mejores animes de primavera 2024', excerpt: 'Descubre qué series están dominando la temporada y cuáles no te puedes perder.', image: 'http://static.photos/nature/640x360/101', category: 'Temporada', date: '2 días atrás' }, { title: 'Guía completa de Demon Slayer', excerpt: 'Todo lo que necesitas saber sobre el fenómeno que revolucionó el manga moderno.', image: 'http://static.photos/nature/640x360/102', category: 'Guía', date: '5 días atrás' }, { title: 'Entrevista exclusiva con Tatsuki Fujimoto', excerpt: 'El autor de Chainsaw Man nos habla de su proceso creativo y futuros proyectos.', image: 'http://static.photos/nature/640x360/103', category: 'Entrevista', date: '1 semana atrás' } ]; container.innerHTML = posts.map(post => `
${post.title}
${post.category} ${post.date}

${post.title}

${post.excerpt}

Leer artículo
`).join(''); feather.replace(); } // Carousel controls initializeCarousels() { // Popular carousel const popularCarousel = document.getElementById('popular-carousel'); const popularPrev = document.getElementById('popular-prev'); const popularNext = document.getElementById('popular-next'); if (popularPrev && popularNext) { popularPrev.addEventListener('click', () => { popularCarousel.scrollBy({ left: -400, behavior: 'smooth' }); }); popularNext.addEventListener('click', () => { popularCarousel.scrollBy({ left: 400, behavior: 'smooth' }); }); } // Lists carousel const listsCarousel = document.getElementById('lists-carousel'); const listsPrev = document.getElementById('lists-prev'); const listsNext = document.getElementById('lists-next'); if (listsPrev && listsNext) { listsPrev.addEventListener('click', () => { listsCarousel.scrollBy({ left: -300, behavior: 'smooth' }); }); listsNext.addEventListener('click', () => { listsCarousel.scrollBy({ left: 300, behavior: 'smooth' }); }); } } // Chapter filter initializeFilters() { const filter = document.getElementById('chapter-filter'); if (filter) { filter.addEventListener('change', (e) => { // In a real app, this would filter the API results console.log('Filter changed to:', e.target.value); this.loadNewChapters(); }); } } // Pagination setup setupChapterPagination(totalItems) { const container = document.getElementById('chapters-pagination'); const totalPages = Math.ceil(totalItems / this.chaptersPerPage); container.innerHTML = ` ${Array.from({ length: Math.min(totalPages, 5) }, (_, i) => ` `).join('')} `; feather.replace(); } // Utility functions formatNumber(num) { if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M'; if (num >= 1000) return (num / 1000).toFixed(1) + 'k'; return num.toString(); } generateRandomTimestamp() { const times = ['Hace 15 min', 'Hace 1 hora', 'Hace 3 horas', 'Hace 6 horas', 'Hace 12 horas', 'Ayer', 'Hace 2 días']; return times[Math.floor(Math.random() * times.length)]; } getRandomScanGroup() { const groups = ['MangoScan', 'NeoFansub', 'KawaiiScans', 'DarkManga', 'SkyTranslations', 'MoonlitScans']; return groups[Math.floor(Math.random() * groups.length)]; } generateSkeletons(count, type = 'landscape') { const aspectClass = type === 'portrait' ? 'aspect-manga-portrait' : 'aspect-manga-landscape'; return Array(count).fill(`
`).join(''); } generateListSkeletons(count) { return Array(count).fill(`
`).join(''); } } // Initialize app when DOM is loaded document.addEventListener('DOMContentLoaded', () => { new MangaApp(); // Add scroll-based navbar effect const navbar = document.querySelector('manga-navbar'); if (navbar) { window.addEventListener('scroll', () => { const scrolled = window.pageYOffset > 50; navbar.shadowRoot.querySelector('nav').classList.toggle('bg-opacity-95', scrolled); navbar.shadowRoot.querySelector('nav').classList.toggle('backdrop-blur', scrolled); }); } }); // Handle navigation window.addEventListener('hashchange', () => { const hash = window.location.hash; if (hash.startsWith('#manga/')) { console.log('Navigate to manga:', hash); // In a real app, this would load manga detail page } });