const API_BASE = import.meta.env.VITE_API_BASE_URL || '' export interface ApiResponse { success?: boolean data?: T error?: string } export interface UserInfo { id: string username: string email?: string role: 'system_admin' | 'admin' | 'user' status: string created_at: string } export interface Role { id: number name: 'system_admin' | 'admin' | 'user' description?: string permissions: string[] created_at: string } export interface AuthResponse { token: string user: UserInfo } export interface StockRow { symbol: string name: string close: number change_pct: number amount?: number } export interface MarketOverview { latest_trade_date: string counts: { up: number down: number flat: number total: number } avg_change_pct: number indices: StockRow[] top_gainers: StockRow[] top_losers: StockRow[] turnover_leaders: StockRow[] } export interface SyncJob { id: string job_date: string status: 'running' | 'success' | 'failed' records_count: number started_at: string finished_at?: string error_message?: string trigger_by: string } export function getToken(): string | null { try { return localStorage.getItem('access_token') } catch { return null } } export function setToken(token: string) { localStorage.setItem('access_token', token) } export function removeToken() { localStorage.removeItem('access_token') } async function request( path: string, options: RequestInit = {}, ): Promise { const url = `${API_BASE}${path}` const token = getToken() const headers: Record = { 'Content-Type': 'application/json', ...(options.headers as Record), } if (token) { headers['Authorization'] = `Bearer ${token}` } const res = await fetch(url, { ...options, headers, }) let data: any try { data = await res.json() } catch { data = {} } if (!res.ok) { const msg = data.error || data.message || `HTTP ${res.status}` throw new Error(msg) } return data as T } export const api = { login: (body: { username: string; password: string }) => request('/api/auth/login', { method: 'POST', body: JSON.stringify(body), }), me: () => request('/api/auth/me'), logout: () => request<{ message: string }>('/api/auth/logout', { method: 'POST' }), listUsers: () => request('/api/admin/users'), createUser: (body: { username: string; email?: string; password: string; role?: string }) => request('/api/admin/users', { method: 'POST', body: JSON.stringify(body), }), updateUser: (id: string, body: Partial<{ email: string; role: string; status: string }>) => request(`/api/admin/users/${id}`, { method: 'PUT', body: JSON.stringify(body), }), deleteUser: (id: string) => request<{ message: string }>(`/api/admin/users/${id}`, { method: 'DELETE' }), listRoles: () => request('/api/admin/roles'), stockOverview: () => request('/api/stocks/overview'), stockSyncStatus: () => request('/api/stocks/sync/status'), triggerStockSync: () => request<{ job: SyncJob }>('/api/admin/stocks/sync', { method: 'POST' }), }