'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; interface Instrument { symbol: string; enabled: boolean; } interface ResolvedContract { name: string; alternative?: string; frontVolume?: number; rolledVolume?: number; } interface AppSettings { max_concurrent_accounts: string | null; } export default function SettingsPage() { const [instruments, setInstruments] = useState([]); const [contracts, setContracts] = useState>({}); const [maxConcurrent, setMaxConcurrent] = useState('5'); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); useEffect(() => { fetch('/api/instruments') .then((r) => r.json()) .then(setInstruments); fetch('/api/settings') .then((r) => r.json()) .then((s: AppSettings) => { if (s.max_concurrent_accounts != null) { setMaxConcurrent(s.max_concurrent_accounts); } }); // Load cached contracts; if cache is empty, auto-resolve fetch('/api/instruments/contracts') .then((r) => r.json()) .then((data: Record) => { if (data.error) return; const hasData = Object.values(data).some((v) => v !== null); if (hasData) { setContracts(data); } else { // Cache empty — trigger a fresh resolve automatically fetch('/api/instruments/contracts', { method: 'POST' }) .then((r) => r.json()) .then((fresh) => { if (!fresh.error) setContracts(fresh); }) .catch(() => {}); } }) .catch(() => {}); }, []); async function toggle(symbol: string, enabled: boolean) { setInstruments((prev) => prev.map((i) => (i.symbol === symbol ? { ...i, enabled } : i)) ); await fetch(`/api/instruments/${symbol}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled }), }); } async function saveSettings() { setSaving(true); setSaved(false); await fetch('/api/settings', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ max_concurrent_accounts: maxConcurrent }), }); setSaving(false); setSaved(true); setTimeout(() => setSaved(false), 2000); } return (
← Back

Settings

{/* ── Trading ── */}

Trading

Max concurrent accounts

How many accounts trade in parallel per /api/trade call

setMaxConcurrent(e.target.value)} className="w-20 rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 text-sm text-right font-mono text-slate-800 focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* ── Instruments ── */}

Instruments

{instruments.length === 0 ? (
Loading…
) : ( {instruments.map((instr) => { const c = contracts[instr.symbol]; const wasRolled = c?.alternative && c.rolledVolume != null && c.frontVolume != null && c.rolledVolume > c.frontVolume; return ( ); })}
Symbol Active Contract Enabled
{instr.symbol} {c ? (
{c.name} {c.frontVolume != null && c.rolledVolume != null && ( vol {Math.max(c.frontVolume, c.rolledVolume).toLocaleString()} )} {wasRolled && ( rolled )}
) : ( )}
)}
); }