/** * TekDek Command Center - API Client * Handles all REST API calls to the backend */ class APIClient { constructor(baseURL = 'http://localhost:3000/api/v1') { this.baseURL = baseURL; this.headers = { 'Content-Type': 'application/json' }; } /** * Make an HTTP request to the API * @private */ async request(method, path, body = null) { const url = `${this.baseURL}${path}`; const options = { method, headers: this.headers }; if (body) { options.body = JSON.stringify(body); } try { const response = await fetch(url, options); const data = await response.json(); if (data.status === 'error') { const error = new Error(data.error.message); error.code = data.error.code; error.details = data.error.details; throw error; } return data.data; } catch (error) { if (error instanceof SyntaxError) { throw new Error('Invalid server response'); } throw error; } } // ==================== PROJECTS ==================== /** * Get all projects * @param {Object} options - Filter and pagination options * @returns {Promise} */ async getProjects(options = {}) { const params = new URLSearchParams(); if (options.status) params.append('status', options.status); if (options.limit) params.append('limit', options.limit); if (options.offset) params.append('offset', options.offset); const query = params.toString(); const path = `/projects${query ? '?' + query : ''}`; return this.request('GET', path); } /** * Get a specific project * @param {number} projectId * @returns {Promise} */ async getProject(projectId) { return this.request('GET', `/projects/${projectId}`); } /** * Create a new project * @param {Object} data - Project data * @returns {Promise} */ async createProject(data) { return this.request('POST', '/projects', { name: data.name, description: data.description || null, color_hex: data.color_hex || '#3498db', icon_name: data.icon_name || 'rocket' }); } /** * Update a project * @param {number} projectId * @param {Object} data - Fields to update * @returns {Promise} */ async updateProject(projectId, data) { return this.request('PUT', `/projects/${projectId}`, data); } /** * Delete a project * @param {number} projectId * @returns {Promise} */ async deleteProject(projectId) { return this.request('DELETE', `/projects/${projectId}`); } // ==================== TASKS ==================== /** * Get all tasks for a project * @param {number} projectId * @param {Object} options - Filter and sort options * @returns {Promise} */ async getTasks(projectId, options = {}) { const params = new URLSearchParams(); if (options.status) params.append('status', options.status); if (options.sort) params.append('sort', options.sort); if (options.limit) params.append('limit', options.limit); if (options.offset) params.append('offset', options.offset); const query = params.toString(); const path = `/projects/${projectId}/tasks${query ? '?' + query : ''}`; return this.request('GET', path); } /** * Get a specific task * @param {number} projectId * @param {number} taskId * @returns {Promise} */ async getTask(projectId, taskId) { return this.request('GET', `/projects/${projectId}/tasks/${taskId}`); } /** * Create a new task * @param {number} projectId * @param {Object} data - Task data * @returns {Promise} */ async createTask(projectId, data) { return this.request('POST', `/projects/${projectId}/tasks`, { title: data.title, description: data.description || null, status: data.status || 'backlog', due_date: data.due_date || null, assignee_id: data.assignee_id || null }); } /** * Update a task * @param {number} projectId * @param {number} taskId * @param {Object} data - Fields to update * @returns {Promise} */ async updateTask(projectId, taskId, data) { return this.request('PUT', `/projects/${projectId}/tasks/${taskId}`, data); } /** * Delete a task * @param {number} projectId * @param {number} taskId * @returns {Promise} */ async deleteTask(projectId, taskId) { return this.request('DELETE', `/projects/${projectId}/tasks/${taskId}`); } /** * Reorder multiple tasks * @param {number} projectId * @param {Array} taskIds - New order of task IDs * @returns {Promise} */ async reorderTasks(projectId, taskIds) { return this.request('POST', `/projects/${projectId}/tasks/reorder`, { order: taskIds }); } /** * Check API connectivity * @returns {Promise} */ async checkConnection() { try { await this.request('GET', '/projects', { limit: 1 }); return true; } catch (error) { return false; } } } // Create global API client instance const api = new APIClient( process.env.API_BASE_URL || 'http://localhost:3000/api/v1' );