v1.1.0: session guard on all game routes + register + sign-in screen (ISS-107)
CI / build + unit + e2e (pull_request) Failing after 26m20s

This commit is contained in:
2026-09-26 14:40:56 +00:00
parent 21dd37f88c
commit b0f1bd8b67
54 changed files with 1002 additions and 91 deletions
+8 -3
View File
@@ -13,6 +13,7 @@ import { weatherFor } from '../lib/weather';
import { approxLocalTime } from '../lib/localTime';
import Modal from './Modal';
import AdminPanel from './AdminPanel';
import { sessionHeaders } from '../lib/authClient';
// v0.70.0 default view: null island [0,0] at zoom 2 — the world is 2048 px wide there and the
// Africa+Europe bounding box (lat −35..+71, lon −18..+52) spans ~800 px vertically in Web Mercator,
@@ -69,11 +70,14 @@ interface MapProps {
// ISS-010 (v0.18.0): push an action endpoint's full response snapshot into the shared
// shell state — same callback RightPane receives, used by the airport popup's Relocate row.
applySnapshot: (snapshot: StateSnapshot) => void;
// v1.1.0 (ISS-107): the admin panel's Log out cleared the session — tell the shell to drop back
// to the sign-in screen instead of leaving a signed-out user staring at a live dashboard.
onLogout?: () => void;
}
// Named FlightMap (not Map): a component called `Map` would shadow the global
// Map constructor inside its own body, breaking `new Map(...)` for the airport index.
export default function FlightMap({ state, hovered, applySnapshot }: MapProps) {
export default function FlightMap({ state, hovered, applySnapshot, onLogout }: MapProps) {
const containerRef = useRef<HTMLDivElement>(null);
const mapRef = useRef<maplibregl.Map | null>(null);
// /api/airports is fetched at most once per page life: every styledata event
@@ -295,7 +299,8 @@ export default function FlightMap({ state, hovered, applySnapshot }: MapProps) {
const action = planeStatus === 'available' ? 'fly' : 'queue';
const res = await fetch(`/api/planes/${planeId}/${action}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
// v1.1.0 (ISS-107): fly/queue are session-guarded — echo the stored id.
headers: { 'Content-Type': 'application/json', ...sessionHeaders() },
body: JSON.stringify({ destIcao: p.icao }),
cache: 'no-store',
});
@@ -591,7 +596,7 @@ export default function FlightMap({ state, hovered, applySnapshot }: MapProps) {
</header>
<div ref={containerRef} data-testid="map" className="map-container" />
<Modal open={adminOpen} onClose={() => setAdminOpen(false)} title="Admin">
<AdminPanel />
<AdminPanel onLogout={onLogout} />
</Modal>
</div>
);