feat(tv): Serie als gesehen markieren - Button im Header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-03-16 11:28:10 +01:00
parent 764da40447
commit 406ba57a2d
2 changed files with 82 additions and 0 deletions

View file

@ -1814,6 +1814,31 @@ textarea.input-editing {
font-size: 0.75rem;
}
/* Serie als gesehen markieren - Button */
.tv-mark-series-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.5rem 1rem;
background: transparent;
border: 1px solid var(--border);
color: var(--text);
border-radius: var(--radius);
cursor: pointer;
font-size: 0.9rem;
transition: background 0.2s, border-color 0.2s;
}
.tv-mark-series-btn:hover,
.tv-mark-series-btn:focus {
background: var(--bg-hover);
border-color: var(--accent);
}
.tv-mark-series-btn.active {
background: var(--accent);
color: #000;
border-color: var(--accent);
}
/* --- Episode Card-Grid (Phase 5, Plex-Style) --- */
.tv-episode-grid {
display: grid;

View file

@ -63,6 +63,15 @@
<span class="watchlist-icon">{% if in_watchlist %}&#9829;{% else %}&#9825;{% endif %}</span>
<span class="watchlist-text">{{ t('series.watchlist') }}</span>
</button>
<!-- Serie als gesehen markieren -->
<button class="tv-mark-series-btn"
id="btn-mark-series"
data-focusable
data-series-id="{{ series.id }}"
onclick="markSeriesWatched(this)">
<span class="mark-series-icon">&#10003;</span>
<span class="mark-series-text">{{ t('status.mark_series') }}</span>
</button>
</div>
</div>
</div>
@ -254,6 +263,54 @@ function toggleWatched(videoId, btn) {
.catch(() => {});
}
function markSeriesWatched(btn) {
// Alle ungesehenen Episoden aus ALLEN Staffeln sammeln
const allCards = document.querySelectorAll('.tv-episode-tile:not(.tv-ep-seen)');
const ids = [];
allCards.forEach(function(card) {
var vid = card.dataset.videoId;
if (vid) ids.push(parseInt(vid));
});
if (ids.length === 0) return;
// Batch-Request an API (gleiche Methode wie markSeasonWatched)
Promise.all(ids.map(function(id) {
return fetch('/tv/api/watch-progress', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ video_id: id, position_sec: 100, duration_sec: 100 }),
});
})).then(function() {
// Alle Episoden-Cards als gesehen markieren
document.querySelectorAll('.tv-episode-tile').forEach(function(card) {
card.classList.add('tv-ep-seen');
var markBtn = card.querySelector('.tv-ep-tile-mark');
if (markBtn) markBtn.classList.add('active');
var thumb = card.querySelector('.tv-ep-thumb');
if (thumb && !thumb.querySelector('.tv-ep-watched')) {
var check = document.createElement('div');
check.className = 'tv-ep-watched';
check.innerHTML = '&#10003;';
thumb.appendChild(check);
}
});
// Alle Staffel-Tabs als komplett markieren
document.querySelectorAll('.tv-tab').forEach(function(tab) {
if (!tab.classList.contains('tv-tab-complete')) {
tab.classList.add('tv-tab-complete');
if (!tab.querySelector('.tv-tab-check')) {
var check = document.createElement('span');
check.className = 'tv-tab-check';
check.innerHTML = ' &#10003;';
tab.appendChild(check);
}
}
});
// Button-Zustand aendern
btn.classList.add('active');
}).catch(function() {});
}
function markSeasonWatched(seriesId, seasonNum) {
const season = document.getElementById('season-' + seasonNum);
if (!season) return;