Admin panel: real data - backend API, users/audit/roles/stats, frontend wired
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,140 +1,266 @@
|
||||
import { api } from '../api'
|
||||
import { api } from '../api';
|
||||
|
||||
// Users API
|
||||
export interface User {
|
||||
id: string
|
||||
email: string
|
||||
username: string
|
||||
status: string
|
||||
employeeId?: string
|
||||
employee?: any
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
isActive: boolean;
|
||||
lastLogin?: string | null;
|
||||
employeeId?: string | null;
|
||||
employee?: {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
firstNameAr?: string | null;
|
||||
lastNameAr?: string | null;
|
||||
position?: { id: string; title: string; titleAr?: string | null };
|
||||
department?: { name: string; nameAr?: string | null };
|
||||
};
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CreateUserData {
|
||||
email: string
|
||||
username: string
|
||||
password: string
|
||||
employeeId?: string
|
||||
email: string;
|
||||
username: string;
|
||||
password: string;
|
||||
employeeId: string;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateUserData {
|
||||
email?: string
|
||||
username?: string
|
||||
password?: string
|
||||
status?: string
|
||||
employeeId?: string
|
||||
email?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
employeeId?: string | null;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
export interface UserFilters {
|
||||
search?: string;
|
||||
status?: 'active' | 'inactive';
|
||||
positionId?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
success: boolean;
|
||||
data: T[];
|
||||
pagination: {
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const usersAPI = {
|
||||
getAll: async (): Promise<User[]> => {
|
||||
const response = await api.get('/auth/users')
|
||||
return response.data.data || response.data
|
||||
getAll: async (filters?: UserFilters): Promise<PaginatedResponse<User>> => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters?.search) params.append('search', filters.search);
|
||||
if (filters?.status) params.append('status', filters.status);
|
||||
if (filters?.positionId) params.append('positionId', filters.positionId);
|
||||
if (filters?.page) params.append('page', String(filters.page));
|
||||
if (filters?.pageSize) params.append('pageSize', String(filters.pageSize));
|
||||
|
||||
const response = await api.get(`/admin/users?${params.toString()}`);
|
||||
return {
|
||||
success: true,
|
||||
data: response.data.data || [],
|
||||
pagination: response.data.pagination || { total: 0, page: 1, pageSize: 20, totalPages: 0 },
|
||||
};
|
||||
},
|
||||
|
||||
getById: async (id: string): Promise<User> => {
|
||||
const response = await api.get(`/auth/users/${id}`)
|
||||
return response.data.data
|
||||
const response = await api.get(`/admin/users/${id}`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
create: async (data: CreateUserData): Promise<User> => {
|
||||
const response = await api.post('/auth/register', data)
|
||||
return response.data.data
|
||||
const response = await api.post('/admin/users', data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
update: async (id: string, data: UpdateUserData): Promise<User> => {
|
||||
const response = await api.put(`/auth/users/${id}`, data)
|
||||
return response.data.data
|
||||
const response = await api.put(`/admin/users/${id}`, data);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
toggleActive: async (id: string): Promise<User> => {
|
||||
const response = await api.patch(`/admin/users/${id}/toggle-active`);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
delete: async (id: string): Promise<void> => {
|
||||
await api.delete(`/auth/users/${id}`)
|
||||
}
|
||||
await api.delete(`/admin/users/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
// Stats API
|
||||
export interface AdminStats {
|
||||
totalUsers: number;
|
||||
activeUsers: number;
|
||||
inactiveUsers: number;
|
||||
loginsToday: number;
|
||||
}
|
||||
|
||||
// Roles & Permissions API
|
||||
export const statsAPI = {
|
||||
get: async (): Promise<AdminStats> => {
|
||||
const response = await api.get('/admin/stats');
|
||||
return response.data.data || response.data;
|
||||
},
|
||||
};
|
||||
|
||||
// Positions (Roles) API - maps to HR positions with permissions
|
||||
export interface PositionPermission {
|
||||
id: string;
|
||||
module: string;
|
||||
resource: string;
|
||||
actions: string[];
|
||||
}
|
||||
|
||||
export interface PositionRole {
|
||||
id: string;
|
||||
title: string;
|
||||
titleAr?: string | null;
|
||||
code: string;
|
||||
department?: { name: string; nameAr?: string | null };
|
||||
permissions: PositionPermission[];
|
||||
usersCount: number;
|
||||
_count?: { employees: number };
|
||||
}
|
||||
|
||||
export const positionsAPI = {
|
||||
getAll: async (): Promise<PositionRole[]> => {
|
||||
const response = await api.get('/admin/positions');
|
||||
return response.data.data || [];
|
||||
},
|
||||
|
||||
updatePermissions: async (
|
||||
positionId: string,
|
||||
permissions: Array<{ module: string; resource: string; actions: string[] }>
|
||||
): Promise<PositionRole> => {
|
||||
const response = await api.put(`/admin/positions/${positionId}/permissions`, {
|
||||
permissions,
|
||||
});
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
// Roles API - alias for positions (for compatibility with existing frontend)
|
||||
export interface Role {
|
||||
id: string
|
||||
name: string
|
||||
nameAr?: string
|
||||
permissions: Permission[]
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
id: string
|
||||
module: string
|
||||
resource: string
|
||||
action: string
|
||||
id: string;
|
||||
name: string;
|
||||
nameAr?: string;
|
||||
title?: string;
|
||||
titleAr?: string;
|
||||
permissions: { id?: string; module: string; resource: string; actions: string[] }[];
|
||||
usersCount?: number;
|
||||
}
|
||||
|
||||
export const rolesAPI = {
|
||||
getAll: async (): Promise<Role[]> => {
|
||||
const response = await api.get('/admin/roles')
|
||||
return response.data.data || []
|
||||
const positions = await positionsAPI.getAll();
|
||||
return positions.map((p) => ({
|
||||
id: p.id,
|
||||
name: p.title,
|
||||
nameAr: p.titleAr || undefined,
|
||||
title: p.title,
|
||||
titleAr: p.titleAr || undefined,
|
||||
permissions: p.permissions,
|
||||
usersCount: p.usersCount,
|
||||
}));
|
||||
},
|
||||
|
||||
update: async (id: string, permissions: Permission[]): Promise<Role> => {
|
||||
const response = await api.put(`/admin/roles/${id}/permissions`, { permissions })
|
||||
return response.data.data
|
||||
}
|
||||
}
|
||||
update: async (
|
||||
id: string,
|
||||
permissions: Array<{ module: string; resource: string; actions: string[] }>
|
||||
): Promise<Role> => {
|
||||
const position = await positionsAPI.updatePermissions(id, permissions);
|
||||
return {
|
||||
id: position.id,
|
||||
name: position.title,
|
||||
nameAr: position.titleAr || undefined,
|
||||
permissions: position.permissions,
|
||||
usersCount: position.usersCount,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// Audit Logs API
|
||||
export interface AuditLog {
|
||||
id: string
|
||||
entityType: string
|
||||
entityId: string
|
||||
action: string
|
||||
userId: string
|
||||
user?: any
|
||||
changes?: any
|
||||
createdAt: string
|
||||
id: string;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
action: string;
|
||||
userId: string;
|
||||
user?: { id: string; username: string; email: string };
|
||||
changes?: unknown;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AuditLogFilters {
|
||||
entityType?: string;
|
||||
action?: string;
|
||||
userId?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export const auditLogsAPI = {
|
||||
getAll: async (filters?: any): Promise<AuditLog[]> => {
|
||||
const params = new URLSearchParams()
|
||||
if (filters?.entityType) params.append('entityType', filters.entityType)
|
||||
if (filters?.action) params.append('action', filters.action)
|
||||
if (filters?.startDate) params.append('startDate', filters.startDate)
|
||||
if (filters?.endDate) params.append('endDate', filters.endDate)
|
||||
|
||||
const response = await api.get(`/admin/audit-logs?${params.toString()}`)
|
||||
return response.data.data || []
|
||||
}
|
||||
}
|
||||
getAll: async (filters?: AuditLogFilters): Promise<PaginatedResponse<AuditLog>> => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters?.entityType) params.append('entityType', filters.entityType);
|
||||
if (filters?.action) params.append('action', filters.action);
|
||||
if (filters?.userId) params.append('userId', filters.userId);
|
||||
if (filters?.startDate) params.append('startDate', filters.startDate);
|
||||
if (filters?.endDate) params.append('endDate', filters.endDate);
|
||||
if (filters?.page) params.append('page', String(filters.page));
|
||||
if (filters?.pageSize) params.append('pageSize', String(filters.pageSize));
|
||||
|
||||
// System Settings API
|
||||
const response = await api.get(`/admin/audit-logs?${params.toString()}`);
|
||||
return {
|
||||
success: true,
|
||||
data: response.data.data || [],
|
||||
pagination: response.data.pagination || { total: 0, page: 1, pageSize: 20, totalPages: 0 },
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// System Settings API (placeholder - out of scope)
|
||||
export interface SystemSetting {
|
||||
key: string
|
||||
value: any
|
||||
description?: string
|
||||
key: string;
|
||||
value: unknown;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export const settingsAPI = {
|
||||
getAll: async (): Promise<SystemSetting[]> => {
|
||||
const response = await api.get('/admin/settings')
|
||||
return response.data.data || []
|
||||
const response = await api.get('/admin/settings').catch(() => ({ data: { data: [] } }));
|
||||
return response.data?.data || [];
|
||||
},
|
||||
|
||||
update: async (key: string, value: any): Promise<SystemSetting> => {
|
||||
const response = await api.put(`/admin/settings/${key}`, { value })
|
||||
return response.data.data
|
||||
}
|
||||
}
|
||||
update: async (key: string, value: unknown): Promise<SystemSetting> => {
|
||||
const response = await api.put(`/admin/settings/${key}`, { value });
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
// System Health API
|
||||
// System Health API (placeholder - optional)
|
||||
export interface SystemHealth {
|
||||
status: string
|
||||
database: string
|
||||
memory: any
|
||||
uptime: number
|
||||
status: string;
|
||||
database: string;
|
||||
memory?: unknown;
|
||||
uptime?: number;
|
||||
}
|
||||
|
||||
export const healthAPI = {
|
||||
check: async (): Promise<SystemHealth> => {
|
||||
const response = await api.get('/admin/health')
|
||||
return response.data.data || response.data
|
||||
}
|
||||
}
|
||||
const response = await api.get('/admin/health').catch(() => ({ data: { data: {} } }));
|
||||
return response.data?.data || response.data || {};
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user