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:
@@ -0,0 +1,24 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
const DB_URL = (process.env.PHP_DB_URL ?? 'http://localhost:8080/DB4js_all.php')
|
||||
.replace(/\?.*$/, '');
|
||||
|
||||
async function proxy(req: Request) {
|
||||
const search = new URL(req.url).search;
|
||||
const target = DB_URL + search;
|
||||
const isReadOnly = req.method === 'GET' || req.method === 'HEAD';
|
||||
const upstream = await fetch(target, {
|
||||
method: req.method,
|
||||
headers: { 'content-type': req.headers.get('content-type') ?? 'application/x-www-form-urlencoded' },
|
||||
body: isReadOnly ? undefined : await req.arrayBuffer(),
|
||||
cache: 'no-store',
|
||||
});
|
||||
const body = await upstream.arrayBuffer();
|
||||
return new NextResponse(Buffer.from(body), {
|
||||
status: upstream.status,
|
||||
headers: { 'content-type': upstream.headers.get('content-type') ?? 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
export const GET = proxy;
|
||||
export const POST = proxy;
|
||||
@@ -1,14 +1,12 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { query } from '@/lib/db';
|
||||
import { getSession } from '@/lib/session';
|
||||
import * as phpdb from '@/lib/phpdb';
|
||||
|
||||
export async function GET() {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 });
|
||||
try {
|
||||
const rows = await query(
|
||||
'SELECT id AS ID, `kürzel` AS Kuerzel, CONCAT(IFNULL(vorname, \'\'), IF(vorname IS NOT NULL, \' \', \'\'), name) AS Name FROM beos WHERE `kürzel` IS NOT NULL AND FIND_IN_SET(\'guide\', role) > 0 ORDER BY name ASC'
|
||||
) as { ID: number; Kuerzel: string; Name: string }[];
|
||||
const rows = await phpdb.getBeos();
|
||||
return NextResponse.json(rows);
|
||||
} catch (error) {
|
||||
console.error('GET /api/beos:', error);
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { query } from '@/lib/db';
|
||||
import { getSession } from '@/lib/session';
|
||||
import * as phpdb from '@/lib/phpdb';
|
||||
|
||||
export interface FahrkostenRow {
|
||||
ID: number;
|
||||
Kuerzel: string;
|
||||
Name: string;
|
||||
Anzahl: number;
|
||||
}
|
||||
|
||||
const EXCLUDED = "'PrF','Beob','BEOS','TD','ToT'";
|
||||
export type { FahrkostenRow } from '@/lib/phpdb';
|
||||
|
||||
export async function GET(req: Request) {
|
||||
const session = await getSession();
|
||||
@@ -22,18 +15,7 @@ export async function GET(req: Request) {
|
||||
}
|
||||
|
||||
try {
|
||||
const rows = await query(
|
||||
'SELECT b.id AS ID, b.`kürzel` AS Kuerzel,' +
|
||||
' CONCAT(IFNULL(b.vorname, \'\'), IF(b.vorname IS NOT NULL, \' \', \'\'), b.name) AS Name,' +
|
||||
' COUNT(DISTINCT l.ID) AS Anzahl' +
|
||||
' FROM beos b' +
|
||||
' JOIN logbuch_beos lb ON lb.BeoID = b.id' +
|
||||
' JOIN logbuch l ON l.ID = lb.LogbuchID' +
|
||||
' WHERE l.Beginn >= ? AND l.ArtFuehrung NOT IN (' + EXCLUDED + ')' +
|
||||
' GROUP BY b.id, b.`kürzel`, b.name, b.vorname' +
|
||||
' ORDER BY b.name ASC',
|
||||
[ab + ' 00:00:00']
|
||||
) as FahrkostenRow[];
|
||||
const rows = await phpdb.getFahrkosten(ab);
|
||||
return NextResponse.json(rows);
|
||||
} catch (error) {
|
||||
console.error('GET /api/fahrkosten:', error);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { query, getPool } from '@/lib/db';
|
||||
import { getSession } from '@/lib/session';
|
||||
import { triggerBackup } from '@/lib/backup';
|
||||
import type { SelectedObjekt } from '@/types/logbuch';
|
||||
import * as phpdb from '@/lib/phpdb';
|
||||
|
||||
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const session = await getSession();
|
||||
@@ -12,66 +11,25 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
||||
const logbuchId = parseInt(id);
|
||||
|
||||
try {
|
||||
const existingRows = await query('SELECT ID FROM logbuch WHERE ID = ?', [logbuchId]) as { ID: number }[];
|
||||
if (existingRows.length === 0) {
|
||||
return NextResponse.json({ error: 'Eintrag nicht gefunden' }, { status: 404 });
|
||||
}
|
||||
|
||||
const isAdmin = session.role?.includes('admin');
|
||||
const beoRows = await query('SELECT COUNT(*) AS cnt FROM logbuch_beos WHERE LogbuchID = ? AND BeoID = ?', [logbuchId, session.beoId]) as { cnt: number }[];
|
||||
const isBeo = (beoRows[0]?.cnt ?? 0) > 0;
|
||||
|
||||
if (!isAdmin && !isBeo) {
|
||||
return NextResponse.json({ error: 'Keine Berechtigung zum Ändern dieses Eintrags' }, { status: 403 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { Kuppel, ArtFuehrung, SonderName, Beginn, Ende, Besucher, beoIds, objekte, Bemerkungen, Wetter } = body;
|
||||
|
||||
await getPool().execute(
|
||||
'UPDATE logbuch SET Kuppel=?, ArtFuehrung=?, SonderName=?, Beginn=?, Ende=?, Besucher=?,' +
|
||||
' Bemerkungen=?, WetterTemp=?, WetterFeuchte=?, WetterDruck=? WHERE ID=?',
|
||||
[
|
||||
Kuppel, ArtFuehrung, SonderName || null, Beginn, Ende,
|
||||
Besucher ?? 0,
|
||||
Bemerkungen?.slice(0, 500) || null,
|
||||
Wetter?.temp ?? null,
|
||||
Wetter?.feuchte ?? null,
|
||||
Wetter?.druck ?? null,
|
||||
logbuchId,
|
||||
]
|
||||
);
|
||||
|
||||
await query('DELETE FROM logbuch_beos WHERE LogbuchID = ?', [logbuchId]);
|
||||
await query('DELETE FROM logbuch_objekte WHERE LogbuchID = ?', [logbuchId]);
|
||||
|
||||
for (const beoId of (beoIds as number[]) || []) {
|
||||
await query('INSERT INTO logbuch_beos (LogbuchID, BeoID) VALUES (?, ?)', [logbuchId, beoId]);
|
||||
}
|
||||
|
||||
for (const obj of (objekte as SelectedObjekt[]) || []) {
|
||||
let objektId = obj.ID;
|
||||
if (!objektId) {
|
||||
const existing = await query('SELECT ID, Name FROM objekte WHERE LOWER(Name) = LOWER(?)', [obj.Name]) as { ID: number; Name: string }[];
|
||||
if (existing[0]) {
|
||||
objektId = existing[0].ID;
|
||||
} else {
|
||||
const [ins] = await getPool().execute(
|
||||
'INSERT INTO objekte (Name) VALUES (?)', [obj.Name]
|
||||
) as [{ insertId: number }, unknown];
|
||||
objektId = ins.insertId;
|
||||
}
|
||||
}
|
||||
await query('UPDATE objekte SET LastUsed = NOW() WHERE ID = ?', [objektId]);
|
||||
await query(
|
||||
'INSERT INTO logbuch_objekte (LogbuchID, ObjektID) VALUES (?, ?)',
|
||||
[logbuchId, objektId]
|
||||
);
|
||||
}
|
||||
await phpdb.updateLogbuch(logbuchId, session.beoId, session.role ?? '', {
|
||||
Kuppel, ArtFuehrung, SonderName, Beginn, Ende,
|
||||
Besucher: Besucher ?? 0,
|
||||
beoIds: beoIds ?? [],
|
||||
objekte: objekte ?? [],
|
||||
Bemerkungen: Bemerkungen ?? null,
|
||||
Wetter: Wetter ?? null,
|
||||
});
|
||||
|
||||
triggerBackup();
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message.includes('404')) return NextResponse.json({ error: 'Eintrag nicht gefunden' }, { status: 404 });
|
||||
if (error.message.includes('403')) return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 });
|
||||
}
|
||||
console.error('PUT /api/logbuch/[id]:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
}
|
||||
@@ -85,22 +43,13 @@ export async function DELETE(_request: NextRequest, { params }: { params: Promis
|
||||
const logbuchId = parseInt(id);
|
||||
|
||||
try {
|
||||
const existingRows = await query('SELECT ID FROM logbuch WHERE ID = ?', [logbuchId]) as { ID: number }[];
|
||||
if (existingRows.length === 0) {
|
||||
return NextResponse.json({ error: 'Eintrag nicht gefunden' }, { status: 404 });
|
||||
}
|
||||
|
||||
const isAdmin = session.role?.includes('admin');
|
||||
const beoRows = await query('SELECT COUNT(*) AS cnt FROM logbuch_beos WHERE LogbuchID = ? AND BeoID = ?', [logbuchId, session.beoId]) as { cnt: number }[];
|
||||
const isBeo = (beoRows[0]?.cnt ?? 0) > 0;
|
||||
|
||||
if (!isAdmin && !isBeo) {
|
||||
return NextResponse.json({ error: 'Keine Berechtigung zum Löschen dieses Eintrags' }, { status: 403 });
|
||||
}
|
||||
|
||||
await query('DELETE FROM logbuch WHERE ID = ?', [logbuchId]);
|
||||
await phpdb.deleteLogbuch(logbuchId, session.beoId, session.role ?? '');
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message.includes('404')) return NextResponse.json({ error: 'Eintrag nicht gefunden' }, { status: 404 });
|
||||
if (error.message.includes('403')) return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 });
|
||||
}
|
||||
console.error('DELETE /api/logbuch/[id]:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
}
|
||||
|
||||
+18
-114
@@ -1,90 +1,23 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { query, getPool } from '@/lib/db';
|
||||
import { getSession } from '@/lib/session';
|
||||
import { triggerBackup } from '@/lib/backup';
|
||||
import type { SelectedObjekt } from '@/types/logbuch';
|
||||
|
||||
const LIST_SQL =
|
||||
'SELECT' +
|
||||
' l.ID, l.Kuppel, l.ArtFuehrung,' +
|
||||
" DATE_FORMAT(l.Beginn, '%Y-%m-%dT%H:%i') AS Beginn," +
|
||||
" DATE_FORMAT(l.Ende, '%Y-%m-%dT%H:%i') AS Ende," +
|
||||
' l.Besucher, l.Bemerkungen, l.SonderName,' +
|
||||
' l.WetterTemp, l.WetterFeuchte, l.WetterDruck,' +
|
||||
' l.created_by, l.created_at,' +
|
||||
' creator.kuerzel AS created_by_kuerzel,' +
|
||||
" GROUP_CONCAT(DISTINCT bk.kuerzel ORDER BY bk.kuerzel SEPARATOR ', ') AS BEOs," +
|
||||
" GROUP_CONCAT(DISTINCT o.Name ORDER BY o.Name SEPARATOR ', ') AS Objekte" +
|
||||
' FROM logbuch l' +
|
||||
' LEFT JOIN (SELECT id, `kürzel` AS kuerzel FROM beos) creator ON creator.id = l.created_by' +
|
||||
' LEFT JOIN logbuch_beos lb ON lb.LogbuchID = l.ID' +
|
||||
' LEFT JOIN (SELECT id, `kürzel` AS kuerzel FROM beos) bk ON bk.id = lb.BeoID' +
|
||||
' 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';
|
||||
import * as phpdb from '@/lib/phpdb';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 });
|
||||
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, 500);
|
||||
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';
|
||||
|
||||
const month = searchParams.get('month') || '';
|
||||
const order = searchParams.get('order') === 'asc' ? 'asc' : 'desc';
|
||||
const search = (searchParams.get('search') || '').trim();
|
||||
|
||||
if (search) {
|
||||
const pattern = '%' + search + '%';
|
||||
const searchParams2 = [kuppel, pattern, pattern, pattern];
|
||||
const countSQL =
|
||||
'SELECT COUNT(*) AS total FROM (' +
|
||||
'SELECT l.ID FROM logbuch l' +
|
||||
' LEFT JOIN logbuch_beos lb ON lb.LogbuchID = l.ID' +
|
||||
' LEFT JOIN (SELECT id, `kürzel` AS kuerzel FROM beos) bk ON bk.id = lb.BeoID' +
|
||||
' 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' +
|
||||
" HAVING (MAX(l.Bemerkungen) LIKE ? OR GROUP_CONCAT(DISTINCT bk.kuerzel ORDER BY bk.kuerzel SEPARATOR ', ') LIKE ? OR GROUP_CONCAT(DISTINCT o.Name ORDER BY o.Name SEPARATOR ', ') LIKE ?)" +
|
||||
') AS sub';
|
||||
const listSQL = LIST_SQL +
|
||||
' HAVING (MAX(l.Bemerkungen) LIKE ? OR BEOs LIKE ? OR Objekte LIKE ?)' +
|
||||
` ORDER BY l.Beginn DESC LIMIT ${limit} OFFSET ${offset}`;
|
||||
try {
|
||||
const [countRows, entries] = await Promise.all([
|
||||
query(countSQL, searchParams2) as Promise<{ total: number }[]>,
|
||||
query(listSQL, searchParams2),
|
||||
]);
|
||||
return NextResponse.json({ entries, total: (countRows as unknown as { total: number }[])[0]?.total ?? 0 });
|
||||
} catch (error) {
|
||||
console.error('GET /api/logbuch (search):', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
let listWhere = 'WHERE l.Kuppel = ?';
|
||||
let countWhere = 'WHERE Kuppel = ?';
|
||||
let params: (string | number | null)[] = [kuppel];
|
||||
if (month && /^\d{4}-\d{2}$/.test(month)) {
|
||||
const [y, m] = month.split('-').map(Number);
|
||||
const start = `${y}-${String(m).padStart(2, '0')}-01`;
|
||||
const nextM = m === 12 ? 1 : m + 1;
|
||||
const nextY = m === 12 ? y + 1 : y;
|
||||
const end = `${nextY}-${String(nextM).padStart(2, '0')}-01`;
|
||||
listWhere += ' AND l.Beginn >= ? AND l.Beginn < ?';
|
||||
countWhere += ' AND Beginn >= ? AND Beginn < ?';
|
||||
params = [kuppel, start, end];
|
||||
}
|
||||
|
||||
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) + ` ORDER BY l.Beginn ${order} LIMIT ${limit} OFFSET ${offset}`, params),
|
||||
]);
|
||||
return NextResponse.json({ entries, total: (countRows as unknown as { total: number }[])[0]?.total ?? 0 });
|
||||
const result = await phpdb.listLogbuch({ kuppel, limit, offset, month, search, order });
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('GET /api/logbuch:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
@@ -99,47 +32,18 @@ export async function POST(request: NextRequest) {
|
||||
const body = await request.json();
|
||||
const { Kuppel, ArtFuehrung, SonderName, Beginn, Ende, Besucher, beoIds, objekte, Bemerkungen, Wetter } = body;
|
||||
|
||||
const pool = getPool();
|
||||
const [result] = await pool.execute(
|
||||
'INSERT INTO logbuch (Kuppel, ArtFuehrung, SonderName, Beginn, Ende, Besucher, Bemerkungen, WetterTemp, WetterFeuchte, WetterDruck, created_by)' +
|
||||
' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
[
|
||||
Kuppel, ArtFuehrung, SonderName || null, Beginn, Ende,
|
||||
Besucher ?? 0,
|
||||
Bemerkungen?.slice(0, 500) || null,
|
||||
Wetter?.temp ?? null,
|
||||
Wetter?.feuchte ?? null,
|
||||
Wetter?.druck ?? null,
|
||||
session.beoId,
|
||||
]
|
||||
) as [{ insertId: number }, unknown];
|
||||
|
||||
const logbuchId = result.insertId;
|
||||
|
||||
for (const beoId of (beoIds as number[]) || []) {
|
||||
await query('INSERT INTO logbuch_beos (LogbuchID, BeoID) VALUES (?, ?)', [logbuchId, beoId]);
|
||||
}
|
||||
|
||||
for (const obj of (objekte as SelectedObjekt[]) || []) {
|
||||
let objektId = obj.ID;
|
||||
if (!objektId) {
|
||||
const existing = await query('SELECT ID, Name FROM objekte WHERE LOWER(Name) = LOWER(?)', [obj.Name]) as { ID: number; Name: string }[];
|
||||
if (existing[0]) {
|
||||
objektId = existing[0].ID;
|
||||
} else {
|
||||
const [ins] = await pool.execute('INSERT INTO objekte (Name) VALUES (?)', [obj.Name]) as [{ insertId: number }, unknown];
|
||||
objektId = ins.insertId;
|
||||
}
|
||||
}
|
||||
await query('UPDATE objekte SET LastUsed = NOW() WHERE ID = ?', [objektId]);
|
||||
await query(
|
||||
'INSERT INTO logbuch_objekte (LogbuchID, ObjektID) VALUES (?, ?)',
|
||||
[logbuchId, objektId]
|
||||
);
|
||||
}
|
||||
const result = await phpdb.createLogbuch({
|
||||
Kuppel, ArtFuehrung, SonderName, Beginn, Ende,
|
||||
Besucher: Besucher ?? 0,
|
||||
beoIds: beoIds ?? [],
|
||||
objekte: objekte ?? [],
|
||||
Bemerkungen: Bemerkungen ?? null,
|
||||
Wetter: Wetter ?? null,
|
||||
created_by: session.beoId,
|
||||
});
|
||||
|
||||
triggerBackup();
|
||||
return NextResponse.json({ id: logbuchId }, { status: 201 });
|
||||
return NextResponse.json(result, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('POST /api/logbuch:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
|
||||
@@ -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 PUT(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const session = await getSession();
|
||||
@@ -13,8 +13,8 @@ export async function PUT(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
const { name } = await req.json();
|
||||
const trimmed = (name as string)?.trim();
|
||||
if (!trimmed) return NextResponse.json({ error: 'Name darf nicht leer sein' }, { status: 400 });
|
||||
await query('UPDATE objekte SET Name = ? WHERE ID = ?', [trimmed, numId]);
|
||||
return NextResponse.json({ ID: numId, Name: trimmed });
|
||||
const result = await phpdb.updateObjekt(numId, trimmed);
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('PUT /api/objekte/[id]:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
@@ -29,7 +29,7 @@ export async function DELETE(_req: NextRequest, { params }: { params: Promise<{
|
||||
const { id } = await params;
|
||||
const numId = Number(id);
|
||||
if (isNaN(numId)) return NextResponse.json({ error: 'Ungültige ID' }, { status: 400 });
|
||||
await query('DELETE FROM objekte WHERE ID = ?', [numId]);
|
||||
await phpdb.deleteObjekt(numId);
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
console.error('DELETE /api/objekte/[id]:', error);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
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() {
|
||||
const session = await getSession();
|
||||
if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 });
|
||||
try {
|
||||
const rows = await query('SELECT ID, Name FROM objekte ORDER BY LastUsed DESC LIMIT 100');
|
||||
const rows = await phpdb.getObjekte();
|
||||
return NextResponse.json(rows);
|
||||
} catch (error) {
|
||||
console.error('GET /api/objekte:', error);
|
||||
@@ -22,8 +22,8 @@ export async function POST(req: NextRequest) {
|
||||
const { name } = await req.json();
|
||||
const trimmed = (name as string)?.trim();
|
||||
if (!trimmed) return NextResponse.json({ error: 'Name darf nicht leer sein' }, { status: 400 });
|
||||
const result = await query('INSERT INTO objekte (Name) VALUES (?)', [trimmed]) as { insertId: number };
|
||||
return NextResponse.json({ ID: result.insertId, Name: trimmed }, { status: 201 });
|
||||
const result = await phpdb.createObjekt(trimmed);
|
||||
return NextResponse.json(result, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('POST /api/objekte:', error);
|
||||
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user