18bf94fbfc
- Datenbank auf utf8mb4_unicode_ci migriert (migrate_to_utf8mb4.sh) - beos: Spalte 'role' (kommagetrennte Rollen: guide, admin, key, deleted) - BEO-Auswahl im Formular filtert nur noch role='guide' - logbuch_objekte: ObjektName-Spalte entfernt, stattdessen JOIN auf objekte - lib/db.ts: charset utf8mb4 in Connection-Pool - Session und Auth um role-Feld erweitert - compose.yml: phpMyAdmin mit Traefik unter /myadmin - compose.yml: MySQL auf 127.0.0.1:3336 für SSH-Tunnel (lokale Entwicklung) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
92 lines
3.5 KiB
TypeScript
92 lines
3.5 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { query, getPool } from '@/lib/db';
|
|
import { getSession } from '@/lib/session';
|
|
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,' +
|
|
" 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 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' +
|
|
' ORDER BY l.Beginn DESC';
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const { searchParams } = new URL(request.url);
|
|
const kuppel = searchParams.get('kuppel') || 'West';
|
|
const limit = Math.min(parseInt(searchParams.get('limit') || '20'), 100);
|
|
|
|
try {
|
|
const rows = await query(LIST_SQL + ` LIMIT ${limit}`, [kuppel]);
|
|
return NextResponse.json(rows);
|
|
} catch (error) {
|
|
console.error('GET /api/logbuch:', error);
|
|
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
const session = await getSession();
|
|
if (!session) return NextResponse.json({ error: 'Nicht angemeldet' }, { status: 401 });
|
|
|
|
try {
|
|
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]
|
|
);
|
|
}
|
|
|
|
return NextResponse.json({ id: logbuchId }, { status: 201 });
|
|
} catch (error) {
|
|
console.error('POST /api/logbuch:', error);
|
|
return NextResponse.json({ error: 'Datenbankfehler' }, { status: 500 });
|
|
}
|
|
}
|