Übersicht: Vereins-Header mit Logo + nächste Termine statt redundanter Nav-Chips

This commit is contained in:
rene 2026-05-20 16:51:47 +02:00
parent f2906f5c60
commit 472979a91c

View file

@ -1,70 +1,144 @@
<script lang="ts">
import { pb } from '$lib/pb';
import Icon from '$lib/components/Icon.svelte';
import { onMount } from 'svelte';
import type { Verein, Termin } from '$lib/types';
const vereinsname = pb.authStore.record?.name ?? 'Dein Verein';
let verein = $state<Verein | null>(null);
let termine = $state<Termin[]>([]);
let loading = $state(true);
onMount(async () => {
const vid = pb.authStore.record?.verein_id as string;
const now = new Date().toISOString();
[verein, termine] = await Promise.all([
pb.collection('vereine').getOne<Verein>(vid),
pb.collection('termine').getList<Termin>(1, 3, {
filter: `beginn >= "${now}"`,
sort: 'beginn',
}).then(r => r.items),
]);
loading = false;
});
function formatTermin(t: Termin): string {
const d = new Date(t.beginn);
return d.toLocaleDateString('de-DE', { weekday: 'short', day: '2-digit', month: 'long' })
+ ' · ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) + ' Uhr'
+ (t.ort ? ' · ' + t.ort : '');
}
</script>
<svelte:head>
<title>Übersicht — vereins.haus</title>
</svelte:head>
<h1>Willkommen, {vereinsname}</h1>
{#if !loading && verein}
<div class="verein-header">
<img src="/favicon.svg" alt="" class="verein-icon" />
<div>
<h1>{verein.name}</h1>
{#if verein.ort}
<span class="verein-ort">{verein.ort}</span>
{/if}
</div>
</div>
<div class="cards">
<a href="/mitglieder" class="card">
<Icon name="users" size={40} />
<span class="card-label">Mitglieder</span>
</a>
<a href="/termine" class="card">
<Icon name="calendar" size={40} />
<span class="card-label">Termine</span>
</a>
<a href="/beitraege" class="card">
<Icon name="currency-eur" size={40} />
<span class="card-label">Beiträge</span>
</a>
<a href="/nachrichten" class="card">
<Icon name="envelope" size={40} />
<span class="card-label">Nachrichten</span>
</a>
</div>
{#if termine.length > 0}
<section>
<h2>Nächste Termine</h2>
<ul>
{#each termine as t (t.id)}
<li>
<span class="termin-titel">{t.titel}</span>
<span class="termin-wann">{formatTermin(t)}</span>
</li>
{/each}
</ul>
<a href="/termine" class="alle-link">Alle Termine →</a>
</section>
{:else}
<p class="hint">Noch keine Termine geplant.</p>
{/if}
{/if}
<style>
h1 {
font-size: 1.4rem;
font-weight: 700;
color: #1e293b;
.verein-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.25rem;
background: #0f172a;
border-radius: 14px;
margin-bottom: 1.5rem;
}
.cards {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.75rem;
.verein-icon {
width: 52px;
height: 52px;
border-radius: 12px;
flex-shrink: 0;
}
.card {
h1 {
font-size: 1.15rem;
font-weight: 700;
color: #fff;
margin: 0;
}
.verein-ort {
font-size: 0.82rem;
color: #94a3b8;
}
section {
background: #fff;
border: 1.5px solid #e2e8f0;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 1.5rem 1rem;
overflow: hidden;
}
h2 {
font-size: 0.72rem;
font-weight: 700;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 0.85rem 1rem 0.5rem;
margin: 0;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
gap: 0.15rem;
padding: 0.7rem 1rem;
border-top: 1px solid #f1f5f9;
}
.termin-titel { font-size: 0.92rem; font-weight: 600; color: #1e293b; }
.termin-wann { font-size: 0.78rem; color: #64748b; }
.alle-link {
display: block;
padding: 0.7rem 1rem;
border-top: 1px solid #f1f5f9;
font-size: 0.85rem;
color: #1e40af;
transition: border-color .15s, box-shadow .15s;
text-decoration: none;
font-weight: 500;
}
.card:hover {
border-color: #1e40af;
box-shadow: 0 2px 8px rgba(30,64,175,.1);
}
.card-label {
.hint {
color: #94a3b8;
font-size: 0.9rem;
font-weight: 600;
color: #1e293b;
text-align: center;
margin-top: 2rem;
}
</style>