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
33
frontend/src/hooks/usePlayerColors.ts
Normal file
33
frontend/src/hooks/usePlayerColors.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { useRef, useCallback } from 'react';
|
||||
|
||||
// Matches v1 script.js PALETTE — 30 accessible colors
|
||||
const PALETTE = [
|
||||
'#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd','#8c564b','#e377c2','#7f7f7f',
|
||||
'#bcbd22','#17becf','#aec7e8','#ffbb78','#98df8a','#ff9896','#c5b0d5','#c49c94',
|
||||
'#f7b6d2','#c7c7c7','#dbdb8d','#9edae5','#393b79','#637939','#8c6d31','#843c39',
|
||||
'#7b4173','#5254a3','#6b6ecf','#9c9ede','#d6616b','#ce6dbd',
|
||||
];
|
||||
|
||||
function hashColor(name: string): string {
|
||||
let h = 0;
|
||||
for (let i = 0; i < name.length; i++) h = ((h << 5) - h + name.charCodeAt(i)) | 0;
|
||||
return `hsl(${Math.abs(h) % 360}, 72%, 50%)`;
|
||||
}
|
||||
|
||||
export function usePlayerColors() {
|
||||
const mapRef = useRef(new Map<string, string>());
|
||||
const idxRef = useRef(0);
|
||||
|
||||
const getColor = useCallback((name: string): string => {
|
||||
let c = mapRef.current.get(name);
|
||||
if (!c) {
|
||||
c = idxRef.current < PALETTE.length
|
||||
? PALETTE[idxRef.current++]
|
||||
: hashColor(name);
|
||||
mapRef.current.set(name, c);
|
||||
}
|
||||
return c;
|
||||
}, []);
|
||||
|
||||
return getColor;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue