Neue Migration 0002_labeling_notice.sql: settings.labeling_mode
("detailed"/"notice") + labeling_notice(_en/_pl). Auf der Seite
"Allergene & Zusatzstoffe" (LabelingNoticeEditor) kann zwischen der
detaillierten Auswahl je Gericht und einem editierbaren Hinweistext
umgeschaltet werden. Im Hinweismodus entfällt auf der öffentlichen
Speisekarte (Desktop + Mobile) die Legende und die Kürzel an den
Gerichten, in der Gerichte-Verwaltung wird die Chip-Auswahl beim
Bearbeiten ausgeblendet. Umschalten/Bearbeiten ist für staff und admin
freigegeben, Farben in /api/settings bleiben admin-only.
Version 1.8.0.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
70 lines
2.4 KiB
TypeScript
70 lines
2.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { query } from "@/lib/db";
|
|
import { getSettings, type LabelingMode } from "@/lib/db/settings";
|
|
import { authErrorResponse, requireRole } from "@/lib/auth/session";
|
|
import { isSameOrigin } from "@/lib/origin";
|
|
|
|
export async function GET() {
|
|
return NextResponse.json(await getSettings());
|
|
}
|
|
|
|
interface SettingsPatchBody {
|
|
colors?: Record<string, string>;
|
|
labeling_mode?: LabelingMode;
|
|
labeling_notice?: string;
|
|
labeling_notice_en?: string | null;
|
|
labeling_notice_pl?: string | null;
|
|
}
|
|
|
|
export async function PATCH(request: Request) {
|
|
if (!isSameOrigin(request)) {
|
|
return NextResponse.json({ error: "Nicht erlaubt." }, { status: 403 });
|
|
}
|
|
try {
|
|
// Farben bleiben admin-only wie bisher; die Allergen-/Zusatzstoff-
|
|
// Anzeige darf auch Kantinenpersonal umschalten/bearbeiten.
|
|
const session = await requireRole(["staff", "admin"]);
|
|
const body = (await request.json()) as SettingsPatchBody;
|
|
|
|
const sets: string[] = [];
|
|
const params: unknown[] = [];
|
|
|
|
if (body.colors !== undefined) {
|
|
if (session.user.role !== "admin") {
|
|
return NextResponse.json({ error: "forbidden" }, { status: 403 });
|
|
}
|
|
params.push(JSON.stringify(body.colors));
|
|
sets.push(`colors = $${params.length}`);
|
|
}
|
|
if (body.labeling_mode !== undefined) {
|
|
if (body.labeling_mode !== "detailed" && body.labeling_mode !== "notice") {
|
|
return NextResponse.json({ error: "invalid_input" }, { status: 400 });
|
|
}
|
|
params.push(body.labeling_mode);
|
|
sets.push(`labeling_mode = $${params.length}`);
|
|
}
|
|
if (body.labeling_notice !== undefined) {
|
|
params.push(body.labeling_notice);
|
|
sets.push(`labeling_notice = $${params.length}`);
|
|
}
|
|
if (body.labeling_notice_en !== undefined) {
|
|
params.push(body.labeling_notice_en);
|
|
sets.push(`labeling_notice_en = $${params.length}`);
|
|
}
|
|
if (body.labeling_notice_pl !== undefined) {
|
|
params.push(body.labeling_notice_pl);
|
|
sets.push(`labeling_notice_pl = $${params.length}`);
|
|
}
|
|
|
|
if (sets.length === 0) {
|
|
return NextResponse.json({ error: "invalid_input" }, { status: 400 });
|
|
}
|
|
await query(`update settings set ${sets.join(", ")} where id = 1`, params);
|
|
return NextResponse.json({ ok: true });
|
|
} catch (err) {
|
|
const res = authErrorResponse(err);
|
|
if (res) return res;
|
|
throw err;
|
|
}
|
|
}
|