feat: Features 3.2 + 3.3 — Scan UI + Bet Tracker
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>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
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');
|
||||
}
|
||||
Reference in New Issue
Block a user