142 lines
5.2 KiB
Svelte
142 lines
5.2 KiB
Svelte
<script lang="ts">
|
|
import { page } from '$app/state';
|
|
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 nicht angegeben';
|
|
return new Intl.DateTimeFormat('de-DE', {
|
|
timeZone: 'Europe/Berlin',
|
|
dateStyle: 'full',
|
|
timeStyle: 'short'
|
|
}).format(new Date(value));
|
|
}
|
|
</script>
|
|
|
|
<svelte:head><title>Streamfreigabe | Sendewerk</title></svelte:head>
|
|
|
|
<main class="share-page">
|
|
{#if data.status === 'unavailable'}
|
|
<section class="quiet-panel share-gate">
|
|
<p class="eyebrow">Lesefreigabe</p>
|
|
<h1>Nicht verfügbar</h1>
|
|
<p>Dieser Link ist ungültig, abgelaufen oder wurde widerrufen.</p>
|
|
</section>
|
|
{:else if data.status === 'password'}
|
|
<section class="quiet-panel share-gate">
|
|
<p class="eyebrow">Geschützte Lesefreigabe</p>
|
|
<h1>Passwort erforderlich</h1>
|
|
{#if form?.error}<div class="form-message error" role="alert">{form.error}</div>{/if}
|
|
<form method="POST" action="?/password" class="compact-form">
|
|
<label
|
|
>Passwort<input
|
|
name="password"
|
|
type="password"
|
|
required
|
|
autocomplete="current-password"
|
|
/></label
|
|
>
|
|
<button class="primary-button" type="submit">Stream öffnen</button>
|
|
</form>
|
|
</section>
|
|
{:else}
|
|
<header class="share-heading">
|
|
<p class="eyebrow">
|
|
{data.share.isCompleted ? 'Abgeschlossener Stream' : 'Aktuelle Streamplanung'} · Nur lesen
|
|
</p>
|
|
<h1>{data.share.title}</h1>
|
|
<p>{berlinDate(data.share.startsAtUtc)} Uhr</p>
|
|
</header>
|
|
<div class="shared-rundown">
|
|
{#each data.share.sections as section (section)}
|
|
<section class="quiet-panel shared-section">
|
|
<header>
|
|
<div>
|
|
{#if section.category}<small
|
|
style={`--tax-color: ${section.categoryColor ?? '#67dde8'}`}
|
|
>{section.category}</small
|
|
>{/if}
|
|
<h2>{section.name}</h2>
|
|
</div>
|
|
{#if section.explicitDurationSeconds !== null}<span
|
|
>{formatDuration(section.explicitDurationSeconds)}</span
|
|
>{/if}
|
|
</header>
|
|
{#each section.usages as usage (usage)}
|
|
<article class="shared-usage">
|
|
<div class="shared-usage-heading">
|
|
<div>
|
|
<small
|
|
>{usage.status === 'done'
|
|
? 'Gesendet'
|
|
: usage.status === 'skipped'
|
|
? 'Übersprungen'
|
|
: 'Offen'}</small
|
|
>
|
|
<h3>{usage.title}</h3>
|
|
</div>
|
|
<span>{formatDuration(usage.actualDurationSeconds || usage.durationSeconds)}</span>
|
|
</div>
|
|
{#if usage.media}<img
|
|
src={`${page.url.pathname}/media/${usage.media.id}`}
|
|
alt={usage.media.alt_text}
|
|
/>{/if}
|
|
{#if 'introHtml' in usage && usage.introHtml}<div class="shared-copy">
|
|
<strong>Einleitung</strong>
|
|
<!-- HTML is produced exclusively by the server-side allowlist sanitizer. -->
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
<div>{@html usage.introHtml}</div>
|
|
</div>{/if}
|
|
{#if 'moderationHtml' in usage && usage.moderationHtml}<div class="shared-copy">
|
|
<strong>Moderation</strong>
|
|
<!-- HTML is produced exclusively by the server-side allowlist sanitizer. -->
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
<div>{@html usage.moderationHtml}</div>
|
|
</div>{/if}
|
|
{#if 'interactionHtml' in usage && usage.interactionHtml}<div class="shared-copy">
|
|
<strong>Interaktion</strong>
|
|
<!-- HTML is produced exclusively by the server-side allowlist sanitizer. -->
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
<div>{@html usage.interactionHtml}</div>
|
|
</div>{/if}
|
|
{#if 'transitionHtml' in usage && usage.transitionHtml}<div class="shared-copy">
|
|
<strong>Überleitung</strong>
|
|
<!-- HTML is produced exclusively by the server-side allowlist sanitizer. -->
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
<div>{@html usage.transitionHtml}</div>
|
|
</div>{/if}
|
|
{#if 'researchHtml' in usage && usage.researchHtml}<details>
|
|
<summary>Recherche</summary>
|
|
<!-- HTML is produced exclusively by the server-side allowlist sanitizer. -->
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
<div class="shared-copy">{@html usage.researchHtml}</div>
|
|
</details>{/if}
|
|
{#if 'sources' in usage && usage.sources?.length}<details>
|
|
<summary>Quellen</summary>
|
|
<ul>
|
|
{#each usage.sources ?? [] as source (source)}<li>
|
|
<!-- External source URLs are validated and stored server-side. -->
|
|
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
|
|
<a href={source.url} rel="noreferrer">{source.label || source.url}</a>
|
|
</li>{/each}
|
|
</ul>
|
|
</details>{/if}
|
|
{#if 'tools' in usage && usage.tools?.length}<details>
|
|
<summary>Werkzeuge</summary>
|
|
<ul>
|
|
{#each usage.tools ?? [] as tool (tool)}<li>
|
|
<strong>{tool.name}</strong>{#if tool.note}
|
|
· {tool.note}{/if}
|
|
</li>{/each}
|
|
</ul>
|
|
</details>{/if}
|
|
</article>
|
|
{/each}
|
|
</section>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</main>
|