feat(v2): Phase 1 — map-first layout matching v1
Rebuilds the v1 map-centric experience in React: Layout: - 400px sidebar on left, interactive map on right (flex, 100vh) - Exact same proportions and dark theme as v1 Sidebar (top→bottom): - Header with active player count + Dashboard toggle button - Server status dot (Coldeve online/offline with pulse) - Aggregate counters: Rares (gold), Server KPH (blue glow), Kills (red) - 6 sort buttons (Name, KPH, S.Kills, S.Rares, T.Kills, KPR) - Player name filter - Scrollable player list with per-row: - Name + coordinates - HP/Stamina/Mana vital bars (red/orange/blue gradients) - Session kills, total kills, KPH - Session rares, total rares, VTank meta state pill - Online time, deaths, prismatic tapers - Color-coded left border per player Map: - dereth.png with CSS transform pan (drag) + zoom (wheel, 1.1x factor, max 20x) - Player dots (6px circles, color-matched to sidebar) - Hover tooltip (name, coords, kph, kills) - World coordinate display at cursor position - Fit-to-window on first load View toggle: Map View ↔ Dashboard with localStorage persistence. All v1 CSS ported under ml-* prefix, scoped via map-layout.css. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3791c01bf3
commit
2c4b8d3afb
16 changed files with 995 additions and 151 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import { useState } from 'react';
|
||||
import { Layout } from './components/Layout';
|
||||
import { GlobalStats } from './components/GlobalStats';
|
||||
import { CharacterGrid } from './components/CharacterGrid';
|
||||
|
|
@ -6,44 +7,43 @@ import { CombatTab } from './components/tabs/CombatTab';
|
|||
import { RaresTab } from './components/tabs/RaresTab';
|
||||
import { MapTab } from './components/tabs/MapTab';
|
||||
import { InventoryTab } from './components/tabs/InventoryTab';
|
||||
import { MapLayout } from './components/map/MapLayout';
|
||||
import { useLiveData } from './hooks/useLiveData';
|
||||
import './styles/global.css';
|
||||
import './styles/map-layout.css';
|
||||
|
||||
type ViewMode = 'map' | 'dashboard';
|
||||
|
||||
export default function App() {
|
||||
const { characters, serverHealth, totalRares, totalKills, recentRares } = useLiveData();
|
||||
const [viewMode, setViewMode] = useState<ViewMode>(
|
||||
() => (localStorage.getItem('v2-view') as ViewMode) || 'map'
|
||||
);
|
||||
const data = useLiveData();
|
||||
|
||||
const toggleView = () => {
|
||||
const next = viewMode === 'map' ? 'dashboard' : 'map';
|
||||
setViewMode(next);
|
||||
localStorage.setItem('v2-view', next);
|
||||
};
|
||||
|
||||
if (viewMode === 'map') {
|
||||
return <MapLayout data={data} onViewToggle={toggleView} />;
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
id: 'combat',
|
||||
label: 'Combat',
|
||||
content: <CombatTab characters={characters} />,
|
||||
},
|
||||
{
|
||||
id: 'rares',
|
||||
label: 'Rares',
|
||||
content: <RaresTab characters={characters} totalRares={totalRares} totalKills={totalKills} recentRares={recentRares} />,
|
||||
},
|
||||
{
|
||||
id: 'map',
|
||||
label: 'Map',
|
||||
content: <MapTab characters={characters} />,
|
||||
},
|
||||
{
|
||||
id: 'inventory',
|
||||
label: 'Inventory',
|
||||
content: <InventoryTab />,
|
||||
},
|
||||
{ id: 'combat', label: 'Combat', content: <CombatTab characters={data.characters} /> },
|
||||
{ id: 'rares', label: 'Rares', content: <RaresTab characters={data.characters} totalRares={data.totalRares} totalKills={data.totalKills} recentRares={data.recentRares} /> },
|
||||
{ id: 'map', label: 'Map', content: <MapTab characters={data.characters} /> },
|
||||
{ id: 'inventory', label: 'Inventory', content: <InventoryTab /> },
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<GlobalStats
|
||||
activeChars={characters.size}
|
||||
totalKills={totalKills}
|
||||
totalRares={totalRares}
|
||||
serverHealth={serverHealth}
|
||||
/>
|
||||
<CharacterGrid characters={characters} />
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 8 }}>
|
||||
<button onClick={toggleView} className="tab-btn">Map View</button>
|
||||
</div>
|
||||
<GlobalStats activeChars={data.characters.size} totalKills={data.totalKills} totalRares={data.totalRares} serverHealth={data.serverHealth} />
|
||||
<CharacterGrid characters={data.characters} />
|
||||
<TabContainer tabs={tabs} />
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue