const API_URL = import.meta.env.VITE_API_URL || '/api'; class API { constructor() { this.token = localStorage.getItem('token'); } setToken(token) { this.token = token; if (token) { localStorage.setItem('token', token); } else { localStorage.removeItem('token'); } } async request(endpoint, options = {}) { const headers = { 'Content-Type': 'application/json', ...options.headers }; if (this.token) { headers.Authorization = `Bearer ${this.token}`; } const response = await fetch(`${API_URL}${endpoint}`, { ...options, headers }); if (!response.ok) { const error = await response.json().catch(() => ({ error: 'Request failed' })); throw new Error(error.error || 'Request failed'); } return response.json(); } // Auth async register(email, username, password) { const data = await this.request('/auth/register', { method: 'POST', body: JSON.stringify({ email, username, password }) }); this.setToken(data.token); return data; } async login(email, password) { const data = await this.request('/auth/login', { method: 'POST', body: JSON.stringify({ email, password }) }); this.setToken(data.token); return data; } async getMe() { return this.request('/auth/me'); } // Challenges async getChallenges() { return this.request('/challenges'); } async getChallenge(id) { return this.request(`/challenges/${id}`); } async createChallenge(data) { return this.request('/challenges', { method: 'POST', body: JSON.stringify(data) }); } async inviteToChallenge(challengeId, data) { return this.request(`/challenges/${challengeId}/invite`, { method: 'POST', body: JSON.stringify(data) }); } async respondToChallenge(challengeId, status) { return this.request(`/challenges/${challengeId}/respond`, { method: 'POST', body: JSON.stringify({ status }) }); } // Predictions async getPredictions(challengeId) { return this.request(`/predictions/challenge/${challengeId}`); } async createPrediction(data) { return this.request('/predictions', { method: 'POST', body: JSON.stringify(data) }); } async validatePrediction(predictionId, status) { return this.request(`/predictions/${predictionId}/validate`, { method: 'POST', body: JSON.stringify({ status }) }); } // Friends async getFriends() { return this.request('/friends'); } async searchUsers(query) { return this.request(`/friends/search?q=${encodeURIComponent(query)}`); } async sendFriendRequest(userId) { return this.request('/friends/request', { method: 'POST', body: JSON.stringify({ user_id: userId }) }); } async respondToFriendRequest(friendshipId, status) { return this.request('/friends/respond', { method: 'POST', body: JSON.stringify({ friendship_id: friendshipId, status }) }); } async getFriendRequests() { return this.request('/friends/requests'); } async removeFriend(friendId) { return this.request(`/friends/${friendId}`, { method: 'DELETE' }); } async deleteChallenge(challengeId) { return this.request(`/challenges/${challengeId}`, { method: 'DELETE' }); } async leaveChallenge(challengeId) { return this.request(`/challenges/${challengeId}/leave`, { method: 'POST' }); } // TMDB async searchShows(query) { return this.request(`/tmdb/search?q=${encodeURIComponent(query)}`); } // Leaderboard async getChallengeLeaderboard(challengeId) { return this.request(`/leaderboard/challenge/${challengeId}`); } async getGlobalLeaderboard() { return this.request('/leaderboard/global'); } async getProfile(userId) { return this.request(`/leaderboard/profile${userId ? `/${userId}` : ''}`); } } export default new API();