refactor: use TelemetryReadout and EntityCard components
Both were built and tested but never wired in — SeancePage.tsx was reimplementing the same markup inline. Removes the duplication.
This commit is contained in:
@@ -22,6 +22,8 @@ import { PlanchetteBoard } from '../components/PlanchetteBoard'
|
||||
import { MatrixView } from '../components/MatrixView'
|
||||
import { GraphView } from '../components/GraphView'
|
||||
import { Transcript } from '../components/Transcript'
|
||||
import { EntityCard } from '../components/EntityCard'
|
||||
import { TelemetryReadout } from '../components/TelemetryReadout'
|
||||
import { PlanchetteMachine } from '../lib/planchette'
|
||||
import type { PlanchetteSnapshot } from '../lib/planchette'
|
||||
import { EvpListener } from '../lib/evp'
|
||||
@@ -335,90 +337,12 @@ function SeanceSession({ username }: { username: string }) {
|
||||
</section>
|
||||
|
||||
<aside className="seance-side">
|
||||
{entity ? (
|
||||
<section className={`spirit-dossier ${dossierOpen ? 'open' : 'closed'}`}>
|
||||
<button
|
||||
type="button"
|
||||
className="dossier-header"
|
||||
onClick={() => setDossierOpen((o) => !o)}
|
||||
aria-expanded={dossierOpen}
|
||||
>
|
||||
<span className="dossier-title">{t('seance.entity.title')}</span>
|
||||
<span className="dossier-chevron" aria-hidden>
|
||||
{dossierOpen ? '▾' : '◂'}
|
||||
</span>
|
||||
</button>
|
||||
{dossierOpen && (
|
||||
<div className="dossier-body">
|
||||
<h3 className="dossier-name" style={{ color: `hsl(${entity.visual.hue} 85% 78%)` }}>
|
||||
{entity.name}
|
||||
</h3>
|
||||
<p className="dossier-epithet">{entity.epithet}</p>
|
||||
<div className="dossier-badges">
|
||||
<span className={`rarity-badge rarity-${entity.rarity}`}>
|
||||
{t(`seance.entity.rarity.${entity.rarity}`)}
|
||||
</span>
|
||||
{state.entityIsNew ? (
|
||||
<span className="dossier-badge badge-new">{t('seance.entity.isNew')}</span>
|
||||
) : (
|
||||
<span className="dossier-badge badge-known">
|
||||
{t('seance.entity.known', { count: entity.contact_count })}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="dossier-section">
|
||||
<h4>{t('seance.entity.persona')}</h4>
|
||||
<p className="dossier-persona">{entity.persona}</p>
|
||||
</div>
|
||||
|
||||
<div className="dossier-section">
|
||||
<h4>{t('seance.entity.voice')}</h4>
|
||||
<dl className="voice-params">
|
||||
<div>
|
||||
<dt>id</dt>
|
||||
<dd>{entity.voice.voice_id}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>pitch</dt>
|
||||
<dd>{entity.voice.pitch.toFixed(2)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>rate</dt>
|
||||
<dd>{entity.voice.rate.toFixed(2)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>noise</dt>
|
||||
<dd>{entity.voice.noise.toFixed(2)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>echo</dt>
|
||||
<dd>{entity.voice.echo.toFixed(2)}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
{entity.quotes.length > 0 && (
|
||||
<div className="dossier-section">
|
||||
<h4>{t('seance.entity.quotes')}</h4>
|
||||
<ul className="dossier-quotes">
|
||||
{entity.quotes.slice(0, 4).map((q, i) => (
|
||||
<li key={i}>“{q}”</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
) : (
|
||||
<section className="spirit-dossier empty">
|
||||
<div className="dossier-body">
|
||||
<p className="dossier-none">{t('seance.entity.none')}</p>
|
||||
<p className="dossier-nonehint dim">{t('seance.entity.noneHint')}</p>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
<EntityCard
|
||||
entity={entity}
|
||||
isNew={state.entityIsNew}
|
||||
open={dossierOpen}
|
||||
onToggleOpen={() => setDossierOpen((o) => !o)}
|
||||
/>
|
||||
|
||||
<section className="mode-panel">
|
||||
{state.mode === 'wire' && <WirePanel />}
|
||||
@@ -519,41 +443,10 @@ function ToastCard({ toast, onDismiss }: { toast: Toast; onDismiss: (id: number)
|
||||
function WirePanel() {
|
||||
const { state } = useSeance()
|
||||
const { t } = useTranslation()
|
||||
const tel = state.telemetry
|
||||
|
||||
return (
|
||||
<div className="wire-panel">
|
||||
<h4 className="panel-title">{t('seance.telemetry.title')}</h4>
|
||||
{tel ? (
|
||||
<div className="telemetry-grid">
|
||||
<div className="tel-row">
|
||||
<span className="tel-key">{t('seance.telemetry.jitter')}</span>
|
||||
<span className="tel-val flicker-soft">
|
||||
{tel.jitter_bytes_per_s.toFixed(1)} {t('seance.telemetry.units.bytes')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tel-row">
|
||||
<span className="tel-key">{t('seance.telemetry.latencyVar')}</span>
|
||||
<span className="tel-val flicker-soft">
|
||||
{tel.latency_variance_ms.toFixed(2)} {t('seance.telemetry.units.ms')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tel-row">
|
||||
<span className="tel-key">{t('seance.telemetry.latencyMean')}</span>
|
||||
<span className="tel-val flicker-soft">
|
||||
{tel.latency_mean_ms.toFixed(1)} {t('seance.telemetry.units.ms')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="tel-row">
|
||||
<span className="tel-key">{t('seance.telemetry.dns')}</span>
|
||||
<span className="tel-val flicker-soft">
|
||||
{tel.dns_ms.toFixed(1)} {t('seance.telemetry.units.ms')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p className="dim flicker">{t('common.loading')}</p>
|
||||
)}
|
||||
<TelemetryReadout telemetry={state.telemetry} />
|
||||
<p className="wire-count">{t('seance.anomaly.count', { count: state.anomalyCount })}</p>
|
||||
{!state.passive && (
|
||||
<p className="wire-hint dim">
|
||||
|
||||
Reference in New Issue
Block a user