const API_BASE = '/api/v1'; class APIClient { private async request( endpoint: string, options: RequestInit = {} ): Promise { const response = await fetch(`${API_BASE}${endpoint}`, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, }, }); if (!response.ok) { const error = await response.json().catch(() => ({})); throw new APIError(response.status, error.error || 'Request failed'); } return response.json(); } private get(endpoint: string, params?: Record): Promise { const url = params ? `${endpoint}?${new URLSearchParams(params)}` : endpoint; return this.request(url); } private post(endpoint: string, body?: unknown): Promise { return this.request(endpoint, { method: 'POST', body: body ? JSON.stringify(body) : undefined, }); } private put(endpoint: string, body?: unknown): Promise { return this.request(endpoint, { method: 'PUT', body: body ? JSON.stringify(body) : undefined, }); } private delete(endpoint: string): Promise { return this.request(endpoint, { method: 'DELETE' }); } // Auth auth = { login: (email: string, password: string) => this.post<{ user: any; token: string }>('/auth/login', { email, password }), signup: (data: { email: string; password: string; firstName: string; lastName: string }) => this.post<{ user: any; token: string }>('/auth/signup', data), logout: () => this.post('/auth/logout'), me: () => this.get<{ user: any }>('/auth/me'), updateProfile: (data: { firstName?: string; lastName?: string; brokerage?: string }) => this.put('/auth/me', data), }; // Contacts contacts = { getAll: (params?: { limit?: number; offset?: number; query?: string }) => this.get<{ data: any[]; meta: any }>('/contacts', params as any), getById: (id: string) => this.get(`/contacts/${id}`), create: (data: any) => this.post('/contacts', data), update: (id: string, data: any) => this.put(`/contacts/${id}`, data), delete: (id: string) => this.delete(`/contacts/${id}`), addTags: (id: string, tags: string[]) => this.post(`/contacts/${id}/tags`, { tags }), removeTags: (id: string, tags: string[]) => this.delete(`/contacts/${id}/tags`), addToWorkflow: (contactId: string, workflowId: string) => this.post(`/contacts/${contactId}/workflow/${workflowId}`), }; // Conversations conversations = { getAll: (params?: { limit?: number; status?: string; contactId?: string }) => this.get<{ data: any[] }>('/conversations', params as any), getById: (id: string) => this.get(`/conversations/${id}`), getMessages: (id: string, limit = 50) => this.get<{ data: any[] }>(`/conversations/${id}/messages`, { limit: String(limit) }), sendSMS: (contactId: string, message: string) => this.post('/conversations/send', { type: 'SMS', contactId, message }), sendEmail: (contactId: string, subject: string, htmlBody: string) => this.post('/conversations/send', { type: 'EMAIL', contactId, subject, htmlBody }), markAsRead: (id: string) => this.put(`/conversations/${id}/status`, { status: 'read' }), delete: (id: string) => this.delete(`/conversations/${id}`), }; // Opportunities opportunities = { getAll: (params?: { pipelineId?: string; stageId?: string; status?: string }) => this.get<{ data: any[] }>('/opportunities', params as any), getById: (id: string) => this.get(`/opportunities/${id}`), create: (data: any) => this.post('/opportunities', data), update: (id: string, data: any) => this.put(`/opportunities/${id}`, data), delete: (id: string) => this.delete(`/opportunities/${id}`), moveToStage: (id: string, stageId: string) => this.put(`/opportunities/${id}`, { pipelineStageId: stageId }), }; // Pipelines pipelines = { getAll: () => this.get<{ pipelines: any[] }>('/opportunities/pipelines'), getById: (id: string) => this.get(`/opportunities/pipelines/${id}`), create: (data: { name: string; stages: { name: string }[] }) => this.post('/opportunities/pipelines', data), addStage: (pipelineId: string, name: string) => this.post(`/opportunities/pipelines/${pipelineId}/stages`, { name }), }; // Onboarding onboarding = { get: () => this.get<{ onboarding: any }>('/onboarding'), save: (data: any) => this.post('/onboarding', data), getStatus: () => this.get<{ status: any }>('/onboarding/status'), updateStatus: (data: any) => this.put('/onboarding/status', data), }; // Admin admin = { getStats: () => this.get<{ stats: any }>('/admin/stats'), getUsers: (params?: { page?: number; limit?: number; search?: string; filter?: string }) => this.get<{ users: any[]; pagination: any }>('/users', params as any), getSettings: () => this.get<{ settings: any }>('/admin/settings'), updateSettings: (data: any) => this.put('/admin/settings', data), testConnection: (service: 'ghl' | 'stripe') => this.post<{ success: boolean; error?: string }>('/admin/settings/test', { service }), }; } export class APIError extends Error { constructor(public status: number, message: string) { super(message); this.name = 'APIError'; } } export const api = new APIClient();