feat(setup): add done button and integrate NFO scan into initialization

- Add /api/setup/unresolved/done endpoint to mark phase complete
- NFO scan now runs after series sync during initialization
- Middleware redirects to /login after setup complete (was /loading)
- Done button allows skipping folder resolution with redirect to NFO scan phase
This commit is contained in:
2026-06-06 23:47:48 +02:00
parent be7b210959
commit 275aeb4544
7 changed files with 332 additions and 31 deletions

View File

@@ -415,6 +415,36 @@
text-decoration: underline;
}
.done-btn {
background: var(--color-success);
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: var(--border-radius-md);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all var(--transition-duration);
display: none;
}
.done-btn:hover:not(:disabled) {
background: #27ae60;
transform: translateY(-2px);
}
.done-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.header-actions {
display: flex;
justify-content: center;
gap: 1rem;
margin-top: 1.5rem;
}
@media (max-width: 600px) {
.folder-input-row {
flex-direction: column;
@@ -439,6 +469,11 @@
</div>
<h1>Resolve Unresolved Series</h1>
<p>Some series couldn't be found automatically. Enter the provider key for each folder to complete setup.</p>
<div class="header-actions">
<button class="done-btn" id="done-btn" onclick="handleDone()">
<i class="fas fa-check"></i> Done
</button>
</div>
</div>
<div id="loading-state" class="loading-state">
@@ -754,6 +789,7 @@
const listEl = document.getElementById('folder-list');
const emptyEl = document.getElementById('empty-state');
const skipLink = document.getElementById('skip-link');
const doneBtn = document.getElementById('done-btn');
if (listEl.children.length === 0) {
listEl.style.display = 'none';
@@ -764,11 +800,54 @@
}
}
async function completeUnresolved() {
const token = localStorage.getItem('auth_token');
const res = await fetch('/api/setup/unresolved/done', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return res.json();
}
async function handleDone() {
const doneBtn = document.getElementById('done-btn');
doneBtn.disabled = true;
doneBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
try {
const result = await completeUnresolved();
if (result.status === 'success') {
showToast(result.message, 'success');
setTimeout(() => { window.location.href = '/loading'; }, 1000);
} else {
showToast(result.message || 'Failed to complete', 'error');
doneBtn.disabled = false;
doneBtn.innerHTML = '<i class="fas fa-check"></i> Done';
}
} catch (err) {
showToast('Server error. Please try again.', 'error');
doneBtn.disabled = false;
doneBtn.innerHTML = '<i class="fas fa-check"></i> Done';
}
}
// Show Done button when there are folders
function showDoneButton() {
const doneBtn = document.getElementById('done-btn');
doneBtn.style.display = 'inline-flex';
}
// Init
(async function init() {
const folders = await fetchUnresolved();
if (folders !== null) {
renderFolders(folders);
if (folders.length > 0) {
showDoneButton();
}
}
})();
</script>