58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
|
|
import { LoginRequest, RegisterRequest, AuthResponse, RegisterResponse } from '../types/auth';
|
||
|
|
import { User } from '../types/user';
|
||
|
|
|
||
|
|
const API_URL = import.meta.env.VITE_API_URL || '';
|
||
|
|
|
||
|
|
class ApiClient {
|
||
|
|
private async request<T>(input: RequestInfo, init?: RequestInit): Promise<T> {
|
||
|
|
const token = localStorage.getItem('token');
|
||
|
|
|
||
|
|
const headers = new Headers(init?.headers);
|
||
|
|
if (token) {
|
||
|
|
headers.set('Authorization', `Bearer ${token}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const response = await fetch(`${API_URL}${input}`, {
|
||
|
|
...init,
|
||
|
|
headers,
|
||
|
|
});
|
||
|
|
|
||
|
|
// Handle 401 Unauthorized - clear token and redirect to login
|
||
|
|
if (response.status === 401) {
|
||
|
|
localStorage.removeItem('token');
|
||
|
|
window.location.href = '/login';
|
||
|
|
throw new Error('Unauthorized');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
const errorData = await response.json().catch(() => ({}));
|
||
|
|
throw new Error(errorData.message || `Error ${response.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
async login(data: LoginRequest): Promise<AuthResponse> {
|
||
|
|
return this.request<AuthResponse>('/api/auth/login', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify(data),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async register(data: RegisterRequest): Promise<RegisterResponse> {
|
||
|
|
return this.request<RegisterResponse>('/api/auth/register', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify(data),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async getUsers(): Promise<User[]> {
|
||
|
|
return this.request<User[]>('/api/users', {
|
||
|
|
method: 'GET',
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export const apiClient = new ApiClient();
|