feat: Introduce core admin and instructor dashboards with dedicated services, pages, and layouts.

This commit is contained in:
Missez 2026-02-13 11:55:12 +07:00
parent af14610442
commit 5442f1beb6
7 changed files with 497 additions and 7 deletions

View file

@ -254,6 +254,57 @@ export interface AuditLogStats {
recentActivity: AuditLog[];
}
export interface RecommendedCourse {
id: number;
title: {
th: string;
en: string;
};
slug: string;
description: {
th: string;
en: string;
};
thumbnail_url: string | null;
price: number;
is_free: boolean;
have_certificate: boolean;
is_recommended: boolean;
status: string;
created_at: string;
updated_at: string;
category: {
id: number;
name: {
th: string;
en: string;
};
};
instructors: {
user_id: number;
is_primary: boolean;
user: {
id: number;
username: string;
email: string;
};
}[];
creator: {
id: number;
username: string;
email: string;
};
chapters_count: number;
lessons_count: number;
}
export interface RecommendedCoursesListResponse {
code: number;
message: string;
data: RecommendedCourse[];
total: number;
}
// Helper function to get auth token from cookie
const getAuthToken = (): string => {
const tokenCookie = useCookie('token');
@ -517,6 +568,48 @@ export const adminService = {
headers: { Authorization: `Bearer ${token}` },
query: { days }
});
return response;
},
// ============ Recommended Courses ============
async getRecommendedCourses(): Promise<RecommendedCourse[]> {
const config = useRuntimeConfig();
const token = getAuthToken();
const response = await $fetch<RecommendedCoursesListResponse>('/api/admin/recommended-courses', {
baseURL: config.public.apiBaseUrl as string,
headers: {
Authorization: `Bearer ${token}`
}
});
return response.data;
},
async getRecommendedCourseById(id: number): Promise<RecommendedCourse> {
const config = useRuntimeConfig();
const token = getAuthToken();
const response = await $fetch<ApiResponse<RecommendedCourse>>(`/api/admin/recommended-courses/${id}`, {
baseURL: config.public.apiBaseUrl as string,
headers: {
Authorization: `Bearer ${token}`
}
});
return response.data;
},
async toggleCourseRecommendation(courseId: number, isRecommended: boolean): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const token = getAuthToken();
const response = await $fetch<ApiResponse<void>>(`/api/admin/recommended-courses/${courseId}/toggle`, {
method: 'PUT',
baseURL: config.public.apiBaseUrl as string,
headers: {
Authorization: `Bearer ${token}`
},
query: { is_recommended: isRecommended }
});
return response;
}
};

View file

@ -301,6 +301,10 @@ export const instructorService = {
return await authRequest<ApiResponse<void>>(`/api/instructors/courses/send-review/${courseId}`, { method: 'POST' });
},
async setCourseDraft(courseId: number): Promise<ApiResponse<void>> {
return await authRequest<ApiResponse<void>>(`/api/instructors/courses/set-draft/${courseId}`, { method: 'POST' });
},
async getEnrolledStudents(
courseId: number,
page: number = 1,