Im Wochenplan lässt sich pro Tag ein optionaler, mehrsprachiger Schließungsgrund hinterlegen. Geschlossene Tage werden auf der öffentlichen Speisekarte (Desktop + mobil) und im RSS-Feed als "Geschlossen" statt mit Essenszeiten angezeigt, im Wochenplan bleibt "Mahlzeit hinzufügen" für diesen Tag deaktiviert.
122 lines
3.1 KiB
TypeScript
122 lines
3.1 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;
|
||
}
|
||
|
||
export interface ClosedDay {
|
||
closed_date: string;
|
||
reason: string | null;
|
||
translations: Record<string, string>;
|
||
}
|
||
|
||
/** Übersetzten Namen für die aktuelle Sprache liefern, sonst Deutsch als Fallback. */
|
||
export function localized(
|
||
item: {
|
||
name?: string;
|
||
label?: string;
|
||
// Grund eines geschlossenen Tages (s. ClosedDay) – optional, anders
|
||
// als name/label bei den übrigen Inhaltstypen.
|
||
reason?: string | null;
|
||
// 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 ?? item.reason ?? "";
|
||
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";
|