Gerichtnamen, Essenszeiten und Allergen-/Zusatzstoff-Bezeichnungen sind jetzt genauso dynamisch mehrsprachig wie die Bedienoberfläche aus v1.10.0, statt fest auf Englisch/Polnisch begrenzt zu sein. Neue Übersetzungstabellen ersetzen die alten name_en/name_pl-Spalten, DeepL-Auto-Übersetzung und CSV-Import/-Export unterstützen jetzt beliebig viele aktive Sprachen.
83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { query, queryOne } from "@/lib/db";
|
|
import { loadTranslationsFor, replaceTranslations } from "@/lib/db/translations";
|
|
import { authErrorResponse, requireRole } from "@/lib/auth/session";
|
|
import { isSameOrigin } from "@/lib/origin";
|
|
import type { Section } from "@/lib/types";
|
|
|
|
interface SectionRow {
|
|
key: string;
|
|
label: string;
|
|
time_range: string;
|
|
sort: number;
|
|
}
|
|
|
|
export async function PATCH(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ key: string }> }
|
|
) {
|
|
if (!isSameOrigin(request)) {
|
|
return NextResponse.json({ error: "Nicht erlaubt." }, { status: 403 });
|
|
}
|
|
try {
|
|
await requireRole(["staff", "admin"]);
|
|
const { key } = await params;
|
|
const body = (await request.json()) as Partial<
|
|
Pick<Section, "label" | "time_range" | "sort">
|
|
> & { translations?: Record<string, string | null> };
|
|
|
|
const fields: string[] = [];
|
|
const values: unknown[] = [];
|
|
for (const col of ["label", "time_range", "sort"] as const) {
|
|
if (body[col] !== undefined) {
|
|
values.push(body[col]);
|
|
fields.push(`${col} = $${values.length}`);
|
|
}
|
|
}
|
|
let row: SectionRow | null;
|
|
if (fields.length > 0) {
|
|
values.push(key);
|
|
row = await queryOne<SectionRow>(
|
|
`update sections set ${fields.join(", ")} where key = $${values.length}
|
|
returning key, label, time_range, sort`,
|
|
values
|
|
);
|
|
} else {
|
|
row = await queryOne<SectionRow>(
|
|
"select key, label, time_range, sort from sections where key = $1",
|
|
[key]
|
|
);
|
|
}
|
|
if (!row) return NextResponse.json({ error: "not_found" }, { status: 404 });
|
|
if (body.translations) {
|
|
await replaceTranslations("section_translations", row.key, body.translations);
|
|
}
|
|
const translations = await loadTranslationsFor("section_translations", [row.key]);
|
|
const section: Section = { ...row, translations: translations.get(row.key) ?? {} };
|
|
return NextResponse.json(section);
|
|
} catch (err) {
|
|
const res = authErrorResponse(err);
|
|
if (res) return res;
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
export async function DELETE(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ key: string }> }
|
|
) {
|
|
if (!isSameOrigin(request)) {
|
|
return NextResponse.json({ error: "Nicht erlaubt." }, { status: 403 });
|
|
}
|
|
try {
|
|
await requireRole(["staff", "admin"]);
|
|
const { key } = await params;
|
|
await query("delete from sections where key = $1", [key]);
|
|
return NextResponse.json({ ok: true });
|
|
} catch (err) {
|
|
const res = authErrorResponse(err);
|
|
if (res) return res;
|
|
throw err;
|
|
}
|
|
}
|