added local manga, todo: novels
This commit is contained in:
89
desktop/src/scripts/local-library-books.js
Normal file
89
desktop/src/scripts/local-library-books.js
Normal file
@@ -0,0 +1,89 @@
|
||||
let activeFilter = 'all';
|
||||
let activeSort = 'az';
|
||||
let isLocalMode = false;
|
||||
let localEntries = [];
|
||||
|
||||
function toggleLibraryMode() {
|
||||
isLocalMode = !isLocalMode;
|
||||
const btn = document.getElementById('library-mode-btn');
|
||||
const onlineContent = document.getElementById('online-content');
|
||||
const localContent = document.getElementById('local-content');
|
||||
|
||||
if (isLocalMode) {
|
||||
btn.classList.add('active');
|
||||
onlineContent.classList.add('hidden');
|
||||
localContent.classList.remove('hidden');
|
||||
loadLocalEntries();
|
||||
} else {
|
||||
btn.classList.remove('active');
|
||||
onlineContent.classList.remove('hidden');
|
||||
localContent.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadLocalEntries() {
|
||||
const grid = document.getElementById('local-entries-grid');
|
||||
grid.innerHTML = '<div class="skeleton-card"></div>'.repeat(6);
|
||||
|
||||
try {
|
||||
// Cambiado a endpoint de libros
|
||||
const response = await fetch('/api/library/manga');
|
||||
const entries = await response.json();
|
||||
localEntries = entries;
|
||||
|
||||
if (entries.length === 0) {
|
||||
grid.innerHTML = '<p style="grid-column: 1/-1; text-align: center; color: var(--color-text-secondary); padding: 3rem;">No books found in your local library.</p>';
|
||||
return;
|
||||
}
|
||||
renderLocalEntries(entries);
|
||||
} catch (err) {
|
||||
grid.innerHTML = '<p style="grid-column: 1/-1; text-align: center; color: var(--color-danger); padding: 3rem;">Error loading local books.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
function renderLocalEntries(entries) {
|
||||
const grid = document.getElementById('local-entries-grid');
|
||||
grid.innerHTML = entries.map(entry => {
|
||||
const title = entry.metadata?.title?.romaji || entry.metadata?.title?.english || entry.id;
|
||||
const cover = entry.metadata?.coverImage?.extraLarge || '/public/assets/placeholder.jpg';
|
||||
const chapters = entry.metadata?.chapters || '??';
|
||||
|
||||
return `
|
||||
<div class="local-card" onclick="viewLocalEntry(${entry.metadata?.id || 'null'})">
|
||||
<div class="card-img-wrap">
|
||||
<img src="${cover}" alt="${title}" loading="lazy">
|
||||
</div>
|
||||
<div class="local-card-info">
|
||||
<div class="local-card-title">${title}</div>
|
||||
<p style="font-size: 0.85rem; color: var(--color-text-secondary); margin: 0;">
|
||||
${chapters} Chapters
|
||||
</p>
|
||||
<div class="match-status ${entry.matched ? 'status-linked' : 'status-unlinked'}">
|
||||
${entry.matched ? '● Linked' : '○ Unlinked'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
async function scanLocalLibrary() {
|
||||
const btnText = document.getElementById('scan-text');
|
||||
btnText.innerText = "Scanning...";
|
||||
try {
|
||||
// Asumiendo que el scan de libros usa este query param
|
||||
const response = await fetch('/api/library/scan?mode=incremental', { method: 'POST' });
|
||||
if (response.ok) {
|
||||
await loadLocalEntries();
|
||||
if (window.NotificationUtils) NotificationUtils.show('Library scanned!', 'success');
|
||||
}
|
||||
} catch (err) {
|
||||
if (window.NotificationUtils) NotificationUtils.show('Scan failed', 'error');
|
||||
} finally {
|
||||
btnText.innerText = "Scan Library";
|
||||
}
|
||||
}
|
||||
|
||||
function viewLocalEntry(id) {
|
||||
if (id) window.location.href = `/book/${id}`;
|
||||
}
|
||||
Reference in New Issue
Block a user