feat: Implement admin dashboard, login, user management, authentication, and API utilities with port configuration.
This commit is contained in:
147
src/lib/api.ts
Normal file
147
src/lib/api.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/v1';
|
||||
|
||||
interface ApiResponse<T> {
|
||||
success: boolean;
|
||||
data: T;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface LoginResponse {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
role: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
avatar: string | null;
|
||||
};
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
role: string;
|
||||
status: string;
|
||||
emailVerified: boolean;
|
||||
authProvider: string;
|
||||
createdAt: string;
|
||||
lastLoginAt: string | null;
|
||||
profile: {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
avatar: string | null;
|
||||
phone: string | null;
|
||||
city: string | null;
|
||||
state: string | null;
|
||||
country: string | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
class ApiClient {
|
||||
private baseUrl: string;
|
||||
|
||||
constructor() {
|
||||
this.baseUrl = API_URL;
|
||||
}
|
||||
|
||||
private getToken(): string | null {
|
||||
if (typeof window === 'undefined') return null;
|
||||
return localStorage.getItem('accessToken');
|
||||
}
|
||||
|
||||
private async request<T>(
|
||||
endpoint: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<ApiResponse<T>> {
|
||||
const token = this.getToken();
|
||||
|
||||
const headers: HeadersInit = {
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
||||
...options,
|
||||
headers,
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || 'An error occurred');
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async login(email: string, password: string): Promise<LoginResponse> {
|
||||
const response = await this.request<LoginResponse>('/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
|
||||
// Check if user is ADMIN
|
||||
if (response.data.user.role !== 'ADMIN') {
|
||||
throw new Error('Access denied. Admin privileges required.');
|
||||
}
|
||||
|
||||
// Store tokens
|
||||
localStorage.setItem('accessToken', response.data.accessToken);
|
||||
localStorage.setItem('refreshToken', response.data.refreshToken);
|
||||
localStorage.setItem('user', JSON.stringify(response.data.user));
|
||||
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async logout(): Promise<void> {
|
||||
try {
|
||||
await this.request('/auth/logout', { method: 'POST' });
|
||||
} finally {
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('user');
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentUser(): Promise<User> {
|
||||
const response = await this.request<User>('/auth/me');
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async getUsers(page = 1, limit = 10): Promise<{ users: User[]; total: number; page: number; limit: number }> {
|
||||
const response = await this.request<{ users: User[]; total: number; page: number; limit: number }>(
|
||||
`/users?page=${page}&limit=${limit}`
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async refreshToken(): Promise<{ accessToken: string; refreshToken: string }> {
|
||||
const refreshToken = localStorage.getItem('refreshToken');
|
||||
if (!refreshToken) {
|
||||
throw new Error('No refresh token available');
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/auth/refresh`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ refreshToken }),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || 'Failed to refresh token');
|
||||
}
|
||||
|
||||
localStorage.setItem('accessToken', data.data.accessToken);
|
||||
localStorage.setItem('refreshToken', data.data.refreshToken);
|
||||
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const api = new ApiClient();
|
||||
export type { User, LoginResponse };
|
||||
Reference in New Issue
Block a user