105 lines
3.0 KiB
Svelte
105 lines
3.0 KiB
Svelte
<script lang="ts">
|
||
import { resolve } from '$app/paths';
|
||
import { formatDuration } from '#lib/format.js';
|
||
import type { PageProps } from './$types';
|
||
|
||
let { data, form }: PageProps = $props();
|
||
|
||
function berlinDate(value: string | null) {
|
||
if (!value) return 'Termin offen';
|
||
return new Intl.DateTimeFormat('de-DE', {
|
||
timeZone: 'Europe/Berlin',
|
||
dateStyle: 'medium',
|
||
timeStyle: 'short'
|
||
}).format(new Date(value));
|
||
}
|
||
</script>
|
||
|
||
<svelte:head><title>Sendungen | Sendewerk</title></svelte:head>
|
||
|
||
<div class="page-wrap shows-page">
|
||
<header class="page-heading">
|
||
<div>
|
||
<h1>Sendungen</h1>
|
||
<p class="page-intro">Streams aus Fundus-Pieces und freien Abschnitten zusammenstellen.</p>
|
||
</div>
|
||
</header>
|
||
|
||
{#if form?.error}<div class="form-message error" role="alert">{form.error}</div>{/if}
|
||
|
||
<section class="show-create-panel">
|
||
<div>
|
||
<p class="eyebrow">Neuen Stream planen</p>
|
||
<h2>Leer starten oder Ablauf übernehmen</h2>
|
||
</div>
|
||
<form method="POST" action="?/create" class="show-create-form">
|
||
<label
|
||
>Titel<input
|
||
name="title"
|
||
required
|
||
maxlength="200"
|
||
value={form?.title ?? ''}
|
||
placeholder="Nächste heinzlive-Sendung"
|
||
/></label
|
||
>
|
||
<label
|
||
>Termin<input name="startsAt" type="datetime-local" value={form?.startsAt ?? ''} /></label
|
||
>
|
||
<label
|
||
>Ausgangspunkt<select name="templateId" value={form?.templateId ?? ''}
|
||
><option value="">Leer starten</option
|
||
>{#each data.templates as template (template.id)}<option value={template.id}
|
||
>{template.name}</option
|
||
>{/each}</select
|
||
></label
|
||
>
|
||
<button class="primary-button" type="submit">Sendung anlegen</button>
|
||
</form>
|
||
<div class="template-notes">
|
||
{#each data.templates as template (template.id)}<p>
|
||
<strong>{template.name}:</strong>
|
||
{template.description}
|
||
</p>{/each}
|
||
</div>
|
||
</section>
|
||
|
||
<section class="show-library" aria-labelledby="show-library-title">
|
||
<header>
|
||
<h2 id="show-library-title">Geplante Sendungen</h2>
|
||
<span>{data.shows.length}</span>
|
||
</header>
|
||
{#if data.shows.length}
|
||
<div class="show-card-list">
|
||
{#each data.shows as show (show.id)}
|
||
<a class="show-card" href={resolve('/sendungen/[id]', { id: show.id })}>
|
||
<div>
|
||
<span class={`show-state ${show.status}`}
|
||
>{show.status === 'ready'
|
||
? 'Bereit'
|
||
: show.status === 'draft'
|
||
? 'Entwurf'
|
||
: show.status === 'live'
|
||
? 'Live'
|
||
: 'Abgeschlossen'}</span
|
||
>
|
||
<h3>{show.title}</h3>
|
||
<p>{berlinDate(show.startsAtUtc)} Uhr</p>
|
||
</div>
|
||
<div class="show-card-facts">
|
||
<span><strong>{show.sectionCount}</strong> Abschnitte</span><span
|
||
><strong>{formatDuration(show.totalDurationSeconds)}</strong> Planzeit</span
|
||
><b aria-hidden="true">→</b>
|
||
</div>
|
||
</a>
|
||
{/each}
|
||
</div>
|
||
{:else}
|
||
<div class="empty-state">
|
||
<span aria-hidden="true">+</span>
|
||
<h2>Noch keine Sendung</h2>
|
||
<p>Oben kann der erste Stream geplant werden.</p>
|
||
</div>
|
||
{/if}
|
||
</section>
|
||
</div>
|