Entwicklerdokumentation

Specials

Die Specials von heute oder dieser Woche mit renderSpecialsWidget und der Markierung Jetzt zeigen – oder eigene Karten auf client.specials bauen.

Dieselbe SDK-Datei, die das Buchungswidget rendert, zeigt auch die Specials einer Location: die Gerichte und Angebote auf Speisekartenpositionen, die die Location anbietet, jeweils mit Preis und Zeitfenster pro Tag. Zwei Wege hinein, beide auf derselben Specials-API:

  • renderSpecialsWidget – ein Aufruf, eine Liste von Karten in einem Element Ihrer Wahl, stilisoliert wie das Buchungswidget. Das Special, das gerade läuft, trägt die Markierung Jetzt. Für eine Seite „Heute“ oder „Diese Woche“ oder für einen Bildschirm in der Location.
  • Der Headless-Client – client.specials({ date, days }) neben den Buchungs- und Eventaufrufen aus Eigene Formulare. Für eine Website, die schon eigene Karten hat und nur die Daten braucht.

Specials stehen jedem Tarif offen, nichts davon hängt also vom Tarif der Location ab.

Installation

Laden Sie das SDK wie für das Buchungswidget (JavaScript-SDK) und fügen Sie ein Element für die Specials ein:

<div id="bookdineplay-specials"></div>
<script src="https://cdn.bookdineplay.com/sdk/v0/bookdineplay.js"></script>

Das Specials-Widget rendern

HTML

<script>
  window.BookDinePlay.renderSpecialsWidget({
    container: '#bookdineplay-specials',
    venueSlug: 'your-venue',
    apiBaseUrl: 'https://api.bookdineplay.com',
    publishableKey: 'bdp_pk_your_publishable_key',
    view: 'today',
    locale: 'de',
    theme: 'auto'
  });
</script>

JavaScript

// Headless: eigenes Markup auf denselben Daten. Die Antwort ist null, wenn die Location keine Specials anbietet.
const client = window.BookDinePlay.createClient({
  apiBaseUrl: 'https://api.bookdineplay.com',
  venueSlug: 'your-venue',
  publishableKey: 'bdp_pk_your_publishable_key'
});
const response = await client.specials({ days: 7 });
for (const day of response?.days ?? []) {
  for (const special of day.specials) {
    console.log(day.date, special.title, special.price, response.currency);
  }
}

Der Aufruf gibt die Widget-Instanz zurück – oder null, wenn das Rendern verweigert wurde (Wenn es nicht rendert). Die Instanz hat eine Methode, destroy(), die ihren Timer und eine laufende Anfrage beendet.

Optionen

Option Pflicht Bedeutung
container ja Ein CSS-Selektor oder ein DOM-Element. Das Widget rendert darin.
venueSlug ja Der Slug Ihrer Location.
apiBaseUrl ja https://api.bookdineplay.com. Nur bei einer privaten Installation anders.
publishableKey ja Der bdp_pk_…-Schlüssel der Location. Nie ein geheimer Schlüssel.
view nein today (Standard): die Specials von heute unter „Heute im Special“. Oder week: die nächsten sieben Tage unter „Diese Woche“, mit einer Überschrift je Tag, an dem es Specials gibt. Alles andere zählt als today.
locale nein en (Standard) oder de: die eigenen Texte des Widgets, die Tagesüberschriften und das Geldformat. Jedes de-*-Tag zählt als de. language wird als Alias akzeptiert. Titel und Beschreibungen der Location erscheinen in der Sprache, in der die Location sie geschrieben hat.
theme nein auto (folgt der Systemeinstellung des Besuchers, Standard), light oder dark.

Was der Gast sieht

Jedes Special ist eine Karte mit Bild (wenn ein verwendbares da ist), Titel, Preis, dem Namen der Position, wenn er vom Titel abweicht, Beschreibung, den Tags der Position und einer Zeile mit dem Zeitfenster pro Tag: 17:00–22:00, mit angehängtem „(Folgetag)“, wenn es nach Mitternacht endet, oder „Ganztägig“. Ein Special, das günstiger ist als der Normalpreis der Position, zeigt den Normalpreis durchgestrichen, Screenreader lesen „Normalpreis“ vor. Innerhalb eines Tages behalten die Karten die Reihenfolge der API (Specials-API).

  • Heute listet den ersten Tag der Antwort: zuerst die späten Fenster von gestern, die noch laufen, markiert mit „(seit gestern)“, dann die Specials von heute.
  • Diese Woche fragt sieben Tage ab und listet nur die Tage, an denen es Specials gibt, jeden unter einer eigenen Datumsüberschrift. Ein vom Vortag übernommenes spätes Fenster erscheint nur unter dem ersten Tag; an jedem späteren Tag steht es schon unter dem Tag, an dem es begann.
  • Jetzt markiert das Special, dessen Fenster die aktuelle Uhrzeit der Location enthält, mit einem pulsierenden Punkt, der für Besucher mit der Einstellung „weniger Bewegung“ stillsteht. Ein von gestern übernommenes Special, das schon geendet hat, wird abgedunkelt.

