300 lines
12 KiB
TypeScript
300 lines
12 KiB
TypeScript
import http from "./http"
|
|
import type {
|
|
GetCourseCategoriesResponse,
|
|
GetCoursesResponse,
|
|
CreateCourseRequest,
|
|
UpdateCourseRequest,
|
|
GetSubCoursesResponse,
|
|
CreateSubCourseRequest,
|
|
UpdateSubCourseRequest,
|
|
UpdateSubCourseStatusRequest,
|
|
GetSubCourseVideosResponse,
|
|
CreateSubCourseVideoRequest,
|
|
UpdateSubCourseVideoRequest,
|
|
GetPracticesResponse,
|
|
CreatePracticeRequest,
|
|
UpdatePracticeRequest,
|
|
UpdatePracticeStatusRequest,
|
|
CreatePracticeQuestionRequest,
|
|
UpdatePracticeQuestionRequest,
|
|
GetProgramsResponse,
|
|
GetLevelsResponse,
|
|
GetModulesResponse,
|
|
UpdateProgramStatusRequest,
|
|
CreateProgramRequest,
|
|
UpdateProgramRequest,
|
|
CreateLevelRequest,
|
|
UpdateLevelRequest,
|
|
UpdateLevelStatusRequest,
|
|
CreateModuleRequest,
|
|
UpdateModuleRequest,
|
|
UpdateModuleStatusRequest,
|
|
GetQuestionSetsResponse,
|
|
GetQuestionSetsParams,
|
|
GetQuestionSetDetailResponse,
|
|
GetQuestionSetQuestionsResponse,
|
|
CreateQuestionSetRequest,
|
|
CreateQuestionSetResponse,
|
|
AddQuestionToSetRequest,
|
|
CreateQuestionRequest,
|
|
CreateQuestionResponse,
|
|
GetQuestionDetailResponse,
|
|
GetQuestionsParams,
|
|
GetQuestionsResponse,
|
|
CreateVimeoVideoRequest,
|
|
CreateCourseCategoryRequest,
|
|
GetSubCoursePrerequisitesResponse,
|
|
AddSubCoursePrerequisiteRequest,
|
|
GetLearningPathResponse,
|
|
GetSubCourseEntryAssessmentResponse,
|
|
ReorderItem,
|
|
GetRatingsResponse,
|
|
GetRatingsParams,
|
|
GetVimeoSampleResponse,
|
|
} from "../types/course.types"
|
|
|
|
export const getCourseCategories = () =>
|
|
http.get<GetCourseCategoriesResponse>("/course-management/categories")
|
|
|
|
export const createCourseCategory = (data: CreateCourseCategoryRequest) =>
|
|
http.post("/course-management/categories", data)
|
|
|
|
export const getCoursesByCategory = (categoryId: number) =>
|
|
http.get<GetCoursesResponse>(`/course-management/categories/${categoryId}/courses`)
|
|
|
|
export const createCourse = (data: CreateCourseRequest) =>
|
|
http.post("/course-management/courses", data)
|
|
|
|
export const deleteCourse = (courseId: number) =>
|
|
http.delete(`/course-management/courses/${courseId}`)
|
|
|
|
export const updateCourseStatus = (courseId: number, isActive: boolean) =>
|
|
http.put(`/course-management/courses/${courseId}`, { is_active: isActive })
|
|
|
|
export const updateCourse = (courseId: number, data: UpdateCourseRequest) =>
|
|
http.put(`/course-management/courses/${courseId}`, data)
|
|
|
|
// SubCourse APIs (New Hierarchy)
|
|
export const getSubCoursesByCourse = (courseId: number) =>
|
|
http.get<GetSubCoursesResponse>(`/course-management/courses/${courseId}/sub-courses`)
|
|
|
|
export const createSubCourse = (data: CreateSubCourseRequest) =>
|
|
http.post("/course-management/sub-courses", data)
|
|
|
|
export const updateSubCourse = (subCourseId: number, data: UpdateSubCourseRequest) =>
|
|
http.patch(`/course-management/sub-courses/${subCourseId}`, data)
|
|
|
|
export const updateSubCourseStatus = (subCourseId: number, data: UpdateSubCourseStatusRequest) =>
|
|
http.patch(`/course-management/sub-courses/${subCourseId}`, data)
|
|
|
|
export const deleteSubCourse = (subCourseId: number) =>
|
|
http.delete(`/course-management/sub-courses/${subCourseId}`)
|
|
|
|
// SubCourse Video APIs
|
|
export const getVideosBySubCourse = (subCourseId: number) =>
|
|
http.get<GetSubCourseVideosResponse>(`/course-management/sub-courses/${subCourseId}/videos`)
|
|
|
|
export const createSubCourseVideo = (data: CreateSubCourseVideoRequest) =>
|
|
http.post("/course-management/sub-course-videos", data)
|
|
|
|
export const updateSubCourseVideo = (videoId: number, data: UpdateSubCourseVideoRequest) =>
|
|
http.put(`/course-management/sub-course-videos/${videoId}`, data)
|
|
|
|
export const deleteSubCourseVideo = (videoId: number) =>
|
|
http.delete(`/course-management/sub-course-videos/${videoId}`)
|
|
|
|
// Practice APIs - for SubCourse practices (New Hierarchy)
|
|
// Practices are sourced from question sets by owner_type=SUB_COURSE.
|
|
export const getPracticesBySubCourse = (subCourseId: number) =>
|
|
http.get<GetQuestionSetsResponse>("/question-sets/by-owner", {
|
|
params: { owner_type: "SUB_COURSE", owner_id: subCourseId },
|
|
})
|
|
|
|
export const createPractice = (data: CreatePracticeRequest) =>
|
|
http.post("/course-management/practices", data)
|
|
|
|
export const updatePractice = (practiceId: number, data: UpdatePracticeRequest) =>
|
|
http.put(`/course-management/practices/${practiceId}`, data)
|
|
|
|
export const updatePracticeStatus = (practiceId: number, data: UpdatePracticeStatusRequest) =>
|
|
http.put(`/course-management/practices/${practiceId}`, data)
|
|
|
|
export const deletePractice = (practiceId: number) =>
|
|
http.delete(`/course-management/practices/${practiceId}`)
|
|
|
|
// Practice Questions APIs
|
|
export const getPracticeQuestions = (practiceId: number) =>
|
|
http.get<GetQuestionSetQuestionsResponse>(`/question-sets/${practiceId}/questions`)
|
|
|
|
export const createPracticeQuestion = (data: CreatePracticeQuestionRequest) =>
|
|
http.post("/course-management/practice-questions", data)
|
|
|
|
export const updatePracticeQuestion = (questionId: number, data: UpdatePracticeQuestionRequest) =>
|
|
http.put(`/course-management/practice-questions/${questionId}`, data)
|
|
|
|
export const deletePracticeQuestion = (questionId: number) =>
|
|
http.delete(`/course-management/practice-questions/${questionId}`)
|
|
|
|
// ============================================
|
|
// Legacy APIs (deprecated - using SubCourse hierarchy now)
|
|
// Keeping for backward compatibility
|
|
// ============================================
|
|
|
|
export const getProgramsByCourse = (courseId: number) =>
|
|
http.get<GetProgramsResponse>(`/course-management/courses/${courseId}/programs`)
|
|
|
|
export const updateProgramStatus = (programId: number, data: UpdateProgramStatusRequest) =>
|
|
http.patch(`/course-management/programs/${programId}`, data)
|
|
|
|
export const deleteProgram = (programId: number) =>
|
|
http.delete(`/course-management/programs/${programId}`)
|
|
|
|
export const createProgram = (data: CreateProgramRequest) =>
|
|
http.post("/course-management/programs", data)
|
|
|
|
export const updateProgram = (programId: number, data: UpdateProgramRequest) =>
|
|
http.patch(`/course-management/programs/${programId}`, data)
|
|
|
|
export const getLevelsByProgram = (programId: number) =>
|
|
http.get<GetLevelsResponse>(`/course-management/programs/${programId}/levels`)
|
|
|
|
export const createLevel = (data: CreateLevelRequest) =>
|
|
http.post("/course-management/levels", data)
|
|
|
|
export const updateLevel = (levelId: number, data: UpdateLevelRequest) =>
|
|
http.put(`/course-management/levels/${levelId}`, data)
|
|
|
|
export const updateLevelStatus = (levelId: number, data: UpdateLevelStatusRequest) =>
|
|
http.put(`/course-management/levels/${levelId}`, data)
|
|
|
|
export const deleteLevel = (levelId: number) =>
|
|
http.delete(`/course-management/levels/${levelId}`)
|
|
|
|
export const getModulesByLevel = (levelId: number) =>
|
|
http.get<GetModulesResponse>(`/course-management/levels/${levelId}/modules`)
|
|
|
|
export const createModule = (data: CreateModuleRequest) =>
|
|
http.post("/course-management/modules", data)
|
|
|
|
export const updateModule = (moduleId: number, data: UpdateModuleRequest) =>
|
|
http.put(`/course-management/modules/${moduleId}`, data)
|
|
|
|
export const updateModuleStatus = (moduleId: number, data: UpdateModuleStatusRequest) =>
|
|
http.put(`/course-management/modules/${moduleId}`, data)
|
|
|
|
export const deleteModule = (moduleId: number) =>
|
|
http.delete(`/course-management/modules/${moduleId}`)
|
|
|
|
export const getPracticesByLevel = (levelId: number) =>
|
|
http.get<GetPracticesResponse>(`/course-management/levels/${levelId}/practices`)
|
|
|
|
export const getPracticesByModule = (moduleId: number) =>
|
|
http.get<GetPracticesResponse>(`/course-management/modules/${moduleId}/practices`)
|
|
|
|
// Question Sets API
|
|
export const getQuestionSets = (params?: GetQuestionSetsParams) =>
|
|
http.get<GetQuestionSetsResponse>("/question-sets", { params })
|
|
|
|
export const getQuestionSetsByOwner = (ownerType: string, ownerId: number) =>
|
|
http.get<GetQuestionSetsResponse>("/question-sets/by-owner", {
|
|
params: { owner_type: ownerType, owner_id: ownerId },
|
|
})
|
|
|
|
export const getQuestionSetById = (questionSetId: number) =>
|
|
http.get<GetQuestionSetDetailResponse>(`/question-sets/${questionSetId}`)
|
|
|
|
export const getQuestionSetQuestions = (questionSetId: number) =>
|
|
http.get<GetQuestionSetQuestionsResponse>(`/question-sets/${questionSetId}/questions`)
|
|
|
|
export const createQuestionSet = (data: CreateQuestionSetRequest) =>
|
|
http.post<CreateQuestionSetResponse>("/question-sets", data)
|
|
|
|
export const addQuestionToSet = (questionSetId: number, data: AddQuestionToSetRequest) =>
|
|
http.post(`/question-sets/${questionSetId}/questions`, data)
|
|
|
|
export const createQuestion = (data: CreateQuestionRequest) =>
|
|
http.post<CreateQuestionResponse>("/questions", data)
|
|
|
|
export const getQuestions = (params: GetQuestionsParams) =>
|
|
http.get<GetQuestionsResponse>("/questions", { params })
|
|
|
|
export const getQuestionById = (questionId: number) =>
|
|
http.get<GetQuestionDetailResponse>(`/questions/${questionId}`)
|
|
|
|
export const deleteQuestion = (questionId: number) =>
|
|
http.delete(`/questions/${questionId}`)
|
|
|
|
export const updateQuestion = (questionId: number, data: CreateQuestionRequest) =>
|
|
http.put(`/questions/${questionId}`, data)
|
|
|
|
export const deleteQuestionSet = (questionSetId: number) =>
|
|
http.delete(`/question-sets/${questionSetId}`)
|
|
|
|
export const createVimeoVideo = (data: CreateVimeoVideoRequest) =>
|
|
http.post("/course-management/videos/vimeo", data)
|
|
|
|
// Sub-course Prerequisite APIs
|
|
export const getSubCoursePrerequisites = (subCourseId: number) =>
|
|
http.get<GetSubCoursePrerequisitesResponse>(`/course-management/sub-courses/${subCourseId}/prerequisites`)
|
|
|
|
export const addSubCoursePrerequisite = (subCourseId: number, data: AddSubCoursePrerequisiteRequest) =>
|
|
http.post(`/course-management/sub-courses/${subCourseId}/prerequisites`, data)
|
|
|
|
export const removeSubCoursePrerequisite = (subCourseId: number, prerequisiteId: number) =>
|
|
http.delete(`/course-management/sub-courses/${subCourseId}/prerequisites/${prerequisiteId}`)
|
|
|
|
// Learning Path APIs
|
|
export const getLearningPath = (courseId: number) =>
|
|
http.get<GetLearningPathResponse>(`/course-management/courses/${courseId}/learning-path`)
|
|
|
|
export const getSubCourseEntryAssessment = (subCourseId: number) =>
|
|
http.get<GetSubCourseEntryAssessmentResponse>(
|
|
`/question-sets/sub-courses/${subCourseId}/entry-assessment`,
|
|
)
|
|
|
|
const buildReorderPayload = (items: ReorderItem[]) => {
|
|
const normalized = items.map((item, idx) => ({
|
|
id: Number(item.id),
|
|
position: Number(item.position ?? idx),
|
|
}))
|
|
|
|
const hasInvalid = normalized.some(
|
|
(item) =>
|
|
Number.isNaN(item.id) ||
|
|
Number.isNaN(item.position) ||
|
|
!Number.isFinite(item.id) ||
|
|
!Number.isFinite(item.position),
|
|
)
|
|
|
|
if (hasInvalid) {
|
|
throw new Error("Invalid reorder payload: ids/positions must be numeric.")
|
|
}
|
|
|
|
return { items: normalized }
|
|
}
|
|
|
|
export const reorderCategories = (items: ReorderItem[]) =>
|
|
http.put("/course-management/categories/reorder", buildReorderPayload(items))
|
|
|
|
export const reorderCourses = (items: ReorderItem[]) =>
|
|
http.put("/course-management/courses/reorder", buildReorderPayload(items))
|
|
|
|
export const reorderSubCourses = (items: ReorderItem[]) =>
|
|
http.put("/course-management/sub-courses/reorder", buildReorderPayload(items))
|
|
|
|
export const reorderVideos = (items: ReorderItem[]) =>
|
|
http.put("/course-management/videos/reorder", buildReorderPayload(items))
|
|
|
|
export const reorderPractices = (items: ReorderItem[]) =>
|
|
http.put("/course-management/practices/reorder", buildReorderPayload(items))
|
|
|
|
// Ratings
|
|
export const getRatings = (params: GetRatingsParams) =>
|
|
http.get<GetRatingsResponse>("/ratings", { params })
|
|
|
|
// Vimeo Sample Video
|
|
export const getVimeoSample = (videoId: string, width = 640, height = 360) =>
|
|
http.get<GetVimeoSampleResponse>("/vimeo/sample", {
|
|
params: { video_id: videoId, width, height },
|
|
})
|