feat: event eco

This commit is contained in:
OpenSquared
2026-07-21 15:59:53 +02:00
parent 5f23141992
commit 24e5e4b03b
7 changed files with 129 additions and 50 deletions

View File

@@ -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>
)}