Der Titel ist eine echte Überschrift und die Karten sind eine Liste, ein Screenreader kündigt sie also entsprechend an.

Zeitzone und Aktualisierung

„Jetzt“ wird immer in der Zeitzone der Location berechnet, aus dem timezone der Antwort, nie aus dem Browser des Besuchers. Ein Gast in einem anderen Land sieht also dieselbe Markierung wie das Personal der Location. Das Widget wertet sie jede Minute ohne Anfrage neu aus. Wechselt der Kalendertag der Location, lädt es neu, einmal pro Tag der Location – ein über Nacht offener Bildschirm springt von selbst auf die Specials des neuen Tages.

Eine fehlgeschlagene Anfrage leert das Widget nie. Die letzte Antwort bleibt stehen und der nächste Minutentakt versucht es erneut, höchstens eine Anfrage pro Minute, mit einer Konsolenwarnung beim ersten Fehler. Nur ein fehlgeschlagener erster Ladevorgang lässt nichts zum Anzeigen, bis ein neuer Versuch gelingt.

Bilder

Die API kann das Bild eines Specials als Pfad relativ zur BookDinePlay-App liefern, der sich auf Ihrer Website falsch auflösen würde. Das Widget zeigt ein Bild deshalb nur, wenn seine Adresse eine absolute https-URL ist, und zeigt die Karte sonst ohne Bild. (Auf einer Seite, die über reines http läuft, etwa in der lokalen Entwicklung, wird auch eine absolute http-Adresse akzeptiert.) Ein Bild, das nicht lädt, wird entfernt, statt als kaputtes Bild stehenzubleiben. Die Bilder tragen ein leeres alt, weil der Titel das Special schon benennt.

Eine Instanz pro Container

Ruft man renderSpecialsWidget erneut auf demselben Container auf, ersetzt es das erste Widget: Das frühere beendet Timer und Anfrage und gibt den Container frei, es läuft also kein verwaister Timer weiter. Nutzen Sie für ein „Heute“- und ein „Woche“-Widget auf einer Seite getrennte Container. Ein Widget, dessen Container die Seite verlassen hat, hält von selbst an.

Nichts, wenn es leer ist

Eine Location ohne Specials im Zeitraum (nichts veröffentlicht, an dem Tag nichts aktiv) bekommt gar kein Widget: keinen Rahmen, keine Überschrift, keinen Rand, nur Ihren leeren Container. Dasselbe gilt, solange die erste Anfrage noch lädt, wenn die erste Anfrage fehlgeschlagen ist und wenn die Antwort 404 lautet. Geben Sie dem Container keine eigene Höhe und keinen Platzhalter, damit die Seite keine Lücke zeigt.

Wenn es nicht rendert

renderSpecialsWidget gibt null zurück und schreibt eine Zeile in die Browser-Konsole, ohne je in Ihre Seite zu werfen – dieselben drei Verweigerungen wie bei renderBookingWidget (Wenn es nicht rendert): Der Container wurde nicht gefunden, venueSlug oder apiBaseUrl fehlt, oder publishableKey fehlt oder ist kein bdp_pk_…-Schlüssel.

Theming

Das Specials-Widget rendert im selben isolierten Root wie die anderen Widgets und liest dieselben neun --bdp-*-Custom-Properties von der Host-Seite: --bdp-accent für die Markierung „Jetzt“ und die Tags, --bdp-surface für die Karten, --bdp-radius für deren Ecken. Theming listet jede Property mit ihrem Standardwert; es gibt keine Specials-spezifische Property.

Der Headless-Client

client.specials(params, { signal }) ruft GET /api/venues/{venueSlug}/specials mit dem veröffentlichbaren Schlüssel des Clients auf. params ist optional: date (yyyy-MM-dd, der erste Tag in Ortszeit der Location) und days (1 bis 14) werden nur gesendet, wenn sie gesetzt sind, und die API nimmt sonst das heutige Datum der Location und einen Tag. Der Aufruf liefert den Antwort-Body (slug, timezone, currency und days[]) oder null bei einem 404, wo die anderen Lesezugriffe ablehnen. Jeder andere Fehler lehnt mit einem BookDinePlayError ab.

Für Seiten, die eigene Karten zeichnen, gibt es zwei reine Helfer. BookDinePlay.helpers.venueLocalNow(timezone, now) liefert das lokale date und die time der Location für einen Zeitpunkt, und BookDinePlay.helpers.isSpecialOnAt(occurrenceDate, windowStart, windowEnd, localDate, localTime) beantwortet, ob ein Special in diesem Moment läuft, gerechnet ab seinem occurrenceDate wie im Widget.

Nächste Schritte

  • Specials-API – jedes Feld der Antwort und wie Zeitzone und späte Fenster der Location funktionieren.
  • Theming – Farben, Radius und Schrift.
  • Eigene Formulare – die übrigen Aufrufe desselben Clients.
  • WordPress-Plugin – dasselbe Widget als [bookdineplay_specials].
  • .NET-SDK – GetSpecialsAsync für serverseitigen Code.