feat: option
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
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, useValidateSaxoWatchlist, useSaxoCatalog, useSaxoCatalogSummary, useRefreshSaxoCatalog, useTestSaxoQuote, type CycleStepDef } from '../hooks/useApi'
|
||||
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, useSaxoCatalog, useSaxoCatalogSummary, useRefreshSaxoCatalog, useTestSaxoQuote, useSaxoSettings, useUpdateSaxoSettings, useSnapshotAllSaxoNow, 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'
|
||||
|
||||
@@ -430,6 +430,9 @@ function SaxoConnectionCard() {
|
||||
const { data: validation, refetch: runValidation, isFetching: validating } = useValidateSaxoWatchlist()
|
||||
const { data: catalogSummary } = useSaxoCatalogSummary()
|
||||
const refreshCatalog = useRefreshSaxoCatalog()
|
||||
const { data: settings } = useSaxoSettings()
|
||||
const updateSettings = useUpdateSaxoSettings()
|
||||
const snapshotAllNow = useSnapshotAllSaxoNow()
|
||||
const [input, setInput] = useState('')
|
||||
const [snapMsg, setSnapMsg] = useState('')
|
||||
const { data: catalogMatches } = useSaxoCatalog(undefined, input.length >= 2 ? input : undefined)
|
||||
@@ -470,6 +473,17 @@ function SaxoConnectionCard() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleSnapshotAllNow = async () => {
|
||||
setSnapMsg('')
|
||||
try {
|
||||
const r = await snapshotAllNow.mutateAsync()
|
||||
const total = Object.values(r.results).reduce((a, b) => a + b, 0)
|
||||
setSnapMsg(`✓ Watchlist entière — ${total} lignes enregistrées (${Object.keys(r.results).length} symboles)`)
|
||||
} catch (e: any) {
|
||||
setSnapMsg(`✗ ${e?.response?.data?.detail ?? 'échec'}`)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
@@ -517,10 +531,25 @@ function SaxoConnectionCard() {
|
||||
</div>
|
||||
|
||||
<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 className="text-xs text-slate-500 flex items-center gap-2">
|
||||
<span>Watchlist snapshotée toutes les</span>
|
||||
<input
|
||||
type="number" min={1} max={120}
|
||||
value={settings?.snapshot_minutes ?? ''}
|
||||
onChange={e => updateSettings.mutate(parseFloat(e.target.value) || 5)}
|
||||
className="w-14 bg-dark-800 border border-slate-700/40 rounded px-1.5 py-0.5 text-xs text-white text-center"
|
||||
/>
|
||||
<span>min (historique Date/Spot/Expiry/Strike/Bid/Ask/Mid/VolatilityPct/Greeks) :</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<button
|
||||
onClick={handleSnapshotAllNow}
|
||||
disabled={!status?.connected || snapshotAllNow.isPending}
|
||||
title="Snapshot immédiat de toute la watchlist, sans attendre le prochain cycle"
|
||||
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"
|
||||
>
|
||||
<RefreshCw className={clsx('w-3.5 h-3.5', snapshotAllNow.isPending && 'animate-spin')} /> Rafraîchir maintenant
|
||||
</button>
|
||||
<button
|
||||
onClick={() => runValidation()}
|
||||
disabled={!status?.connected || validating}
|
||||
|
||||
Reference in New Issue
Block a user