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.
113 lines
2.8 KiB
TypeScript
113 lines
2.8 KiB
TypeScript
export type Role = "admin" | "staff";
|
||
|
||
export interface Profile {
|
||
id: string;
|
||
email: string;
|
||
full_name: string;
|
||
role: Role;
|
||
password_auth_enabled: boolean;
|
||
created_at: string;
|
||
}
|
||
|
||
export interface Section {
|
||
key: string;
|
||
label: string;
|
||
// Sprachcode (z. B. "en", "fr") -> übersetzter Name. Enthält nie "de" -
|
||
// Deutsch ist immer die "label"-Spalte selbst.
|
||
translations: Record<string, string>;
|
||
time_range: string;
|
||
sort: number;
|
||
}
|
||
|
||
export interface Dish {
|
||
id: string;
|
||
name: string;
|
||
translations: Record<string, string>;
|
||
price: number;
|
||
allergens: string[];
|
||
additives: string[];
|
||
}
|
||
|
||
export interface MenuEntry {
|
||
id: string;
|
||
menu_date: string;
|
||
section_key: string;
|
||
position: number;
|
||
dish: Dish;
|
||
}
|
||
|
||
export interface CodeItem {
|
||
code: string;
|
||
name: string;
|
||
translations: Record<string, string>;
|
||
sort: number;
|
||
}
|
||
|
||
export interface DishSuggestion {
|
||
id: string;
|
||
name: string;
|
||
description: string | null;
|
||
created_at: string;
|
||
}
|
||
|
||
/** Übersetzten Namen für die aktuelle Sprache liefern, sonst Deutsch als Fallback. */
|
||
export function localized(
|
||
item: {
|
||
name?: string;
|
||
label?: string;
|
||
// Neue, dynamische Form (Gerichte/Essenszeiten/Allergene/
|
||
// Zusatzstoffe, s. lib/db/translations.ts) – Sprachcode -> Text.
|
||
translations?: Record<string, string>;
|
||
// Ältere, feste Form – wird u. a. noch für den Hinweistext in den
|
||
// Design-Einstellungen genutzt (settings.labeling_notice_en/_pl),
|
||
// die kein Übersetzungstabellen-Konzept haben.
|
||
name_en?: string | null;
|
||
name_pl?: string | null;
|
||
label_en?: string | null;
|
||
label_pl?: string | null;
|
||
},
|
||
locale: string
|
||
): string {
|
||
const de = item.name ?? item.label ?? "";
|
||
if (locale === "de") return de;
|
||
if (item.translations) return item.translations[locale] || de;
|
||
if (locale === "en") return item.name_en || item.label_en || de;
|
||
if (locale === "pl") return item.name_pl || item.label_pl || de;
|
||
return de;
|
||
}
|
||
|
||
// Farb-Defaults (r-hofmann.de: Blau #003388, Navy #0d315c, Orange #ff6900)
|
||
export const DEFAULT_COLORS: Record<string, string> = {
|
||
primary: "#003388",
|
||
primaryDark: "#0d315c",
|
||
accent: "#ff6900",
|
||
headerText: "#ffffff",
|
||
rowBg: "#e3e4f1",
|
||
rowBgAlt: "#f4f4fa",
|
||
addBtn: "#6da54c",
|
||
deleteBtn: "#e2371d",
|
||
};
|
||
|
||
export const COLOR_VARS: Record<string, string> = {
|
||
primary: "--c-primary",
|
||
primaryDark: "--c-primary-dark",
|
||
accent: "--c-accent",
|
||
headerText: "--c-header-text",
|
||
rowBg: "--c-row-bg",
|
||
rowBgAlt: "--c-row-bg-alt",
|
||
addBtn: "--c-add",
|
||
deleteBtn: "--c-del",
|
||
};
|
||
|
||
export function logoUrl(path: string | null | undefined): string | null {
|
||
if (!path) return null;
|
||
return `/branding/${path}`;
|
||
}
|
||
|
||
export function faviconUrl(path: string | null | undefined): string | null {
|
||
if (!path) return null;
|
||
return `/branding/${path}`;
|
||
}
|
||
|
||
export const SITE_TITLE = process.env.SITE_TITLE?.trim() || "Canteen Menu";
|