Files
Speisekarte/app/api/dishes/export/route.ts
T
florian.wilde cd8b0fab9f feat: Speiseplan-Inhalte variabel mehrsprachig (Teil 2)
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.
2026-07-20 11:10:06 +02:00

49 lines
1.4 KiB
TypeScript

import { query } from "@/lib/db";
import { loadTranslationsFor } from "@/lib/db/translations";
import { listActiveLanguageCodes } from "@/lib/db/languages";
import { authErrorResponse, requireRole } from "@/lib/auth/session";
import { toCsv } from "@/lib/csv";
interface DishRow {
id: string;
name: string;
price: string;
allergens: string[];
additives: string[];
}
export async function GET() {
try {
await requireRole(["staff", "admin"]);
const [dishes, activeCodes] = await Promise.all([
query<DishRow>("select id, name, price, allergens, additives from dishes order by name"),
listActiveLanguageCodes(),
]);
const langCodes = activeCodes.filter((c) => c !== "de");
const translations = await loadTranslationsFor(
"dish_translations",
dishes.map((d) => d.id)
);
const rows = [
["name", ...langCodes.map((c) => `name_${c}`), "price", "allergens", "additives"],
...dishes.map((d) => [
d.name,
...langCodes.map((c) => translations.get(d.id)?.[c] ?? ""),
d.price,
(d.allergens ?? []).join(";"),
(d.additives ?? []).join(";"),
]),
];
return new Response(toCsv(rows), {
headers: {
"Content-Type": "text/csv; charset=utf-8",
"Content-Disposition": 'attachment; filename="gerichte.csv"',
},
});
} catch (err) {
const res = authErrorResponse(err);
if (res) return res;
throw err;
}
}