import { API_CONFIG } from '../constants/Config'; import AsyncStorage from '@react-native-async-storage/async-storage'; const API_URL = API_CONFIG.BASE_URL; interface RequestOptions extends RequestInit { requireAuth?: boolean; } class ApiClient { private baseURL: string; constructor(baseURL: string) { this.baseURL = baseURL; } /** * Lấy token từ AsyncStorage */ private async getAuthToken(): Promise { try { return await AsyncStorage.getItem('authToken'); } catch (error) { console.error('Error getting auth token:', error); return null; } } /** * Tạo headers cho request */ private async createHeaders(requireAuth: boolean = false): Promise { const headers: HeadersInit = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; if (requireAuth) { const token = await this.getAuthToken(); if (token) { headers['Authorization'] = `Bearer ${token}`; } } return headers; } /** * Xử lý response */ private async handleResponse(response: Response): Promise { if (!response.ok) { let errorMessage = `Request failed: ${response.status} ${response.statusText}`; try { const errorData = await response.json(); errorMessage = errorData.message || errorData.error || errorMessage; } catch { const text = await response.text().catch(() => ''); errorMessage = text || errorMessage; } throw new Error(errorMessage); } // Xử lý response 204 No Content if (response.status === 204) { return {} as T; } return await response.json(); } /** * GET request */ async get(endpoint: string, options: RequestOptions = {}): Promise { try { const { requireAuth = false, ...fetchOptions } = options; const headers = await this.createHeaders(requireAuth); const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'GET', headers, ...fetchOptions, }); return await this.handleResponse(response); } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Không thể kết nối đến server. Vui lòng kiểm tra kết nối mạng.'); } throw error; } } /** * POST request */ async post(endpoint: string, data?: any, options: RequestOptions = {}): Promise { try { const { requireAuth = false, ...fetchOptions } = options; const headers = await this.createHeaders(requireAuth); const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'POST', headers, body: data ? JSON.stringify(data) : undefined, ...fetchOptions, }); return await this.handleResponse(response); } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Không thể kết nối đến server. Vui lòng kiểm tra kết nối mạng.'); } throw error; } } /** * PUT request */ async put(endpoint: string, data?: any, options: RequestOptions = {}): Promise { try { const { requireAuth = false, ...fetchOptions } = options; const headers = await this.createHeaders(requireAuth); const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'PUT', headers, body: data ? JSON.stringify(data) : undefined, ...fetchOptions, }); return await this.handleResponse(response); } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Không thể kết nối đến server. Vui lòng kiểm tra kết nối mạng.'); } throw error; } } /** * DELETE request */ async delete(endpoint: string, options: RequestOptions = {}): Promise { try { const { requireAuth = false, ...fetchOptions } = options; const headers = await this.createHeaders(requireAuth); const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'DELETE', headers, ...fetchOptions, }); return await this.handleResponse(response); } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Không thể kết nối đến server. Vui lòng kiểm tra kết nối mạng.'); } throw error; } } /** * PATCH request */ async patch(endpoint: string, data?: any, options: RequestOptions = {}): Promise { try { const { requireAuth = false, ...fetchOptions } = options; const headers = await this.createHeaders(requireAuth); const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'PATCH', headers, body: data ? JSON.stringify(data) : undefined, ...fetchOptions, }); return await this.handleResponse(response); } catch (error) { if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('Không thể kết nối đến server. Vui lòng kiểm tra kết nối mạng.'); } throw error; } } } // Export singleton instance const api = new ApiClient(API_URL); export default api;