+
+
![]()
-
-
-
-
-
{{ $t('course.noVideoPreview') || 'Preview Not Available' }}
+
+
![]()
+
+
+
diff --git a/Frontend-Learner/composables/useCourse.ts b/Frontend-Learner/composables/useCourse.ts
index ce2cd3f4..1a587eb6 100644
--- a/Frontend-Learner/composables/useCourse.ts
+++ b/Frontend-Learner/composables/useCourse.ts
@@ -18,6 +18,7 @@ export interface Course {
approved_at?: string
approved_by?: number
rejection_reason?: string
+ enrolled?: boolean
rating?: string
@@ -253,21 +254,20 @@ export const useCourse = () => {
message: data.message
}
} catch (err: any) {
- console.error('Enroll course failed:', err)
-
- // เช็ค Error 409 Conflict หรือ 400 Bad Request (กรณีลงทะเบียนไปแล้ว)
- // API ใหม่ส่ง 400 พร้อม error.code = "VALIDATION_ERROR" และ message "Already enrolled..."
const status = err.statusCode || err.status || err.response?.status
const errorData = err.data?.error || err.data
+ // เช็ค Error 409 Conflict หรือ 400 Bad Request (กรณีลงทะเบียนไปแล้ว)
+ // สำหรับกรณีนี้ เราจะไม่ log console.error ให้รกหน้าจอเพราะเป็นเรื่องที่ดักจับได้
if (status === 409 || (status === 400 && errorData?.message?.includes('Already enrolled'))) {
return {
success: false,
error: 'ท่านได้ลงทะเบียนไปแล้ว',
- code: 409 // Treat as conflict logic internally
+ code: 409 // treat internally as conflict
}
}
+ console.error('Enroll course failed:', err)
return {
success: false,
error: errorData?.message || err.message || 'Error enrolling in course',
diff --git a/Frontend-Learner/nuxt.config.ts b/Frontend-Learner/nuxt.config.ts
index 0ab78514..b3079964 100644
--- a/Frontend-Learner/nuxt.config.ts
+++ b/Frontend-Learner/nuxt.config.ts
@@ -36,7 +36,7 @@ export default defineNuxtConfig({
extras: {
fontIcons: ["material-icons"],
},
- plugins: ["Notify"], // เปิดใช้ Plugin Notify
+ plugins: ["Notify", "Dialog"], // เปิดใช้ Plugin Notify และ Dialog
config: {
brand: { // กำหนดชุดสีหลัก (Theme Colors)
primary: "#4b82f7",
diff --git a/Frontend-Learner/pages/course/[id].vue b/Frontend-Learner/pages/course/[id].vue
index aef56e85..9c559339 100644
--- a/Frontend-Learner/pages/course/[id].vue
+++ b/Frontend-Learner/pages/course/[id].vue
@@ -31,6 +31,23 @@ const isEnrolling = ref(false)
const handleEnroll = async () => {
if (!course.value) return
if (isEnrolling.value) return
+
+ // กรณีเคยกดลงทะเบียนไปแล้ว (Check จากสถานะคอร์ส)
+ if (course.value.enrolled) {
+ $q.dialog({
+ message: `
ท่านเคยลงทะเบียนคอร์ส "${getLocalizedText(course.value.title)}" นี้ไปเรียบร้อยแล้ว
`,
+ html: true,
+ ok: {
+ label: 'ตกลง',
+ color: 'primary',
+ rounded: true,
+ unelevated: true,
+ padding: '8px 32px'
+ }
+ })
+ return
+ }
+
isEnrolling.value = true
// เรียก API ลงทะเบียนเรียน
@@ -38,7 +55,6 @@ const handleEnroll = async () => {
if (res.success) {
// ถ้าสำเร็จ ให้เปลี่ยนหน้าไปที่ "คอร์สของฉัน" พร้อม params enrolled=true
- // Use object syntax for robust query param handling
const targetId = route.params.id || course.value?.id
return navigateTo({
path: '/dashboard/my-courses',
@@ -47,14 +63,30 @@ const handleEnroll = async () => {
course_id: String(targetId)
}
})
- // กรณี error แสดง Toast notification แทน alert
- $q.notify({
- type: 'negative',
- message: res.error || 'Failed to enroll',
- position: 'top',
- timeout: 3000,
- actions: [{ icon: 'close', color: 'white' }]
- })
+ } else {
+ // กรณี API แจ้งว่าเคยลงทะเบียนไปแล้ว (Code 409)
+ if (res.code === 409) {
+ $q.dialog({
+ message: `
ท่านเคยลงทะเบียนคอร์ส "${getLocalizedText(course.value.title)}" นี้ไปเรียบร้อยแล้ว
`,
+ html: true,
+ ok: {
+ label: 'ตกลง',
+ color: 'primary',
+ rounded: true,
+ unelevated: true,
+ padding: '8px 32px'
+ }
+ })
+ } else {
+ // กรณี error ทั่วไป แสดง Toast notification
+ $q.notify({
+ type: 'negative',
+ message: res.error || 'Failed to enroll',
+ position: 'top',
+ timeout: 3000,
+ actions: [{ icon: 'close', color: 'white' }]
+ })
+ }
}
isEnrolling.value = false