// Пусто = тот же origin (фронт отдаётся самим API → один туннель для Telegram). // Для dev в браузере (Vite на :5173) задай VITE_API_URL=http://localhost:3000 в apps/web/.env const BASE_URL = import.meta.env.VITE_API_URL ?? ''; async function request(path, options = {}) { const token = localStorage.getItem('token'); const headers = { 'Content-Type': 'application/json', ...(options.headers || {}), }; if (token) { headers['Authorization'] = `Bearer ${token}`; } const config = { ...options, headers, }; try { const response = await fetch(`${BASE_URL}${path}`, config); let data = {}; const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { data = await response.json(); } if (!response.ok) { if (data.error) { throw data.error; } throw { code: 'HTTP_ERROR', message: data.message || `Request failed with status ${response.status}`, }; } return data; } catch (error) { console.error(`API Error on ${path}:`, error); if (error.code && error.message) { throw error; } throw { code: 'NETWORK_ERROR', message: error.message || 'Ошибка сети или бэкенд недоступен', }; } } export const api = { // Auth authTelegram: (initData) => request('/auth/telegram', { method: 'POST', body: JSON.stringify({ initData }), }), authRegister: (email, password, name) => request('/auth/register', { method: 'POST', body: JSON.stringify({ email, password, name }), }), authLogin: (email, password) => request('/auth/login', { method: 'POST', body: JSON.stringify({ email, password }), }), authMe: () => request('/auth/me', { method: 'GET', }), // Spaces getSpaces: () => request('/spaces', { method: 'GET', }), createSpace: (name, type) => request('/spaces', { method: 'POST', body: JSON.stringify({ name, type }), }), getSpace: (id) => request(`/spaces/${id}`, { method: 'GET', }), joinSpace: (id) => request(`/spaces/${id}/join`, { method: 'POST', }), getSpaceMembers: (id) => request(`/spaces/${id}/members`, { method: 'GET', }), // Finance getTransactions: (spaceId) => request(`/spaces/${spaceId}/transactions`, { method: 'GET', }), createTransaction: (spaceId, { title, amount, paid_by, split }) => request(`/spaces/${spaceId}/transactions`, { method: 'POST', body: JSON.stringify({ title, amount, paid_by, split }), }), getBalance: (spaceId) => request(`/spaces/${spaceId}/balance`, { method: 'GET', }), // Tasks getTasks: (spaceId) => request(`/spaces/${spaceId}/tasks`, { method: 'GET', }), createTask: (spaceId, { title, assignee_id, due_at }) => request(`/spaces/${spaceId}/tasks`, { method: 'POST', body: JSON.stringify({ title, assignee_id, due_at }), }), updateTask: (spaceId, taskId, { done, assignee_id, title }) => request(`/spaces/${spaceId}/tasks/${taskId}`, { method: 'PATCH', body: JSON.stringify({ done, assignee_id, title }), }), // Feed (posts) getPosts: (spaceId) => request(`/spaces/${spaceId}/posts`, { method: 'GET', }), createPost: (spaceId, { text }) => request(`/spaces/${spaceId}/posts`, { method: 'POST', body: JSON.stringify({ text }), }), // Calendar (events) getEvents: (spaceId) => request(`/spaces/${spaceId}/events`, { method: 'GET', }), createEvent: (spaceId, { title, start_at }) => request(`/spaces/${spaceId}/events`, { method: 'POST', body: JSON.stringify({ title, start_at }), }), };