Files
arbeitarbeit/src/lib/types.ts
Pascal Linxweiler 1126665195 Add top nav bar and Heimservice page
Adds a Bestellübersicht/Heimservice/Abmelden nav bar to the layout, and
builds out the Heimservice page with a per-restaurant control panel
(availability windows, ORDER WebApp link, password reset, mobile-number
editor, and a consolidated call popup) mirroring the old interface's
button layout in the current design system.
2026-08-10 12:08:44 +02:00

113 lines
3.1 KiB
TypeScript

export type OrderStatus =
| "neu"
| "uebermittelt"
| "telefonisch"
| "nicht_uebermittelt"
| "rueckruf"
| "storniert"
| "fake";
export type OrderType = "vorbestellung" | "direktanruf";
/** Alles, was eine Bearbeiterin an einer Bestellung auslösen kann. */
export type OrderAction =
| "uebermittelt"
| "gastronom_voice"
| "gastronom_anruf"
| "kunde_anrufen"
| "nicht_uebermittelt"
| "rueckruf"
| "storno"
| "fake"
| "stornieren"
| "sos"
| "telefonisch_uebermittelt";
/** Protokolleintrag einer ausgelösten Aktion, treibt die Timeline. */
export type OrderEvent = { type: OrderAction; at: string };
export type PaymentMethod = "bar" | "ec" | "paypal" | "kreditkarte";
export type Restaurant = {
name: string;
city: string;
/** Öffnungszeiten, z. B. "10:00 bis 23:00" */
hours: string;
phone1: string;
phone2?: string;
mobile?: string;
mobile2?: string;
orderUrl: string;
/** Zeitfenster für den Heimservice, z. B. Mittags- und Abendschicht. Zweites Fenster optional. */
heimserviceWindows: [string, string | undefined];
};
export type Customer = {
name: string;
email: string;
phone: string;
};
export type Order = {
id: string;
/** Fortlaufende Bestellnummer, wird in der Liste als erste Spalte gezeigt */
number: number;
status: OrderStatus;
type: OrderType;
restaurant: Restaurant;
customer: Customer;
/** Zeitpunkt des Bestelleingangs, ISO-String */
receivedAt: string;
/** Gewünschte Liefer- bzw. Abholzeit, ISO-String */
dueAt: string;
total: number;
itemCount: number;
payment: PaymentMethod;
pdfUrl: string;
/** Bestellung im externen Backoffice, öffnet in neuem Tab. */
externalUrl: string;
note?: string;
/** Zeitpunkt, zu dem der Gastronom die Bestellung bestätigt hat. */
confirmedAt?: string;
/** Manuell ausgelöste Schritte, ältester zuerst. */
events: OrderEvent[];
};
export const STATUS_LABEL: Record<OrderStatus, string> = {
neu: "Neu",
uebermittelt: "Übermittelt",
telefonisch: "Telefonisch übermittelt",
nicht_uebermittelt: "Nicht übermittelt",
rueckruf: "Rückrufhinweis",
storniert: "Storniert",
fake: "Fake",
};
export const TYPE_LABEL: Record<OrderType, string> = {
vorbestellung: "Vorbestellung",
direktanruf: "Direktanruf",
};
export const PAYMENT_LABEL: Record<PaymentMethod, string> = {
bar: "Bar",
ec: "EC-Karte",
paypal: "PayPal",
kreditkarte: "Kreditkarte",
};
/** Abstand zwischen den drei automatischen Übermittlungsversuchen. */
export const ATTEMPT_INTERVAL_MS = 5 * 60 * 1000;
export const ATTEMPT_COUNT = 3;
/** Nach dieser Zeit ohne Bearbeitung gilt eine Bestellung als nicht übermittelt. */
export const UNDELIVERED_AFTER_MS = 15 * 60 * 1000;
/**
* Eine unbearbeitete Bestellung kippt nach {@link UNDELIVERED_AFTER_MS} automatisch auf
* `nicht_uebermittelt`. Sobald jemand eine Aktion ausgelöst hat, bleibt der echte Status stehen.
*/
export function effectiveStatus(order: Order, now: number): OrderStatus {
const overdue = now - new Date(order.receivedAt).getTime() >= UNDELIVERED_AFTER_MS;
return order.status === "neu" && overdue ? "nicht_uebermittelt" : order.status;
}