fix(v2): character window now updates live from WebSocket

The CharacterWindow only fetched once from API on mount and never
updated. Now:
- character_stats WS messages are tracked in useLiveData via ref
- Passed through WindowRenderer to CharacterWindow as liveStats prop
- Window uses live WS data when available, falls back to API fetch
- Attributes, skills, vitals base values, properties (augmentations,
  ratings, etc.), allegiance all update in real-time

Also: vitals bars in the character window use live WS vitals data
(health_percentage etc.) for real-time HP/Stamina/Mana display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-14 16:02:49 +02:00
parent a5bd659876
commit d2c30b610b
30 changed files with 115 additions and 54 deletions

View file

@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { DraggableWindow } from './DraggableWindow';
import { apiFetch } from '../../api/client';
interface Props { id: string; charName: string; zIndex: number; vitals?: any; }
interface Props { id: string; charName: string; zIndex: number; vitals?: any; liveStats?: any; }
// Property ID maps — verbatim from v1 script.js lines 1843-1876
const TS_AUGMENTATIONS: Record<number, string> = {
@ -49,15 +49,19 @@ function societyRank(v: number): string {
const gold = '#af7a30';
const navy = '#000022';
export const CharacterWindow: React.FC<Props> = ({ id, charName, zIndex, vitals }) => {
const [data, setData] = useState<any>(null);
export const CharacterWindow: React.FC<Props> = ({ id, charName, zIndex, vitals, liveStats }) => {
const [fetchedData, setFetchedData] = useState<any>(null);
const [leftTab, setLeftTab] = useState(0);
const [rightTab, setRightTab] = useState(0);
// Initial fetch from API
useEffect(() => {
apiFetch<any>(`/character-stats/${encodeURIComponent(charName)}`).then(setData).catch(() => {});
apiFetch<any>(`/character-stats/${encodeURIComponent(charName)}`).then(setFetchedData).catch(() => {});
}, [charName]);
// Use live WS data if available (more current), fall back to API fetch
const data = liveStats || fetchedData;
const fmt = (n: any) => n != null ? Number(n).toLocaleString() : '\u2014';
const sd = data?.stats_data || data || {};
const attrs = sd.attributes || {};