Initial release 0.1.0
This commit is contained in:
commit
9f97d8407a
52 files changed
+6774
No files matched your search
@@ -0,0 +1,5 @@
|
||||
import { getPieces } from '#lib/server/previews.js';
|
||||
|
||||
export function load() {
|
||||
return { pieces: getPieces() };
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<script lang="ts">
|
||||
import PreviewNotice from '#lib/components/PreviewNotice.svelte';
|
||||
import { formatClock } from '#lib/format.js';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
let { data }: { data: PageData } = $props();
|
||||
let query = $state('');
|
||||
let filter = $state<'all' | 'ready' | 'preparing'>('all');
|
||||
let filteredPieces = $derived(
|
||||
data.pieces.filter((piece) => {
|
||||
const text =
|
||||
`${piece.title} ${piece.summary} ${piece.format} ${piece.topics.join(' ')}`.toLowerCase();
|
||||
return text.includes(query.toLowerCase()) && (filter === 'all' || piece.status === filter);
|
||||
})
|
||||
);
|
||||
|
||||
const statusLabel = {
|
||||
ready: 'Sendefertig',
|
||||
preparing: 'In Vorbereitung',
|
||||
inbox: 'Eingang',
|
||||
archived: 'Archiviert'
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head><title>Fundus | Sendewerk</title></svelte:head>
|
||||
|
||||
<div class="page-wrap">
|
||||
<header class="page-heading split-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Redaktioneller Fundus</p>
|
||||
<h1>Gute Stücke, sofort griffbereit.</h1>
|
||||
<p class="page-intro">
|
||||
Vorbereitete Ideen, Gespräche und Fundstücke für die nächste Sendung.
|
||||
</p>
|
||||
</div>
|
||||
<div class="heading-stat" aria-label={`${data.pieces.length} Inhalte im Beispieldatensatz`}>
|
||||
<strong>{data.pieces.length}</strong><span>Inhalte</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<PreviewNotice area="Fundus" />
|
||||
|
||||
<section class="library-toolbar" aria-label="Fundus durchsuchen und filtern">
|
||||
<label class="search-field">
|
||||
<span aria-hidden="true">⌕</span>
|
||||
<span class="sr-only">Fundus durchsuchen</span>
|
||||
<input bind:value={query} type="search" placeholder="Titel, Thema oder Format suchen" />
|
||||
</label>
|
||||
<div class="filter-tabs" aria-label="Status filtern">
|
||||
<button class:active={filter === 'all'} type="button" onclick={() => (filter = 'all')}
|
||||
>Alle</button
|
||||
>
|
||||
<button class:active={filter === 'ready'} type="button" onclick={() => (filter = 'ready')}
|
||||
>Sendefertig</button
|
||||
>
|
||||
<button
|
||||
class:active={filter === 'preparing'}
|
||||
type="button"
|
||||
onclick={() => (filter = 'preparing')}>In Arbeit</button
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{#if filteredPieces.length > 0}
|
||||
<div class="piece-grid">
|
||||
{#each filteredPieces as piece (piece.id)}
|
||||
<article class="piece-card" style={`--category: ${piece.categoryColor}`}>
|
||||
<div class="piece-card-topline">
|
||||
<span class="category-label"><i></i>{piece.category}</span>
|
||||
<span class:ready={piece.status === 'ready'} class="status-label"
|
||||
>{statusLabel[piece.status]}</span
|
||||
>
|
||||
</div>
|
||||
<h2>{piece.title}</h2>
|
||||
<p>{piece.summary}</p>
|
||||
<div class="piece-tags">
|
||||
<span>{piece.format}</span>
|
||||
{#each piece.topics as topic (topic)}<span>{topic}</span>{/each}
|
||||
</div>
|
||||
<footer>
|
||||
<span><b>{formatClock(piece.durationSeconds)}</b> geplant</span>
|
||||
<span>{piece.sourceCount} {piece.sourceCount === 1 ? 'Quelle' : 'Quellen'}</span>
|
||||
</footer>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="empty-state">
|
||||
<span aria-hidden="true">⌕</span>
|
||||
<h2>Kein passendes Stück</h2>
|
||||
<p>Suche oder Filter zurücksetzen, um wieder alle Beispieldaten zu sehen.</p>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
query = '';
|
||||
filter = 'all';
|
||||
}}>Filter zurücksetzen</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in new issue
Block a user