import axios from 'axios'; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3020/api/v1'; class ApiClient { private token: string | null = null; private refreshToken: string | null = null; constructor() { // Initialize tokens from localStorage if available if (typeof window !== 'undefined') { this.token = localStorage.getItem('admin_access_token'); this.refreshToken = localStorage.getItem('admin_refresh_token'); } } setTokens(accessToken: string, refreshToken: string) { this.token = accessToken; this.refreshToken = refreshToken; if (typeof window !== 'undefined') { localStorage.setItem('admin_access_token', accessToken); localStorage.setItem('admin_refresh_token', refreshToken); } } clearTokens() { this.token = null; this.refreshToken = null; if (typeof window !== 'undefined') { localStorage.removeItem('admin_access_token'); localStorage.removeItem('admin_refresh_token'); } } private async request(method: string, endpoint: string, data?: any, options?: any) { const config = { method, url: `${API_BASE_URL}${endpoint}`, headers: { 'Content-Type': 'application/json', ...(this.token ? { Authorization: `Bearer ${this.token}` } : {}), ...options?.headers, }, ...options, }; if (data) { config.data = data; } try { const response = await axios(config); return response.data; } catch (error: any) { // Handle token refresh if (error.response?.status === 401 && this.refreshToken) { try { const refreshResponse = await axios.post(`${API_BASE_URL}/auth/refresh`, { refreshToken: this.refreshToken, }); this.setTokens(refreshResponse.data.accessToken, refreshResponse.data.refreshToken); // Retry original request config.headers.Authorization = `Bearer ${this.token}`; const response = await axios(config); return response.data; } catch (refreshError) { this.clearTokens(); window.location.href = '/login'; throw refreshError; } } throw error; } } // Generic HTTP methods async get(endpoint: string, options?: any) { return this.request('GET', endpoint, undefined, options); } async post(endpoint: string, data?: any, options?: any) { return this.request('POST', endpoint, data, options); } async patch(endpoint: string, data?: any, options?: any) { return this.request('PATCH', endpoint, data, options); } async put(endpoint: string, data?: any, options?: any) { return this.request('PUT', endpoint, data, options); } async delete(endpoint: string, options?: any) { return this.request('DELETE', endpoint, undefined, options); } // Auth endpoints async login(email: string, password: string) { // Generate device info for admin dashboard const deviceInfo = { deviceId: this.getOrCreateDeviceId(), platform: 'web', model: 'Admin Dashboard', osVersion: navigator.userAgent, }; const response = await this.request('POST', '/auth/login', { email, password, deviceInfo }); // Extract tokens from nested response structure const tokens = response.tokens || response.data?.tokens; if (tokens?.accessToken && tokens?.refreshToken) { this.setTokens(tokens.accessToken, tokens.refreshToken); } return response; } private getOrCreateDeviceId(): string { if (typeof window === 'undefined') return 'server'; let deviceId = localStorage.getItem('admin_device_id'); if (!deviceId) { deviceId = 'admin_' + Math.random().toString(36).substring(2) + Date.now().toString(36); localStorage.setItem('admin_device_id', deviceId); } return deviceId; } async logout() { try { await this.request('POST', '/auth/logout'); } finally { this.clearTokens(); } } async getCurrentAdmin() { return this.request('GET', '/auth/me'); } // User management endpoints async getUsers(params?: { page?: number; limit?: number; search?: string }) { const queryString = params ? '?' + new URLSearchParams(params as any).toString() : ''; return this.request('GET', `/admin/users${queryString}`); } async getUserById(id: string) { return this.request('GET', `/admin/users/${id}`); } async updateUser(id: string, data: any) { return this.request('PATCH', `/admin/users/${id}`, data); } async deleteUser(id: string) { return this.request('DELETE', `/admin/users/${id}`); } // Invite code endpoints async getInviteCodes(params?: { page?: number; limit?: number; status?: string }) { const queryString = params ? '?' + new URLSearchParams(params as any).toString() : ''; return this.request('GET', `/admin/invite-codes${queryString}`); } async createInviteCode(data: { code: string; maxUses?: number; expiresAt?: string; metadata?: any; }) { return this.request('POST', '/admin/invite-codes', data); } async updateInviteCode(id: string, data: any) { return this.request('PATCH', `/admin/invite-codes/${id}`, data); } async deleteInviteCode(id: string) { return this.request('DELETE', `/admin/invite-codes/${id}`); } // Analytics endpoints async getAnalytics(params?: { startDate?: string; endDate?: string }) { const queryString = params ? '?' + new URLSearchParams(params as any).toString() : ''; return this.request('GET', `/admin/analytics${queryString}`); } async getUserGrowth() { return this.request('GET', '/admin/analytics/user-growth'); } async getActivityStats() { return this.request('GET', '/admin/analytics/activity-stats'); } async getSystemHealth() { return this.request('GET', '/admin/analytics/system-health'); } // Family management async getFamilies(params?: { page?: number; limit?: number; search?: string }) { const queryString = params ? '?' + new URLSearchParams(params as any).toString() : ''; return this.request('GET', `/admin/families${queryString}`); } async getFamilyById(id: string) { return this.request('GET', `/admin/families/${id}`); } // Activity logs async getActivityLogs(params?: { page?: number; limit?: number; userId?: string }) { const queryString = params ? '?' + new URLSearchParams(params as any).toString() : ''; return this.request('GET', `/admin/logs${queryString}`); } // System settings async getSettings() { return this.request('GET', '/admin/settings'); } async updateSettings(data: any) { return this.request('PATCH', '/admin/settings', data); } } export const apiClient = new ApiClient(); export default apiClient;