/** * SocioWire frontend API client */ const API_BASE = "/api"; /** * Récupère la liste des posts, avec filtres optionnels. */ export async function fetchPosts(filters = {}) { const params = new URLSearchParams(); if (filters.category) params.set("category", filters.category); if (filters.subCategory) params.set("sub_category", filters.subCategory); if (filters.time) params.set("time", filters.time); if (typeof filters.lat === "number") params.set("lat", String(filters.lat)); if (typeof filters.lon === "number") params.set("lon", String(filters.lon)); if (typeof filters.radiusKm === "number") { params.set("radius_km", String(filters.radiusKm)); } const qs = params.toString(); const url = qs ? `${API_BASE}/posts?${qs}` : `${API_BASE}/posts`; const res = await fetch(url, { credentials: "include", }); if (!res.ok) { console.error("fetchPosts failed", res.status); throw new Error("Failed to load posts"); } const data = await res.json(); return Array.isArray(data) ? data : data.items || []; } /** * Récupère la position approx de l'utilisateur depuis le backend. */ export async function fetchIpLocation() { try { const res = await fetch(`${API_BASE}/ip-location`, { credentials: "include", }); if (!res.ok) { console.warn("fetchIpLocation: HTTP", res.status); return null; } const text = await res.text(); if (!text || text === "null") { return null; } let data; try { data = JSON.parse(text); } catch (e) { console.warn("fetchIpLocation: JSON parse error", e, text); return null; } const lat = data.lat; const lon = data.lon; if ( typeof lat === "number" && typeof lon === "number" && !Number.isNaN(lat) && !Number.isNaN(lon) ) { return [lon, lat]; // [lng, lat] } console.warn("fetchIpLocation: invalid payload", data); return null; } catch (err) { console.warn("fetchIpLocation: network error", err); return null; } } /** * Crée un nouveau post * token: access token Keycloak (string) ou null */ export async function createPost(payload, token) { const headers = { "Content-Type": "application/json", }; if (token) { headers["Authorization"] = `Bearer ${token}`; } const res = await fetch(`${API_BASE}/post`, { method: "POST", headers, credentials: "include", body: JSON.stringify(payload), }); if (!res.ok) { const text = await res.text().catch(() => ""); console.error("createPost failed", res.status, text); throw new Error("Failed to create post"); } return res.json().catch(() => ({})); } /** * Crée un nouvel utilisateur via le backend * (backend: POST /api/signup) * payload: { username, email, password, firstName, lastName } */ export async function registerUser(payload) { const res = await fetch(`${API_BASE}/signup`, { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify(payload), }); if (!res.ok) { const text = await res.text().catch(() => ""); console.error("registerUser failed", res.status, text); throw new Error(text || "Failed to register user"); } return res.json().catch(() => ({})); }