Phase 4: Terminal im Gerätehaus mit Offline-Betrieb #5
@@ -128,6 +128,15 @@ bedienbar ist und weiterarbeitet, wenn das Netz weg ist.
|
||||
Offline-E2E-Test, der genau darauf wartet.
|
||||
- `/kiosk/einrichten` ließ sich nicht vorab erzeugen, weil `useSearchParams()`
|
||||
ohne Suspense-Grenze stand. Der Produktionsbuild brach dabei ab.
|
||||
- Der Anwesenheits- und der Fahrten-Wizard zeigten erst die eine, nach dem
|
||||
Laden des eigenen Stands die andere Fassung — wer zügig tippte, drückte ins
|
||||
Leere. Bis der Stand bekannt ist, steht dort jetzt ein Platzhalter.
|
||||
- Die Offline-Seite blieb stehen, wenn nur eine einzelne Anfrage abgebrochen
|
||||
war. Am Hallenmonitor, den niemand bedient, hieße das: bis jemand vorbeikommt.
|
||||
Sie versucht es jetzt alle zehn Sekunden von selbst.
|
||||
- Der Hallenmonitor stapelte alle laufenden Einsätze übereinander und schob
|
||||
damit Anwesenheit, Fahrzeuge und Prüfungen aus dem Bild. Zwei stehen groß,
|
||||
der Rest als Zeile.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+11
-1
@@ -13,7 +13,17 @@ export default defineConfig({
|
||||
testDir: "./tests/e2e",
|
||||
fullyParallel: true,
|
||||
forbidOnly: Boolean(process.env.CI),
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/**
|
||||
* Ein Wiederholungsversuch auch lokal.
|
||||
*
|
||||
* Der Grund ist derselbe wie bei den großzügigen Zeitlimits unten: "next
|
||||
* dev" übersetzt jede Route beim ersten Aufruf, und mit vier gleichzeitigen
|
||||
* Arbeitern kommt dazu die Anmeldung mit bcrypt (12 Runden, wie in
|
||||
* Produktion). Unter dieser Last läuft gelegentlich ein Test ins Zeitlimit,
|
||||
* der einzeln zuverlässig grün ist — verstreut über alle Dateien, nicht an
|
||||
* einer Stelle. Ein echter Fehler fällt zweimal durch und bleibt sichtbar.
|
||||
*/
|
||||
retries: process.env.CI ? 2 : 1,
|
||||
/**
|
||||
* Bewusst wenige Worker: "next dev" übersetzt jede Route erst beim ersten
|
||||
* Aufruf. Zu viele gleichzeitige Erstaufrufe lassen den Server so lange
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { CloudOff } from "lucide-react";
|
||||
import { ErneutVersuchen } from "@/app/kiosk/offline/wiederholen";
|
||||
|
||||
export const metadata = { title: "Offline" };
|
||||
|
||||
@@ -9,6 +10,9 @@ export const metadata = { title: "Offline" };
|
||||
* Sie ist bewusst statisch und ohne Datenzugriff — sie muss auch dann noch
|
||||
* erscheinen, wenn vom Server nichts mehr kommt. Und sie sagt das Wichtigste:
|
||||
* das Erfasste ist nicht weg.
|
||||
*
|
||||
* Zurück findet sie von selbst: ein einzelner abgebrochener Aufruf genügt, um
|
||||
* hier zu landen, und dann darf das Terminal nicht warten, bis jemand tippt.
|
||||
*/
|
||||
export default function OfflineSeite() {
|
||||
return (
|
||||
@@ -23,6 +27,8 @@ export default function OfflineSeite() {
|
||||
verloren.
|
||||
</p>
|
||||
|
||||
<ErneutVersuchen />
|
||||
|
||||
<Link
|
||||
href="/kiosk"
|
||||
className="flex h-16 items-center rounded-md border-2 border-[var(--border)] px-8 text-lg"
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* Es allein noch einmal versuchen.
|
||||
*
|
||||
* Die Offline-Seite erscheint auch dann, wenn nur eine einzelne Anfrage
|
||||
* unterwegs abgebrochen ist — ein kurzer Aussetzer des Repeaters genügt.
|
||||
* Ohne diesen Baustein bliebe das Terminal danach auf dieser Seite stehen,
|
||||
* bis jemand vorbeikommt und tippt. Am Hallenmonitor, den niemand bedient,
|
||||
* hieße das: bis zum nächsten Dienstabend.
|
||||
*
|
||||
* Also versucht die Seite es selbst — sofort, wenn der Browser wieder Netz
|
||||
* meldet, und sonst alle paar Sekunden.
|
||||
*/
|
||||
const ABSTAND_MS = 10_000;
|
||||
|
||||
export function ErneutVersuchen() {
|
||||
const [versuche, setVersuche] = React.useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
const nochmal = () => {
|
||||
setVersuche((wert) => wert + 1);
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
window.addEventListener("online", nochmal);
|
||||
const zeitgeber = setInterval(() => {
|
||||
// Ohne Netz spart der Versuch nichts — dann wartet die Seite auf das
|
||||
// "online"-Ereignis darüber.
|
||||
if (navigator.onLine) nochmal();
|
||||
}, ABSTAND_MS);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("online", nochmal);
|
||||
clearInterval(zeitgeber);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<p className="text-[var(--muted-foreground)]" role="status" data-testid="offline-wiederholung">
|
||||
Das Terminal versucht es alle {ABSTAND_MS / 1000} Sekunden von selbst
|
||||
{versuche > 0 ? ` (${versuche}. Versuch)` : ""}.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user