100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
|
|
import type { H3Event } from 'h3'
|
||
|
|
|
||
|
|
// Types based on API responses
|
||
|
|
export interface Course {
|
||
|
|
id: number
|
||
|
|
title: string
|
||
|
|
slug: string
|
||
|
|
description: string
|
||
|
|
thumbnail_url: string
|
||
|
|
price: string
|
||
|
|
is_free: boolean
|
||
|
|
have_certificate: boolean
|
||
|
|
status: string // 'DRAFT' | 'PUBLISHED' | ...
|
||
|
|
category_id: number
|
||
|
|
created_at?: string
|
||
|
|
updated_at?: string
|
||
|
|
created_by?: number
|
||
|
|
updated_by?: number
|
||
|
|
approved_at?: string
|
||
|
|
approved_by?: number
|
||
|
|
rejection_reason?: string
|
||
|
|
|
||
|
|
// Helper properties for UI (may be computed or mapped)
|
||
|
|
rating?: string
|
||
|
|
lessons?: number | string
|
||
|
|
levelType?: 'neutral' | 'warning' | 'success' // For UI badging
|
||
|
|
}
|
||
|
|
|
||
|
|
interface CourseResponse {
|
||
|
|
code: number
|
||
|
|
message: string
|
||
|
|
data: Course[]
|
||
|
|
total: number
|
||
|
|
}
|
||
|
|
|
||
|
|
export const useCourse = () => {
|
||
|
|
const config = useRuntimeConfig()
|
||
|
|
const API_BASE_URL = config.public.apiBase as string
|
||
|
|
const { token } = useAuth()
|
||
|
|
|
||
|
|
const fetchCourses = async () => {
|
||
|
|
try {
|
||
|
|
const { data, error } = await useFetch<CourseResponse>(`${API_BASE_URL}/courses`, {
|
||
|
|
method: 'GET',
|
||
|
|
headers: token.value ? {
|
||
|
|
Authorization: `Bearer ${token.value}`
|
||
|
|
} : {}
|
||
|
|
})
|
||
|
|
|
||
|
|
if (error.value) throw error.value
|
||
|
|
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: data.value?.data || [],
|
||
|
|
total: data.value?.total || 0
|
||
|
|
}
|
||
|
|
} catch (err: any) {
|
||
|
|
console.error('Fetch courses failed:', err)
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
error: err.data?.message || err.message || 'Error fetching courses'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const fetchCourseById = async (id: number) => {
|
||
|
|
try {
|
||
|
|
const { data, error } = await useFetch<CourseResponse>(`${API_BASE_URL}/courses/${id}`, {
|
||
|
|
method: 'GET',
|
||
|
|
headers: token.value ? {
|
||
|
|
Authorization: `Bearer ${token.value}`
|
||
|
|
} : {}
|
||
|
|
})
|
||
|
|
|
||
|
|
if (error.value) throw error.value
|
||
|
|
|
||
|
|
// API returns data array even for single item based on schema
|
||
|
|
const courseData = data.value?.data?.[0]
|
||
|
|
|
||
|
|
if (!courseData) throw new Error('Course not found')
|
||
|
|
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
data: courseData
|
||
|
|
}
|
||
|
|
} catch (err: any) {
|
||
|
|
console.error('Fetch course details failed:', err)
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
error: err.data?.message || err.message || 'Error fetching course details'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
fetchCourses,
|
||
|
|
fetchCourseById
|
||
|
|
}
|
||
|
|
}
|