feat: Implement initial frontend for admin and instructor roles, including dashboards, course management, authentication, and core services.
This commit is contained in:
parent
832a8f5067
commit
127b63de49
16 changed files with 1505 additions and 102 deletions
|
|
@ -214,6 +214,46 @@ export interface UpdateCategoryRequest {
|
|||
};
|
||||
}
|
||||
|
||||
// Audit Logs Interfaces
|
||||
export interface AuditLog {
|
||||
id: number;
|
||||
user_id: number;
|
||||
action: string;
|
||||
entity_type: string;
|
||||
entity_id: number;
|
||||
old_value: string | null;
|
||||
new_value: string | null;
|
||||
ip_address: string | null;
|
||||
user_agent: string | null;
|
||||
metadata: string | null;
|
||||
created_at: string;
|
||||
user: {
|
||||
email: string;
|
||||
username: string;
|
||||
id: number;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface AuditLogsListResponse {
|
||||
data: AuditLog[];
|
||||
pagination: {
|
||||
totalPages: number;
|
||||
total: number;
|
||||
limit: number;
|
||||
page: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AuditLogStats {
|
||||
totalLogs: number;
|
||||
todayLogs: number;
|
||||
actionSummary: {
|
||||
action: string;
|
||||
count: number;
|
||||
}[];
|
||||
recentActivity: AuditLog[];
|
||||
}
|
||||
|
||||
// Helper function to get auth token from cookie
|
||||
const getAuthToken = (): string => {
|
||||
const tokenCookie = useCookie('token');
|
||||
|
|
@ -391,6 +431,92 @@ export const adminService = {
|
|||
}
|
||||
});
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
// ============ Audit Logs ============
|
||||
async getAuditLogs(
|
||||
page: number = 1,
|
||||
limit: number = 20,
|
||||
filters: {
|
||||
userId?: number;
|
||||
action?: string;
|
||||
entityType?: string;
|
||||
entityId?: number;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
} = {}
|
||||
): Promise<AuditLogsListResponse> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
|
||||
let query: any = { page, limit };
|
||||
if (filters.userId) query.userId = filters.userId;
|
||||
if (filters.action) query.action = filters.action;
|
||||
if (filters.entityType) query.entityType = filters.entityType;
|
||||
if (filters.entityId) query.entityId = filters.entityId;
|
||||
if (filters.startDate) query.startDate = filters.startDate;
|
||||
if (filters.endDate) query.endDate = filters.endDate;
|
||||
|
||||
const response = await $fetch<AuditLogsListResponse>('/api/admin/audit-logs', {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
query
|
||||
});
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
async getAuditLogById(id: number): Promise<AuditLog> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<AuditLog>(`/api/admin/audit-logs/${id}`, {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
async getAuditLogStats(): Promise<AuditLogStats> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<AuditLogStats>('/api/admin/audit-logs/stats/summary', {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
async getAuditLogsByEntity(entityType: string, entityId: number): Promise<AuditLog[]> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<AuditLog[]>(`/api/admin/audit-logs/entity/${entityType}/${entityId}`, {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
async getAuditLogsByUser(userId: number, limit: number = 20): Promise<AuditLog[]> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<AuditLog[]>(`/api/admin/audit-logs/user/${userId}/activity`, {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
query: { limit }
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
async cleanupAuditLogs(days: number = 90): Promise<ApiResponse<void>> {
|
||||
const config = useRuntimeConfig();
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<ApiResponse<void>>('/api/admin/audit-logs/cleanup', {
|
||||
method: 'DELETE',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
query: { days }
|
||||
});
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ export const instructorService = {
|
|||
|
||||
async submitCourseForApproval(courseId: number): Promise<ApiResponse<void>> {
|
||||
return await authRequest<ApiResponse<void>>(
|
||||
`/api/instructors/courses/${courseId}/submit`,
|
||||
`/api/instructors/courses/send-review/${courseId}`,
|
||||
{ method: 'POST' }
|
||||
);
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue