import { filme, serien, weiterschauen, naechsteFolgen, type Film, type Serie, type Angefangen, } from '../api'; import { esc, plakat, leer, fehlerzeile, anteil, verbleibend } from '../util'; type Art = 'filme' | 'serien'; /** Die Startseite: waagerechte Reihen, wie bei Plex. * * Oben, was angefangen ist — darum geht man schliesslich hin. Darunter die * Mediathek. Eine Reihe, die nichts enthält, wird gar nicht erst gezeigt. */ export function startseite(oeffnen: (art: Art, id: string) => void): HTMLElement { const wurzel = document.createElement('div'); wurzel.innerHTML = '
'; void (async () => { try { const [weiter, naechste, f, s] = await Promise.all([ weiterschauen(), naechsteFolgen(), filme({ take: 24 }), serien({ take: 24 }), ]); wurzel.innerHTML = ''; if (f.total === 0 && s.total === 0) { wurzel.appendChild(leer('Noch nichts da. Lege unter Verwaltung eine Bibliothek an ' + 'und starte einen Scan.')); return; } if (weiter.items.length) wurzel.appendChild(angefangenReihe('Weiterschauen', weiter)); if (naechste.items.length) wurzel.appendChild(angefangenReihe('Nächste Folge', naechste)); if (f.total > 0) wurzel.appendChild(reihe(`Filme · ${f.total}`, f.items, 'filme')); if (s.total > 0) wurzel.appendChild(reihe(`Serien · ${s.total}`, s.items, 'serien')); } catch (fehler) { wurzel.innerHTML = ''; wurzel.appendChild(fehlerzeile((fehler as Error).message)); } })(); /** Eine Reihe aus Einträgen mit Stand — Filme und Folgen gemischt. */ function angefangenReihe(titel: string, seite: { items: Angefangen[] }): HTMLElement { const bereich = document.createElement('section'); bereich.className = 'reihe'; const h = document.createElement('h2'); h.textContent = titel; const streifen = document.createElement('div'); streifen.className = 'strip'; seite.items.forEach(eintrag => { const k = document.createElement('button'); k.className = 'card'; k.appendChild(plakat(eintrag.posterImage, eintrag.title, anteil(eintrag.state))); const unten = document.createElement('div'); unten.className = 'rowline'; // Bei einer Folge oben die Serie, darunter wo man ist — eine Folge // ohne ihre Serie zu nennen hilft niemandem beim Wiedererkennen. const zweite = eintrag.kind === 'episode' ? `S${String(eintrag.season).padStart(2, '0')}E${String(eintrag.episode).padStart(2, '0')}` + (eintrag.subTitle ? ` · ${eintrag.subTitle}` : '') : verbleibend(eintrag.state); unten.innerHTML = `${esc(eintrag.title)}` + `${esc(zweite)}`; k.appendChild(unten); // Angesprungen wird der Titel, nicht die Folge: von dort kommt man zur // Folge, umgekehrt fehlte der Zusammenhang. k.onclick = () => oeffnen(eintrag.kind === 'movie' ? 'filme' : 'serien', eintrag.id); streifen.appendChild(k); }); bereich.append(h, streifen); return bereich; } function reihe(titel: string, eintraege: (Film | Serie)[], art: Art): HTMLElement { const bereich = document.createElement('section'); bereich.className = 'reihe'; const h = document.createElement('h2'); h.textContent = titel; const streifen = document.createElement('div'); streifen.className = 'strip'; eintraege.forEach(eintrag => { const k = document.createElement('button'); k.className = 'card'; const bild = plakat( eintrag.posterImage, eintrag.title, 'state' in eintrag ? anteil(eintrag.state) : null); if ('unwatchedCount' in eintrag && eintrag.unwatchedCount > 0) { const plakette = document.createElement('span'); plakette.className = 'offen'; plakette.textContent = String(eintrag.unwatchedCount); bild.appendChild(plakette); } k.appendChild(bild); const unten = document.createElement('div'); unten.className = 'rowline'; unten.innerHTML = `${esc(eintrag.title)}` + `${esc(eintrag.year ?? '')}`; k.appendChild(unten); k.onclick = () => oeffnen(art, eintrag.id); streifen.appendChild(k); }); bereich.append(h, streifen); return bereich; } return wurzel; }