feat: event eco
This commit is contained in:
@@ -801,6 +801,7 @@ export default function Config() {
|
||||
const [fmpKey, setFmpKey] = useState('')
|
||||
const [teKey, setTeKey] = useState('')
|
||||
const [calendarRefreshH, setCalendarRefreshH] = useState(6)
|
||||
const [calendarScrapeRefreshH, setCalendarScrapeRefreshH] = useState(24)
|
||||
const [showKeys, setShowKeys] = useState(false)
|
||||
const [savedMsg, setSavedMsg] = useState('')
|
||||
const [configTab, setConfigTab] = useState<'ia' | 'cycle' | 'sources' | 'options' | 'profiles' | 'watchlist' | 'data'>('ia')
|
||||
@@ -930,6 +931,10 @@ export default function Config() {
|
||||
const h = parseFloat(config.calendar_refresh_h)
|
||||
if (!isNaN(h)) setCalendarRefreshH(h)
|
||||
}
|
||||
if (config?.calendar_scrape_refresh_h) {
|
||||
const h = parseFloat(config.calendar_scrape_refresh_h)
|
||||
if (!isNaN(h)) setCalendarScrapeRefreshH(h)
|
||||
}
|
||||
}, [config])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -1601,10 +1606,10 @@ export default function Config() {
|
||||
<RefreshCw className="w-4 h-4 text-indigo-400" /> Calendar Auto-Sync
|
||||
</h2>
|
||||
<div className="text-xs text-slate-400 mb-3">
|
||||
Interval between automatic economic calendar syncs (Forex Factory live JSON + HTML scraper; FMP API used as fallback for weeks 3+ if the FF scraper gets blocked — needs an FMP key below).
|
||||
Live JSON (this week's actuals/forecasts) is cheap and safe to poll often. The HTML scraper (weeks 3+, one FlareSolverr headless-browser fetch per week) is heavier and more likely to get re-flagged by Cloudflare if run too often — kept on its own, slower interval.
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<label className="text-xs text-slate-500 whitespace-nowrap">Refresh every</label>
|
||||
<label className="text-xs text-slate-500 whitespace-nowrap w-32 shrink-0">Live JSON every</label>
|
||||
<div className="flex gap-1">
|
||||
{[2, 4, 6, 12, 24].map(h => (
|
||||
<button key={h} onClick={() => setCalendarRefreshH(h)}
|
||||
@@ -1616,16 +1621,30 @@ export default function Config() {
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => updateApiKeys({ calendar_refresh_h: String(calendarRefreshH) }, {
|
||||
onSuccess: () => { setSavedMsg('Calendar refresh saved'); setTimeout(() => setSavedMsg(''), 2000) }
|
||||
})}
|
||||
disabled={savingKeys}
|
||||
className="flex items-center gap-1.5 bg-indigo-700 hover:bg-indigo-600 disabled:opacity-40 text-white px-3 py-1.5 rounded text-xs font-semibold">
|
||||
<Save className="w-3.5 h-3.5" />
|
||||
{savingKeys ? 'Saving…' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 mt-2">
|
||||
<label className="text-xs text-slate-500 whitespace-nowrap w-32 shrink-0">Scrape (weeks 3+) every</label>
|
||||
<div className="flex gap-1">
|
||||
{[24, 48, 72, 168].map(h => (
|
||||
<button key={h} onClick={() => setCalendarScrapeRefreshH(h)}
|
||||
className={clsx('px-3 py-1.5 rounded text-xs transition-colors', {
|
||||
'bg-indigo-700 text-white': calendarScrapeRefreshH === h,
|
||||
'bg-dark-700 text-slate-400 hover:text-slate-200': calendarScrapeRefreshH !== h,
|
||||
})}>
|
||||
{h < 168 ? `${h}h` : '7j'}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => updateApiKeys({ calendar_refresh_h: String(calendarRefreshH), calendar_scrape_refresh_h: String(calendarScrapeRefreshH) }, {
|
||||
onSuccess: () => { setSavedMsg('Calendar refresh saved'); setTimeout(() => setSavedMsg(''), 2000) }
|
||||
})}
|
||||
disabled={savingKeys}
|
||||
className="mt-3 flex items-center gap-1.5 bg-indigo-700 hover:bg-indigo-600 disabled:opacity-40 text-white px-3 py-1.5 rounded text-xs font-semibold">
|
||||
<Save className="w-3.5 h-3.5" />
|
||||
{savingKeys ? 'Saving…' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user