feat: Anleitung-Button im Footer + Statistik-Effect-Fix

- Footer: 3-Spalten-Layout mit 'Anleitung'-Button in der Mitte (Link auf /anleitung.html)
- anleitung.html: 'Zurück zum Logbuch'-Button oben (beim Drucken ausgeblendet)
- Statistik: synchrones setState im Effect durch abgeleiteten loading/error-State ersetzt; Fetch-Abbruch mit cancelled-Flag; as any durch ArtFuehrung-Cast ersetzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 16:46:38 +02:00
parent 42a2651f8e
commit d56ebb229d
4 changed files with 43 additions and 11 deletions
+12 -8
View File
@@ -1,7 +1,7 @@
'use client';
import { useEffect, useMemo, useState } from 'react';
import type { Kuppel } from '@/types/logbuch';
import type { ArtFuehrung, Kuppel } from '@/types/logbuch';
import { artLabel } from '@/types/logbuch';
interface MonthlyRow {
@@ -33,16 +33,20 @@ interface Props {
export default function Statistik({ kuppel }: Props) {
const [year, setYear] = useState(new Date().getFullYear());
const [data, setData] = useState<StatsData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [fetchError, setFetchError] = useState<{ year: number; kuppel: Kuppel } | null>(null);
const error = fetchError?.year === year && fetchError?.kuppel === kuppel
? 'Fehler beim Laden der Statistik.'
: '';
const loading = !error && (!data || data.year !== year || data.kuppel !== kuppel);
useEffect(() => {
setLoading(true);
setError('');
let cancelled = false;
fetch(`/api/statistik?kuppel=${encodeURIComponent(kuppel)}&year=${year}`)
.then((r) => { if (!r.ok) throw new Error(); return r.json(); })
.then((d: StatsData) => { setData(d); setLoading(false); })
.catch(() => { setError('Fehler beim Laden der Statistik.'); setLoading(false); });
.then((d: StatsData) => { if (!cancelled) { setData(d); setFetchError(null); } })
.catch(() => { if (!cancelled) setFetchError({ year, kuppel }); });
return () => { cancelled = true; };
}, [kuppel, year]);
const { arten, matrix, monatTotal, artTotal, grandTotal, anzahlTotal } = useMemo(() => {
@@ -111,7 +115,7 @@ export default function Statistik({ kuppel }: Props) {
<th className={headCls}>Monat</th>
<th className={headCls}>Führungen</th>
{arten.map((art) => (
<th key={art} className={headCls}>{artLabel(art as any) || art}</th>
<th key={art} className={headCls}>{artLabel(art as ArtFuehrung)}</th>
))}
<th className={headCls}>Gesamt</th>
</tr>