refactor(ui): normalize backtest replay controls
This commit is contained in:
parent
3d97e9a0d8
commit
e1d8ec8a7b
@ -558,13 +558,15 @@ export const BacktestComparePanel: React.FC<BacktestComparePanelProps> = ({ prof
|
|||||||
<td className="px-3 py-2 text-zinc-300">{(row.durationMs / 1000).toFixed(1)}s</td>
|
<td className="px-3 py-2 text-zinc-300">{(row.durationMs / 1000).toFixed(1)}s</td>
|
||||||
<td className="px-3 py-2">
|
<td className="px-3 py-2">
|
||||||
{row.status === 'success' && row.result ? (
|
{row.status === 'success' && row.result ? (
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
className="rounded-md bg-white/10 px-2 py-1 text-[10px] font-bold uppercase tracking-wide text-zinc-200 hover:bg-white/20"
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="min-h-7 px-2 text-[10px]"
|
||||||
onClick={() => setSelectedResultProfileId(row.profileId)}
|
onClick={() => setSelectedResultProfileId(row.profileId)}
|
||||||
>
|
>
|
||||||
Open
|
Open
|
||||||
</button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-[11px] text-rose-300">{row.error || 'Run failed'}</span>
|
<span className="text-[11px] text-rose-300">{row.error || 'Run failed'}</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|||||||
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, ReferenceLine } from 'recharts';
|
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, ReferenceLine } from 'recharts';
|
||||||
import type { BacktestResult } from '../types';
|
import type { BacktestResult } from '../types';
|
||||||
import { buildInsightCards, toEquitySeries } from '../utils';
|
import { buildInsightCards, toEquitySeries } from '../utils';
|
||||||
|
import { Button, Select } from '../../components/ui/Primitives';
|
||||||
|
|
||||||
interface BacktestResultsDashboardProps {
|
interface BacktestResultsDashboardProps {
|
||||||
result: BacktestResult;
|
result: BacktestResult;
|
||||||
@ -103,50 +104,55 @@ export const BacktestResultsDashboard: React.FC<BacktestResultsDashboardProps> =
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setIsPlaying(true)}
|
onClick={() => setIsPlaying(true)}
|
||||||
disabled={isPlaying || !equitySeries.length || isAtEnd}
|
disabled={isPlaying || !equitySeries.length || isAtEnd}
|
||||||
className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${isPlaying || isAtEnd ? 'bg-zinc-800 text-zinc-500' : 'bg-emerald-400 text-black hover:bg-emerald-300'}`}
|
size="sm"
|
||||||
>
|
>
|
||||||
Play
|
Play
|
||||||
</button>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setIsPlaying(false)}
|
onClick={() => setIsPlaying(false)}
|
||||||
disabled={!isPlaying}
|
disabled={!isPlaying}
|
||||||
className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${!isPlaying ? 'bg-zinc-800 text-zinc-500' : 'bg-zinc-200 text-black hover:bg-white'}`}
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
Pause
|
Pause
|
||||||
</button>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCursorIndex((prev) => Math.min(prev + 1, Math.max(0, equitySeries.length - 1)))}
|
onClick={() => setCursorIndex((prev) => Math.min(prev + 1, Math.max(0, equitySeries.length - 1)))}
|
||||||
disabled={!equitySeries.length || isAtEnd}
|
disabled={!equitySeries.length || isAtEnd}
|
||||||
className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${isAtEnd ? 'bg-zinc-800 text-zinc-500' : 'bg-indigo-400 text-black hover:bg-indigo-300'}`}
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
Step
|
Step
|
||||||
</button>
|
</Button>
|
||||||
<select
|
<Select
|
||||||
value={speed}
|
value={speed}
|
||||||
onChange={(event) => setSpeed(event.target.value as '1x' | '5x' | '20x' | 'instant')}
|
onChange={(event) => setSpeed(event.target.value as '1x' | '5x' | '20x' | 'instant')}
|
||||||
className="rounded-lg border border-white/10 bg-zinc-900 px-2 py-1 text-[11px] text-white"
|
controlSize="sm"
|
||||||
>
|
className="w-28"
|
||||||
<option value="1x">1x</option>
|
options={[
|
||||||
<option value="5x">5x</option>
|
{ value: '1x', label: '1x' },
|
||||||
<option value="20x">20x</option>
|
{ value: '5x', label: '5x' },
|
||||||
<option value="instant">Instant</option>
|
{ value: '20x', label: '20x' },
|
||||||
</select>
|
{ value: 'instant', label: 'Instant' },
|
||||||
<button
|
]}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
setCursorIndex(0);
|
setCursorIndex(0);
|
||||||
}}
|
}}
|
||||||
className="rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide bg-white/10 text-zinc-300 hover:bg-white/20"
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-xs text-cyan-100/90">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-xs text-cyan-100/90">
|
||||||
<div data-testid="backtest-replay-cursor">
|
<div data-testid="backtest-replay-cursor">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user