104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'https://api.approagency.ir/api';
|
|
|
|
interface ApiOptions extends RequestInit {
|
|
token?: string;
|
|
}
|
|
|
|
class ApiClient {
|
|
private async request<T>(
|
|
endpoint: string,
|
|
options: ApiOptions = {}
|
|
): Promise<T> {
|
|
const { token, ...fetchOptions } = options;
|
|
|
|
const headers: Record<string, string> = {
|
|
...(options.headers as Record<string, string> || {}),
|
|
};
|
|
|
|
// Don't set Content-Type for FormData (browser will set it automatically with boundary)
|
|
if (!(options.body instanceof FormData)) {
|
|
headers['Content-Type'] = 'application/json';
|
|
}
|
|
|
|
if (token) {
|
|
headers['Authorization'] = `Bearer ${token}`;
|
|
}
|
|
|
|
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
|
|
...fetchOptions,
|
|
headers,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({}));
|
|
throw new Error(error.message || 'API request failed');
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
async post<T>(endpoint: string, data: any, token?: string): Promise<T> {
|
|
const body = data instanceof FormData ? data : JSON.stringify(data);
|
|
|
|
return this.request<T>(endpoint, {
|
|
method: 'POST',
|
|
body,
|
|
token,
|
|
});
|
|
}
|
|
|
|
async get<T>(endpoint: string, token?: string): Promise<T> {
|
|
return this.request<T>(endpoint, {
|
|
method: 'GET',
|
|
token,
|
|
});
|
|
}
|
|
|
|
async put<T>(endpoint: string, data: any, token?: string): Promise<T> {
|
|
const body = data instanceof FormData ? data : JSON.stringify(data);
|
|
|
|
return this.request<T>(endpoint, {
|
|
method: 'PUT',
|
|
body,
|
|
token,
|
|
});
|
|
}
|
|
|
|
async delete<T>(endpoint: string, data?: any, token?: string): Promise<T> {
|
|
const options: ApiOptions = {
|
|
method: 'DELETE',
|
|
token,
|
|
};
|
|
|
|
// Handle DELETE with body if data is provided
|
|
if (data) {
|
|
options.body = data instanceof FormData ? data : JSON.stringify(data);
|
|
|
|
// Don't set Content-Type for FormData
|
|
if (!(data instanceof FormData)) {
|
|
options.headers = {
|
|
'Content-Type': 'application/json',
|
|
};
|
|
}
|
|
}
|
|
|
|
return this.request<T>(endpoint, options);
|
|
}
|
|
|
|
// Convenience method for DELETE with JSON body
|
|
async deleteWithBody<T>(endpoint: string, data: any, token?: string): Promise<T> {
|
|
return this.delete<T>(endpoint, data, token);
|
|
}
|
|
|
|
async patch<T>(endpoint: string, data: any, token?: string): Promise<T> {
|
|
const body = data instanceof FormData ? data : JSON.stringify(data);
|
|
|
|
return this.request<T>(endpoint, {
|
|
method: 'PATCH',
|
|
body,
|
|
token,
|
|
});
|
|
}
|
|
}
|
|
|
|
export const apiClient = new ApiClient(); |