const BASE_URL = import.meta.env.VITE_API_URL ?? '/api'; async function get(path, params = {}) { const url = new URL(BASE_URL + path, window.location.origin); Object.entries(params).forEach(([k, v]) => v !== undefined && url.searchParams.set(k, v)); const res = await fetch(url.toString(), { headers: { Accept: 'application/json' }, }); if (!res.ok) throw new Error(`API error ${res.status}: ${path}`); return res.json(); } async function post(path, body) { const res = await fetch(BASE_URL + path, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify(body), }); if (!res.ok) throw new Error(`API error ${res.status}: ${path}`); return res.json(); } export const api = { spots: { overview: () => get('/spots/overview'), // tous les spots + score en 1 requête cachée get: (id) => get(`/spots/${id}`), score: (id, at) => get(`/spots/${id}/score`, { at }), }, observations: { list: (bbox, date, source) => get('/observations', { bbox, date, source }), get: (id) => get(`/observations/${id}`), }, forecasts: { list: (bbox, horizon) => get('/forecasts', { bbox, horizon }), get: (id) => get(`/forecasts/${id}`), }, feedback: { create: (data) => post('/feedback', data), }, status: { get: () => get('/status'), }, report: { create: (data) => post('/report', data), }, push: { vapidKey: () => get('/push/vapid-public-key'), subscribe: (data) => post('/push/subscribe', data), unsubscribe: async (endpoint) => { const res = await fetch(BASE_URL + '/push/subscribe', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint }), }); if (!res.ok && res.status !== 204) throw new Error(`API error ${res.status}`); }, }, };