From cade280b2d3d2371b93e925ea86070a1de4a53d3 Mon Sep 17 00:00:00 2001 From: Senofy <63175905+Senofy@users.noreply.github.com> Date: Thu, 12 Mar 2026 03:34:51 -0500 Subject: [PATCH] Auto-fetch contract on symbol enable; hide contract when disabled - POST /api/instruments/contracts now accepts optional { symbols[] } body to resolve a subset rather than all enabled instruments - Settings toggle() fires a targeted resolve when enabling a symbol, merging the result into contracts state without a full page refresh - Active Contract cell is hidden (null) when the instrument is disabled Co-Authored-By: Claude Sonnet 4.6 --- app/api/instruments/contracts/route.ts | 17 +++++++++++------ app/settings/page.tsx | 22 ++++++++++++++++++---- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/api/instruments/contracts/route.ts b/app/api/instruments/contracts/route.ts index 7aa81d5..59ce180 100644 --- a/app/api/instruments/contracts/route.ts +++ b/app/api/instruments/contracts/route.ts @@ -1,4 +1,4 @@ -import { NextResponse } from 'next/server'; +import { NextRequest, NextResponse } from 'next/server'; import { getClients } from '@/lib/clients'; import { getInstruments } from '@/lib/db'; import { resolveContracts, getAllCachedContracts } from '@/lib/contract-resolver'; @@ -13,10 +13,11 @@ export async function GET() { /** * POST /api/instruments/contracts - * Triggers a fresh resolve of all enabled instruments via Tradovate + yfinance. - * Returns the resolved contracts with volume data. + * Triggers a fresh resolve via Tradovate + Yahoo Finance. + * Body (optional): { symbols: string[] } — when provided, resolves only those symbols. + * Otherwise resolves all enabled instruments. */ -export async function POST() { +export async function POST(req: NextRequest) { try { const clients = getClients(); // Find first client with a valid token @@ -29,8 +30,12 @@ export async function POST() { return NextResponse.json({ error: 'No authenticated client available' }, { status: 503 }); } - const instruments = getInstruments().filter((i) => i.enabled); - const symbols = instruments.map((i) => i.symbol); + const body = await req.json().catch(() => ({})); + const requestedSymbols: string[] | undefined = Array.isArray(body?.symbols) ? body.symbols : undefined; + + const symbols = requestedSymbols?.length + ? requestedSymbols + : getInstruments().filter((i) => i.enabled).map((i) => i.symbol); const resolved = await resolveContracts(symbols, accessToken); return NextResponse.json(resolved); diff --git a/app/settings/page.tsx b/app/settings/page.tsx index 7df4267..ee4e6a8 100644 --- a/app/settings/page.tsx +++ b/app/settings/page.tsx @@ -67,6 +67,22 @@ export default function SettingsPage() { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled }), }); + + // When enabling a symbol, auto-resolve its active contract + if (enabled) { + fetch('/api/instruments/contracts', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ symbols: [symbol] }), + }) + .then((r) => r.json()) + .then((fresh: Record) => { + if (!fresh.error) { + setContracts((prev) => ({ ...prev, ...fresh })); + } + }) + .catch(() => {}); + } } async function saveSettings() { @@ -161,7 +177,7 @@ export default function SettingsPage() { {instr.symbol} - {c ? ( + {instr.enabled && c ? (
{c.name} @@ -177,9 +193,7 @@ export default function SettingsPage() { )}
- ) : ( - - )} + ) : null}