Files
sendewerk/src/routes/freigabe/[token]/+page.svelte
T
2026-10-27 14:57:17 +01:00

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>