850fe60e8f
Scan UI (/scan): - Leg builder with player autocomplete, stat/line/direction/book - 2-12 legs, add/remove - Calls POST /api/scan/parlay, displays grade results - Color-coded grades (A/B/C/D), correlation flags, kill conditions - Scan counter, upgrade pitch modal at limit - New Scan / Save actions Bet Tracker (/tracker): - Performance cards: ROI, Win Rate, Bets with period toggle - Quick Slip form for fast bet entry - Bet history with status/book filters - Inline settle modal (won/lost/push/void) - Profit display on settled bets Shared API client library (lib/api.ts). Build clean: 9 static pages generated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
|
const NBA_SERVICE = process.env.NEXT_PUBLIC_NBA_SERVICE_URL || 'http://localhost:8000';
|
|
|
|
async function fetchAPI(path: string, options: RequestInit = {}) {
|
|
const token = typeof window !== 'undefined' ? localStorage.getItem('sb-token') : null;
|
|
const headers: Record<string, string> = {
|
|
'Content-Type': 'application/json',
|
|
...(options.headers as Record<string, string> || {}),
|
|
};
|
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
|
|
const res = await fetch(`${API_BASE}${path}`, { ...options, headers });
|
|
if (!res.ok) {
|
|
const body = await res.json().catch(() => ({ error: res.statusText }));
|
|
const err = new Error(body.error || 'Request failed');
|
|
(err as any).status = res.status;
|
|
(err as any).body = body;
|
|
throw err;
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
export async function scanParlay(legs: any[]) {
|
|
return fetchAPI('/api/scan/parlay', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ legs }),
|
|
});
|
|
}
|
|
|
|
export async function searchPlayers(name: string) {
|
|
const res = await fetch(`${NBA_SERVICE}/players/search?name=${encodeURIComponent(name)}`);
|
|
if (!res.ok) return { results: [] };
|
|
return res.json();
|
|
}
|
|
|
|
export async function submitQuickslip(data: any) {
|
|
return fetchAPI('/api/bets/quickslip', {
|
|
method: 'POST',
|
|
body: JSON.stringify(data),
|
|
});
|
|
}
|
|
|
|
export async function getBets(params: Record<string, string> = {}) {
|
|
const qs = new URLSearchParams(params).toString();
|
|
return fetchAPI(`/api/bets?${qs}`);
|
|
}
|
|
|
|
export async function settleBet(betId: string, status: string) {
|
|
return fetchAPI(`/api/bets/${betId}/settle`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify({ status }),
|
|
});
|
|
}
|
|
|
|
export async function getPerformance() {
|
|
return fetchAPI('/api/bets/performance');
|
|
}
|