Hustler-Pixelwelt T13: Korrekturen Hochhaus (Fokus, Tastatur, weniger Bewegung, Handy-Tippflächen, Schnee per transform, Pause überall, Seite ohne Leerlauf-Blitz)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-22 09:47:57 +00:00
1 parent 0924a8d2ae
commit 5e6698f5e0
14 files changed
+994 -52

No files matched your search

+39 -14
View File
@@ -1,21 +1,43 @@
import { useRef, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import HochhausKopf from './HochhausKopf'
import HochhausWelt from './HochhausWelt'
import HustlerDialog from './HustlerDialog'
import RegieEbene from './RegieEbene'
// Von welchem Bildschirm man zurückkommt -> Etage, über die man gegangen war (Freigabe-Pult über die Etage „freigabe“, Keller über „keller“)
const ETAGE_NACH_TAB = Object.freeze({ freigabe: 'freigabe', botleads: 'keller' })
// Überschrift der Seite, nur für Screenreader (Pult und Keller haben ihre eigene sichtbare Überschrift)
function Ueberschrift() {
return <h1 className="hk-nur-sr">Hustler – Hochhaus</h1>
}
// Bildschirm „Hochhaus“: Spielwelt mit Regie-Ebene (T5, T8), Kopfzeile (T6) und Detailansicht eines Hustlers (T7). Zustände wie bisher im WorkersBoard.
// Reine Darstellung ohne Auth-Bezug: isAdmin, der Feed (feed = { state, error, loaded, refresh }), die Hustler-Tabelle (workers), die Regie-Anbindung
// (regieRef, die Seite ruft regieRef.current.push(events) bei neuen Ereignissen) und der Bildschirmwechsel (onOpen(tab)) kommen von der Seite.
// (regieRef, die Seite ruft regieRef.current.push(events) bei neuen Ereignissen), der Bildschirmwechsel (onOpen(tab)) und vonTab (der Bildschirm, von dem man
// zurückkommt: 'freigabe' | 'botleads' | null) kommen von der Seite. Beim Zurückkommen bekommt die Etage, über die man gegangen war, den Fokus (M2).
// Die Kopfzeile steht im DOM vor der Welt, damit die Tab-Reihenfolge oben beginnt (M7); über der Welt liegt sie per z-index.
// Kein CSS-Import und keine Bilder: die Stile hängt WorkersPage ein (Regeln dieser Datei in styles/hustler/hustler-ui.css).
export default function Hochhaus({ api, isAdmin, feed, workers, regieRef, onOpen }) {
export default function Hochhaus({ api, isAdmin, feed, workers, regieRef, onOpen, vonTab = null }) {
const wurzelRef = useRef(null)
const weltRef = useRef(null)
const [auswahl, setAuswahl] = useState(null) // workerId der offenen Detailansicht (null = keine)
const ready = feed.loaded && Boolean(feed.state)
// Rückweg aus Pult oder Keller: Fokus auf die Etage, über die man ging (erst wenn die Welt steht; die Kamera holt sie bei Tastaturfokus ins Bild)
useEffect(() => {
if (!ready || !vonTab || !Object.hasOwn(ETAGE_NACH_TAB, vonTab)) return
const wurzel = wurzelRef.current
if (!wurzel || typeof wurzel.querySelector !== 'function') return
const etage = wurzel.querySelector(`[data-hk-etage="${ETAGE_NACH_TAB[vonTab]}"]`)
if (etage && typeof etage.focus === 'function') etage.focus({ preventScroll: true })
}, [ready, vonTab])
// Dienst noch nie erreicht: Pixel-Leerzustand mit Fehlertext und „Neu laden“
if (!ready && feed.error) {
return (
<div className="hk-hochhaus">
<div className="hk-hochhaus" ref={wurzelRef}>
<Ueberschrift />
<div className="hk-leer">
<strong className="hk-leer-titel">Der Hustler-Dienst ist noch nicht erreichbar</strong>
<p className="hk-leer-text">{feed.error}</p>
@@ -26,7 +48,8 @@ export default function Hochhaus({ api, isAdmin, feed, workers, regieRef, onOpen
}
if (!ready) {
return (
<div className="hk-hochhaus">
<div className="hk-hochhaus" ref={wurzelRef}>
<Ueberschrift />
<div className="hk-laden" role="status">Wird geladen …</div>
</div>
)
@@ -35,7 +58,16 @@ export default function Hochhaus({ api, isAdmin, feed, workers, regieRef, onOpen
// Die Regie-Ebene liegt in der skalierten Bühne (Weltkoordinaten); ihr Handle ist regieRef der Seite, die neue Ereignisse hineinreicht.
// Solange die Detailansicht offen ist, ruhen Rad, Ziehen und Tasten der Kamera (gesperrt).
return (
<div className="hk-hochhaus">
<div className="hk-hochhaus" ref={wurzelRef}>
<Ueberschrift />
<HochhausKopf
api={api}
isAdmin={isAdmin}
state={feed.state}
error={feed.error}
refresh={feed.refresh}
onGanz={() => { if (weltRef.current) weltRef.current.ganz() }}
/>
<HochhausWelt
ref={weltRef}
state={feed.state}
@@ -46,19 +78,12 @@ export default function Hochhaus({ api, isAdmin, feed, workers, regieRef, onOpen
>
<RegieEbene ref={regieRef} />
</HochhausWelt>
<HochhausKopf
api={api}
isAdmin={isAdmin}
state={feed.state}
error={feed.error}
refresh={feed.refresh}
onGanz={() => { if (weltRef.current) weltRef.current.ganz() }}
/>
{auswahl !== null && (
<HustlerDialog
api={api}
workerId={auswahl}
workers={workers}
paused={feed.state?.paused === true}
onClose={() => setAuswahl(null)}
onWechsel={setAuswahl}
/>