MosswartOverlord/frontend/src/App.tsx
Erik 5bda2b64f4 feat(dashboard): open Player Dashboard in a new tab
The 👥 Dashboard button used to open the player table as a draggable
in-app window, which competed for screen space with the map. It now
opens in a separate browser tab as a fullscreen page so users can put
the dashboard on a second monitor.

How:
- App.tsx branches on ?view=dashboard → renders PlayerDashboardFullPage
  (new file in components/) instead of the default MapLayout.
- SidebarWindowButtons.tsx: 👥 Dashboard onClick now does
  window.open('/?view=dashboard', '_blank', 'noopener'). Label shows
  '↗' so users know it's an external open.
- PlayerDashboardWindow.tsx refactored: extracted the sortable table
  body into a reusable PlayerDashboardContent component. The old window
  shell stays registered in WindowRenderer for backward compat — just
  no longer reachable from the default sidebar.
- map-layout.css: new .ml-dashboard-page rules for fullscreen layout.

Each tab gets its own useLiveData + WebSocket connection (server
already handles multiple browser clients). The new tab inherits the
session cookie from the original tab — no re-login.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-23 19:31:26 +02:00

28 lines
1,009 B
TypeScript

import { MapLayout } from './components/map/MapLayout';
import { PlayerDashboardFullPage } from './components/PlayerDashboardFullPage';
import { useLiveData } from './hooks/useLiveData';
import './styles/map-layout.css';
/**
* Single SPA entry. Branches on `?view=` query param:
* /?view=dashboard → fullscreen PlayerDashboardFullPage (new-tab target)
* / → default map + sidebar layout
*
* We don't pull in react-router for one extra view — when a third view
* appears, swap this for proper routing.
*/
export default function App() {
const view = new URLSearchParams(window.location.search).get('view');
if (view === 'dashboard') {
return <PlayerDashboardFullPage />;
}
// Default: full app with map + sidebar.
return <DefaultApp />;
}
/** Default map-and-sidebar layout. Split out so the dashboard tab doesn't
* spin up useLiveData twice for the same render. */
function DefaultApp() {
const data = useLiveData();
return <MapLayout data={data} />;
}