feat: Version 1.10.0 — DB-Zugriff auf PHP-Bridge (DB4js_all.php) umgestellt

- lib/db.ts entfernt, mysql2-Abhängigkeit gestrichen
- lib/phpdb.ts: HTTP-Client für alle DB-Operationen via DB4js_all.php
- Alle API-Routen und Server Actions auf phpdb.ts umgestellt
- compose.yml / docker-compose.prod.yml: MySQL/phpMyAdmin-Container entfernt
- app/api/DB4js_all.php/route.ts: Proxy für Statistik-AJAX-Calls
- Statistik-Grafik liest ab 2026 live aus logbuch statt StatistikJahre
- PHP 7.3-Kompatibilität: str_contains → strpos

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 08:48:15 +02:00
parent c3f0b8f1e0
commit a75303f857
18 changed files with 291 additions and 532 deletions
+3 -61
View File
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { getSession } from '@/lib/session';
import * as phpdb from '@/lib/phpdb';
export async function GET(request: NextRequest) {
const session = await getSession();
@@ -10,66 +10,8 @@ export async function GET(request: NextRequest) {
const year = parseInt(searchParams.get('year') || String(new Date().getFullYear()), 10);
try {
const monthlyRows = await query(
'SELECT' +
' MONTH(Beginn) AS monat,' +
" COUNT(CASE WHEN ArtFuehrung IN ('RF','SF','SonF','PrF') THEN 1 END) AS tageFuehrungen," +
" COUNT(CASE WHEN ArtFuehrung = 'Beob' THEN 1 END) AS tageBeob," +
" COUNT(CASE WHEN ArtFuehrung = 'TD' THEN 1 END) AS tageTD," +
" COUNT(CASE WHEN ArtFuehrung = 'Sonst' THEN 1 END) AS tageSonst," +
" COUNT(CASE WHEN ArtFuehrung = 'BEOS' THEN 1 END) AS tageBEOS," +
" COUNT(CASE WHEN ArtFuehrung = 'ToT' THEN 1 END) AS tagesToT," +
" COUNT(CASE WHEN ArtFuehrung IN ('RF','SF','SonF','PrF','Beob','TD','Sonst','BEOS','ToT') THEN 1 END) AS tageGesamt," +
" SUM(CASE WHEN ArtFuehrung = 'RF' THEN Besucher ELSE 0 END) AS besucherRF," +
" SUM(CASE WHEN ArtFuehrung = 'SF' THEN Besucher ELSE 0 END) AS besucherSF," +
" SUM(CASE WHEN ArtFuehrung = 'SonF' THEN Besucher ELSE 0 END) AS besucherSonF," +
" SUM(CASE WHEN ArtFuehrung = 'PrF' THEN Besucher ELSE 0 END) AS besucherPrF," +
" SUM(CASE WHEN ArtFuehrung = 'ToT' THEN Besucher ELSE 0 END) AS besucherToT," +
" SUM(CASE WHEN ArtFuehrung IN ('RF','SF','SonF','PrF','ToT') THEN Besucher ELSE 0 END) AS besucherGesamt" +
' FROM logbuch' +
' WHERE YEAR(Beginn) = ?' +
' GROUP BY MONTH(Beginn)' +
' ORDER BY monat',
[year]
) as {
monat: number;
tageFuehrungen: number; tageBeob: number; tageTD: number; tageSonst: number; tageBEOS: number; tagesToT: number; tageGesamt: number;
besucherRF: number; besucherSF: number; besucherSonF: number; besucherPrF: number;
besucherToT: number; besucherGesamt: number;
}[];
const cumulativeRows = await query(
"SELECT SUM(CASE WHEN ArtFuehrung IN ('RF','SF','SonF','PrF','ToT') THEN Besucher ELSE 0 END) AS total" +
' FROM logbuch WHERE YEAR(Beginn) = ?',
[year]
) as { total: number | null }[];
const tageRows = await query(
"SELECT COUNT(*) AS tage FROM logbuch WHERE YEAR(Beginn) = ? AND ArtFuehrung IN ('RF','SF','SonF','PrF','Beob','TD','Sonst','BEOS','ToT')",
[year]
) as { tage: number }[];
return NextResponse.json({
monthly: monthlyRows.map((r) => ({
monat: Number(r.monat),
tageFuehrungen: Number(r.tageFuehrungen),
tageBeob: Number(r.tageBeob),
tageTD: Number(r.tageTD),
tageSonst: Number(r.tageSonst),
tageBEOS: Number(r.tageBEOS),
tagesToT: Number(r.tagesToT),
tageGesamt: Number(r.tageGesamt),
besucherRF: Number(r.besucherRF),
besucherSF: Number(r.besucherSF),
besucherSonF: Number(r.besucherSonF),
besucherPrF: Number(r.besucherPrF),
besucherToT: Number(r.besucherToT),
besucherGesamt: Number(r.besucherGesamt),
})),
cumulative: Number(cumulativeRows[0]?.total ?? 0),
tage: Number(tageRows[0]?.tage ?? 0),
year,
});
const result = await phpdb.getStatistik(year);
return NextResponse.json(result);
} catch (error) {
console.error('GET /api/statistik:', error);
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });