const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api/v1'; // Log API URL for debugging if (typeof window !== 'undefined') { console.log('[API Client] API_URL:', API_URL); console.log('[API Client] NEXT_PUBLIC_API_URL:', process.env.NEXT_PUBLIC_API_URL); } export class ApiError extends Error { constructor( public status: number, message: string, public data?: any ) { super(message); this.name = 'ApiError'; } } async function handleResponse(response: Response): Promise { if (!response.ok) { const errorData = await response.json().catch(() => ({})); const error = new ApiError( response.status, errorData.message || response.statusText, errorData ); console.error('[API Client] Request failed:', { url: response.url, status: response.status, statusText: response.statusText, errorData, }); throw error; } if (response.status === 204) { return {} as T; } return response.json(); } export async function apiRequest( endpoint: string, options: RequestInit = {} ): Promise { const url = `${API_URL}${endpoint}`; console.log('[API Client] Request:', { method: options.method || 'GET', url, endpoint, }); const headers: Record = { 'Content-Type': 'application/json', }; // Add auth token if available if (typeof window !== 'undefined') { const token = localStorage.getItem('accessToken'); if (token) { headers['Authorization'] = `Bearer ${token}`; } } // Merge with options headers if (options.headers) { Object.assign(headers, options.headers); } const config: RequestInit = { ...options, headers, }; try { const response = await fetch(url, config); const result = await handleResponse(response); console.log('[API Client] Response:', { url, status: response.status, data: result, }); return result; } catch (error) { console.error('[API Client] Network error:', { url, error: error instanceof Error ? error.message : String(error), errorObject: error, }); throw error; } } export const api = { get: (endpoint: string, options?: RequestInit) => apiRequest(endpoint, { ...options, method: 'GET' }), post: (endpoint: string, data?: any, options?: RequestInit) => apiRequest(endpoint, { ...options, method: 'POST', body: JSON.stringify(data), }), put: (endpoint: string, data?: any, options?: RequestInit) => apiRequest(endpoint, { ...options, method: 'PUT', body: JSON.stringify(data), }), patch: (endpoint: string, data?: any, options?: RequestInit) => apiRequest(endpoint, { ...options, method: 'PATCH', body: JSON.stringify(data), }), delete: (endpoint: string, options?: RequestInit) => apiRequest(endpoint, { ...options, method: 'DELETE' }), };