feat: saxo history
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useSources, useUpdateSources, useUpdateApiKeys, useConfig, useAiStatus, useAnalysisConfig, useSaveAnalysisConfig, useCycleStatus, useUpdateCycleConfig, useTriggerCycle, useCycleStepCatalog, useRiskProfiles, useUpsertProfile, useDeleteProfile, useExitDefaults, useSaveExitDefaults, useOptionsGate, useSaveOptionsGate, useTechIndicatorsConfig, useSaveTechIndicatorsConfig, useInstrumentsWatchlist, useAddWatchlistInstrument, useRemoveWatchlistInstrument, validateTicker, useSaxoStatus, useDisconnectSaxo, useSaxoWatchlist, useUpdateSaxoWatchlist, useSnapshotSaxoNow, type CycleStepDef } from '../hooks/useApi'
|
||||
import { Settings, Key, Globe, CheckCircle, XCircle, AlertCircle, Save, Eye, EyeOff, Brain, SlidersHorizontal, RefreshCw, Zap, Plus, Trash2, Pencil, X, Lock, Gauge, DollarSign, TrendingUp, ShieldAlert, DatabaseBackup, Radar, Link2, Unlink, Camera } from 'lucide-react'
|
||||
import { useSources, useUpdateSources, useUpdateApiKeys, useConfig, useAiStatus, useAnalysisConfig, useSaveAnalysisConfig, useCycleStatus, useUpdateCycleConfig, useTriggerCycle, useCycleStepCatalog, useRiskProfiles, useUpsertProfile, useDeleteProfile, useExitDefaults, useSaveExitDefaults, useOptionsGate, useSaveOptionsGate, useTechIndicatorsConfig, useSaveTechIndicatorsConfig, useInstrumentsWatchlist, useAddWatchlistInstrument, useRemoveWatchlistInstrument, validateTicker, useSaxoStatus, useDisconnectSaxo, useSaxoWatchlist, useUpdateSaxoWatchlist, useSnapshotSaxoNow, useValidateSaxoWatchlist, type CycleStepDef } from '../hooks/useApi'
|
||||
import { Settings, Key, Globe, CheckCircle, XCircle, AlertCircle, Save, Eye, EyeOff, Brain, SlidersHorizontal, RefreshCw, Zap, Plus, Trash2, Pencil, X, Lock, Gauge, DollarSign, TrendingUp, ShieldAlert, DatabaseBackup, Radar, Link2, Unlink, Camera, ShieldCheck, ExternalLink } from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
const API = ''
|
||||
@@ -426,6 +427,7 @@ function SaxoConnectionCard() {
|
||||
const disconnect = useDisconnectSaxo()
|
||||
const updateWatchlist = useUpdateSaxoWatchlist()
|
||||
const snapshotNow = useSnapshotSaxoNow()
|
||||
const { data: validation, refetch: runValidation, isFetching: validating } = useValidateSaxoWatchlist()
|
||||
const [input, setInput] = useState('')
|
||||
const [snapMsg, setSnapMsg] = useState('')
|
||||
|
||||
@@ -508,8 +510,23 @@ function SaxoConnectionCard() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-slate-500 mb-2">
|
||||
Watchlist snapshotée périodiquement (historique Date/Spot/Expiry/Strike/Bid/Ask/Mid/VolatilityPct/Greeks) :
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="text-xs text-slate-500">
|
||||
Watchlist snapshotée périodiquement (historique Date/Spot/Expiry/Strike/Bid/Ask/Mid/VolatilityPct/Greeks) :
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => runValidation()}
|
||||
disabled={!status?.connected || validating}
|
||||
title="Vérifie que chaque symbole résout bien vers un vrai instrument Saxo"
|
||||
className="flex items-center gap-1 text-xs text-slate-400 hover:text-slate-200 border border-slate-700/50 px-2 py-1 rounded disabled:opacity-40"
|
||||
>
|
||||
<ShieldCheck className={clsx('w-3.5 h-3.5', validating && 'animate-pulse')} /> Vérifier l'orthographe
|
||||
</button>
|
||||
<Link to="/saxo-history" className="flex items-center gap-1 text-xs text-blue-400 hover:text-blue-300">
|
||||
<ExternalLink className="w-3.5 h-3.5" /> Historique
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<input
|
||||
@@ -525,15 +542,22 @@ function SaxoConnectionCard() {
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{symbols.map(sym => (
|
||||
<span key={sym} className="badge-blue flex items-center gap-1.5">
|
||||
{sym}
|
||||
<button onClick={() => handleSnapshotNow(sym)} title="Snapshot maintenant" className="hover:text-white">
|
||||
<Camera className="w-3 h-3" />
|
||||
</button>
|
||||
<button onClick={() => removeSymbol(sym)}><X className="w-3 h-3" /></button>
|
||||
</span>
|
||||
))}
|
||||
{symbols.map(sym => {
|
||||
const check = validation?.find(v => v.symbol === sym.toUpperCase())
|
||||
return (
|
||||
<span key={sym} className={clsx('badge flex items-center gap-1.5',
|
||||
check ? (check.valid ? 'badge-green' : 'badge-red') : 'badge-blue')}
|
||||
title={check && !check.valid ? check.error ?? 'Symbole non résolu par Saxo' : undefined}
|
||||
>
|
||||
{sym}
|
||||
{check && (check.valid ? <CheckCircle className="w-3 h-3" /> : <XCircle className="w-3 h-3" />)}
|
||||
<button onClick={() => handleSnapshotNow(sym)} title="Snapshot maintenant" className="hover:text-white">
|
||||
<Camera className="w-3 h-3" />
|
||||
</button>
|
||||
<button onClick={() => removeSymbol(sym)}><X className="w-3 h-3" /></button>
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{snapMsg && <div className="text-[10px] text-slate-500 mt-2">{snapMsg}</div>}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user