Initial commit: Gold Trading Simulator with AI-powered analysis
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { settingsApi } from '@/services/api'
|
||||
|
||||
export default function SettingsPanel() {
|
||||
const [models, setModels] = useState<any>({})
|
||||
const [exchanges, setExchanges] = useState<any>({})
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
let mounted = true
|
||||
;(async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const [m, e] = await Promise.all([settingsApi.getModels(), settingsApi.getExchanges()])
|
||||
if (mounted) { setModels(m); setExchanges(e) }
|
||||
} catch (err: any) {
|
||||
setError(err?.message || 'Failed to load settings')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
})()
|
||||
return () => { mounted = false }
|
||||
}, [])
|
||||
|
||||
const saveModels = async () => {
|
||||
setSaving(true)
|
||||
try { setModels(await settingsApi.putModels(models)) } finally { setSaving(false) }
|
||||
}
|
||||
const saveExchanges = async () => {
|
||||
setSaving(true)
|
||||
try { setExchanges(await settingsApi.putExchanges(exchanges)) } finally { setSaving(false) }
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="card" style={{ display: 'grid', gap: 12 }}>
|
||||
<div className="title">Settings</div>
|
||||
{loading && <div className="text-gray-400">Loading…</div>}
|
||||
{error && <div className="text-red-500">{error}</div>}
|
||||
{!loading && !error && (
|
||||
<div style={{ display: 'grid', gap: 16 }}>
|
||||
<section className="card">
|
||||
<div className="title">Models</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<LabeledInput label="Default Model" value={models.default_model || ''} onChange={v => setModels({ ...models, default_model: v })} />
|
||||
<LabeledInput label="Temperature" type="number" value={models.temperature ?? 0.3} onChange={v => setModels({ ...models, temperature: Number(v) })} />
|
||||
<LabeledInput label="Max Tokens" type="number" value={models.max_tokens ?? 800} onChange={v => setModels({ ...models, max_tokens: Number(v) })} />
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<button className="btn-primary" onClick={saveModels} disabled={saving}>{saving ? 'Saving…' : 'Save Models'}</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card">
|
||||
<div className="title">Exchanges</div>
|
||||
<Toggle label="Binance Enabled" checked={exchanges?.binance?.enabled ?? true} onChange={v => setExchanges({ ...exchanges, binance: { ...(exchanges.binance || {}), enabled: v } })} />
|
||||
<Toggle label="Alpha Vantage Enabled" checked={exchanges?.alpha_vantage?.enabled ?? true} onChange={v => setExchanges({ ...exchanges, alpha_vantage: { ...(exchanges.alpha_vantage || {}), enabled: v } })} />
|
||||
<div className="mt-3">
|
||||
<button className="btn-primary" onClick={saveExchanges} disabled={saving}>{saving ? 'Saving…' : 'Save Exchanges'}</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function LabeledInput({ label, value, onChange, type = 'text' }: { label: string; value: any; onChange: (v: string) => void; type?: string }) {
|
||||
return (
|
||||
<label className="flex flex-col gap-1">
|
||||
<span className="text-gray-300 text-sm">{label}</span>
|
||||
<input className="input" type={type} value={value} onChange={e => onChange(e.target.value)} />
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
function Toggle({ label, checked, onChange }: { label: string; checked: boolean; onChange: (v: boolean) => void }) {
|
||||
return (
|
||||
<label className="flex items-center gap-2">
|
||||
<input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)} />
|
||||
<span className="text-gray-300 text-sm">{label}</span>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user