const API_URL = import.meta.env.VITE_API_URL || '/api'; let onUnauthorized = () => {}; export function setUnauthorizedHandler(fn) { onUnauthorized = fn; } function getToken() { return localStorage.getItem('plc_token'); } async function request(method, path, { body, isForm, extraHeaders } = {}) { const headers = { ...extraHeaders }; const token = getToken(); if (token) headers.Authorization = `Bearer ${token}`; if (!isForm && body !== undefined) headers['Content-Type'] = 'application/json'; const res = await fetch(`${API_URL}${path}`, { method, headers, body: isForm ? body : body !== undefined ? JSON.stringify(body) : undefined, }); if (res.status === 401) { onUnauthorized(); } if (res.status === 204) return null; const isJson = (res.headers.get('content-type') || '').includes('application/json'); const payload = isJson ? await res.json() : null; if (!res.ok) { const message = payload?.error || `Error ${res.status}`; throw new Error(message); } return payload?.data; } export const api = { get: (path, extraHeaders) => request('GET', path, { extraHeaders }), post: (path, body, extraHeaders) => request('POST', path, { body, extraHeaders }), put: (path, body, extraHeaders) => request('PUT', path, { body, extraHeaders }), patch: (path, body) => request('PATCH', path, { body }), delete: (path, extraHeaders) => request('DELETE', path, { extraHeaders }), postForm: (path, formData) => request('POST', path, { body: formData, isForm: true }), putForm: (path, formData) => request('PUT', path, { body: formData, isForm: true }), setToken: (token) => { if (token) localStorage.setItem('plc_token', token); else localStorage.removeItem('plc_token'); }, downloadUrl: (path) => `${API_URL}${path}`, };