From 8fabf7bb300c7b1d6b1a5dba9576581e28409ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20X=2E=20F=C3=BCrst?= Date: Wed, 13 May 2026 21:19:06 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Druck=20=E2=80=93=20kleinere=20Schrift?= =?UTF-8?q?=20und=20chronologische=20Reihenfolge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beim Drucken wird die Tabellenschrift auf 0.72rem verkleinert. Der Drucken-Button lädt vorab alle Einträge des Monats in aufsteigender Reihenfolge (älteste zuerst) und ruft dann window.print() auf. API unterstützt jetzt order=asc. Co-Authored-By: Claude Sonnet 4.6 --- app/MainClient.tsx | 9 -------- app/api/logbuch/route.ts | 8 ++++---- app/globals.css | 3 +++ components/LogbuchList.tsx | 42 +++++++++++++++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/app/MainClient.tsx b/app/MainClient.tsx index 8345bbf..6165638 100644 --- a/app/MainClient.tsx +++ b/app/MainClient.tsx @@ -150,15 +150,6 @@ export default function MainClient({ kuerzel, beoId, beoName, role }: Props) { {/* Liste-Tab: vollständige Liste */} {activeTab === 'liste' && (
-
- Einträge {activeKuppel}-Kuppel - -
Sternwarte Welzheim — Logbuch {activeKuppel}-Kuppel
Ausdruck vom {new Date().toLocaleDateString('de-DE')}
diff --git a/app/api/logbuch/route.ts b/app/api/logbuch/route.ts index bf73da3..fc43f8d 100644 --- a/app/api/logbuch/route.ts +++ b/app/api/logbuch/route.ts @@ -21,17 +21,17 @@ const LIST_SQL = ' LEFT JOIN logbuch_objekte lo ON lo.LogbuchID = l.ID' + ' LEFT JOIN objekte o ON o.ID = lo.ObjektID' + ' WHERE l.Kuppel = ?' + - ' GROUP BY l.ID' + - ' ORDER BY l.Beginn DESC'; + ' GROUP BY l.ID'; export async function GET(request: NextRequest) { const session = await getSession(); if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 }); const { searchParams } = new URL(request.url); const kuppel = searchParams.get('kuppel') || 'West'; - const limit = Math.min(parseInt(searchParams.get('limit') || '10') || 10, 100); + const limit = Math.min(parseInt(searchParams.get('limit') || '10') || 10, 500); const offset = Math.max(0, parseInt(searchParams.get('offset') || '0') || 0); const month = searchParams.get('month') || ''; + const order = searchParams.get('order') === 'asc' ? 'ASC' : 'DESC'; let listWhere = 'WHERE l.Kuppel = ?'; let countWhere = 'WHERE Kuppel = ?'; @@ -50,7 +50,7 @@ export async function GET(request: NextRequest) { try { const [countRows, entries] = await Promise.all([ query('SELECT COUNT(*) AS total FROM logbuch ' + countWhere, params) as Promise<{ total: number }[]>, - query(LIST_SQL.replace('WHERE l.Kuppel = ?', listWhere) + ` LIMIT ${limit} OFFSET ${offset}`, params), + query(LIST_SQL.replace('WHERE l.Kuppel = ?', listWhere) + ` ORDER BY l.Beginn ${order} LIMIT ${limit} OFFSET ${offset}`, params), ]); return NextResponse.json({ entries, total: (countRows as unknown as { total: number }[])[0]?.total ?? 0 }); } catch (error) { diff --git a/app/globals.css b/app/globals.css index 8a4a22a..5d748db 100644 --- a/app/globals.css +++ b/app/globals.css @@ -33,4 +33,7 @@ body { body { background: white; } + table { + font-size: 0.72rem; + } } diff --git a/components/LogbuchList.tsx b/components/LogbuchList.tsx index 0afdac0..2787c5c 100644 --- a/components/LogbuchList.tsx +++ b/components/LogbuchList.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import type { Kuppel, LogbuchEintrag } from '@/types/logbuch'; interface Props { @@ -58,6 +58,8 @@ export default function LogbuchList({ kuppel, refreshKey, onEdit, limit = 10, co const [loading, setLoading] = useState(true); const [deleteId, setDeleteId] = useState(null); const [error, setError] = useState(''); + const [printEntries, setPrintEntries] = useState(null); + const printPending = useRef(false); useEffect(() => { setPage(0); }, [kuppel, refreshKey, month]); @@ -72,6 +74,27 @@ export default function LogbuchList({ kuppel, refreshKey, onEdit, limit = 10, co .catch(() => { setError('Fehler beim Laden.'); setLoading(false); }); }, [kuppel, refreshKey, limit, page, month]); + useEffect(() => { + function onAfterPrint() { setPrintEntries(null); } + window.addEventListener('afterprint', onAfterPrint); + return () => window.removeEventListener('afterprint', onAfterPrint); + }, []); + + useEffect(() => { + if (printPending.current && printEntries !== null) { + printPending.current = false; + window.print(); + } + }, [printEntries]); + + async function handlePrint() { + const url = `/api/logbuch?kuppel=${encodeURIComponent(kuppel)}&limit=500&offset=0` + + (month ? `&month=${encodeURIComponent(month)}` : '') + '&order=asc'; + const data = await fetch(url).then((r) => r.json()); + printPending.current = true; + setPrintEntries(data.entries); + } + async function confirmDelete(id: number) { try { const res = await fetch(`/api/logbuch/${id}`, { method: 'DELETE' }); @@ -129,8 +152,21 @@ export default function LogbuchList({ kuppel, refreshKey, onEdit, limit = 10, co if (loading) return <>{monthNav}
Lade Einträge...
; if (error) return <>{monthNav}
{error}
; + const displayEntries = printEntries ?? entries; + return (
+ {!compact && ( +
+ Einträge {kuppel}-Kuppel + +
+ )} {monthNav} {printHeader}
@@ -156,13 +192,13 @@ export default function LogbuchList({ kuppel, refreshKey, onEdit, limit = 10, co - {entries.length === 0 ? ( + {displayEntries.length === 0 ? ( Keine Einträge für {monthLabel(month)}. - ) : entries.map((e) => ( + ) : displayEntries.map((e) => ( {formatDate(e.Beginn, compact)} {compact ? (