/** * Simple client-side fetch function for making API calls with Authorization header. */ export async function clientFetch(url: string, options: RequestInit = {}): Promise { try { const authToken = document.cookie .split('; ') .find(row => row.startsWith('Authorization=')) ?.split('=')[1] || localStorage.getItem('Authorization'); const headers = { 'Content-Type': 'application/json', ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}), ...options.headers, }; // Ensure the url doesn't start with a slash if it's going to be appended to a URL that ends with one const cleanUrl = url.startsWith('/') ? url.substring(1) : url; // IMPORTANT: Always use /api as the base URL for client-side requests // This ensures all requests go through Next.js API rewrite rules const baseUrl = '/api'; // Ensure there's only one slash between the base URL and endpoint const fullUrl = baseUrl.endsWith('/') ? `${baseUrl}${cleanUrl}` : `${baseUrl}/${cleanUrl}`; console.log(`[clientFetch] Requesting: ${fullUrl}`); const res = await fetch(fullUrl, { ...options, headers, }); if (!res.ok) throw new Error(`Request failed: ${res.statusText}`); return res.json(); } catch (error) { console.error(`Client fetch error at ${url}:`, error); throw error; } } /** * Get a cookie value by name */ export function getCookie(name: string): string | undefined { return document.cookie .split('; ') .find(row => row.startsWith(`${name}=`)) ?.split('=')[1]; }