Files
Webklar/src/components/home/demos/steuerung.tsx
T
rootandClaude Opus 5.5 a23f2e52c2 Relaunch: Station Öffnungszeiten live
Vierter Eintrag der Funktionen-Gruppe (nach der News-Pinnwand, „Bald verfügbar“, ohne Preis):
- Website: Bäckerei Sonnenschein mit großer Status-Pille und Hinweis-Leiste „Betriebsurlaub 12.–26. Oktober“
  (gleitet per transform ein, der Inhalt rückt nach), Desktop und Handy.
- Handy-Ebene: Finger tippt „Hinweis-Leiste anlegen“ (HINWEIS_PUNKT, Platzhalter bis zur Aufnahme).
- Uhr-Regler: echter Schieberegler unter dem MacBook (inaktiv: aria-hidden + inert) und in der Handy-Karte.
- ZeitenSteuerung (setzeUhr(null) beim Verlassen), lazy-Chunks, Kundenportal importiert aus ablauf.ts nur Typen.
- Pins in relaunch-kundenportal.test.tsx auf neun Stationen angepasst (Als App = Marke 8), Spezifikations-Zähler mitgezogen.

ACHTUNG: public/relaunch/portal/phone-12-zeiten-{390,780}.webp sind vorläufig Kopien von phone-9-termine
(damit Build und Tests laufen); Task 36 ersetzt sie durch die echte Aufnahme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 08:05:49 +00:00

71 lines
2.9 KiB
TypeScript

import { memo, useEffect } from "react";
import { useTerminAblauf, type TerminZustand } from "./termin/ablauf";
import { useHeatmapAblauf, type HeatmapZustand } from "./heatmap/ablauf";
import { usePinnwandAblauf, type PinnwandZustand } from "./pinnwand/ablauf";
import { useChatAblauf, type ChatZustand } from "./chat/ablauf";
import { useZeitenAblauf, type ZeitenZustand } from "./zeiten/ablauf";
/**
* Taktgeber der Demos (vier Funktionen und der Chat) als unsichtbare Bauteile (rendern nichts, melden nur ihren Zustand).
* Sie liegen in einem eigenen Chunk, damit die Startseite die Ablauf-Logik erst lädt, wenn die Kundenportal-Bühne
* eine Demo-Station fast erreicht (Spezifikation 4). Die Bühne hält den gemeldeten Zustand und gibt denselben
* Zustand an Website, Handy-Ebene und Diagnose.
* `laeuft` und `statisch` kommen von useDemoLauf (Station aktiv, im Bild, Tab sichtbar, Bewegung erlaubt).
* Die Bauteile sind memoisiert: sie rechnen nur neu, wenn sich ihr eigener Ablauf bewegt, nicht bei jedem Rendern der Bühne.
*/
type Props<Z> = { laeuft: boolean; statisch: boolean; onZustand: (zustand: Z) => void };
export const TerminSteuerung = memo(function TerminSteuerung({ laeuft, statisch, onZustand }: Props<TerminZustand>) {
const zustand = useTerminAblauf(laeuft, statisch);
useEffect(() => onZustand(zustand), [zustand, onZustand]);
return null;
});
export const PinnwandSteuerung = memo(function PinnwandSteuerung({ laeuft, statisch, onZustand }: Props<PinnwandZustand>) {
const zustand = usePinnwandAblauf(laeuft, statisch);
useEffect(() => onZustand(zustand), [zustand, onZustand]);
return null;
});
export const ChatSteuerung = memo(function ChatSteuerung({ laeuft, statisch, onZustand }: Props<ChatZustand>) {
const zustand = useChatAblauf(laeuft, statisch);
useEffect(() => onZustand(zustand), [zustand, onZustand]);
return null;
});
/** `aktiv`: Station ist die aktive; sonst bleiben weder Maus-Zustand noch Auswahl der Heatmap hängen. */
export const HeatmapSteuerung = memo(function HeatmapSteuerung({
laeuft,
statisch,
aktiv,
onZustand,
}: Props<HeatmapZustand> & { aktiv: boolean }) {
const zustand = useHeatmapAblauf(laeuft, statisch);
const { setzeMaus, waehle } = zustand;
useEffect(() => {
if (!aktiv) {
setzeMaus(false);
waehle(null);
}
}, [aktiv, setzeMaus, waehle]);
useEffect(() => onZustand(zustand), [zustand, onZustand]);
return null;
});
/** `aktiv`: Station ist die aktive; sonst geht eine Bedienung des Uhr-Reglers zurück an den Ablauf (beim nächsten Mal von vorn). */
export const ZeitenSteuerung = memo(function ZeitenSteuerung({
laeuft,
statisch,
aktiv,
onZustand,
}: Props<ZeitenZustand> & { aktiv: boolean }) {
const zustand = useZeitenAblauf(laeuft, statisch);
const { setzeUhr } = zustand;
useEffect(() => {
if (!aktiv) setzeUhr(null);
}, [aktiv, setzeUhr]);
useEffect(() => onZustand(zustand), [zustand, onZustand]);
return null;
});