From 23d9e44cc944f5c8fdb4ebbce481361f86f6dc86 Mon Sep 17 00:00:00 2001 From: supalerk-ar66 Date: Wed, 11 Feb 2026 17:06:18 +0700 Subject: [PATCH] feat: Implement course detail viewing and enrollment functionality with a new `useCourse` composable. --- .../components/discovery/CourseDetailView.vue | 30 ++++++----- Frontend-Learner/composables/useCourse.ts | 10 ++-- Frontend-Learner/nuxt.config.ts | 2 +- Frontend-Learner/pages/course/[id].vue | 50 +++++++++++++++---- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/Frontend-Learner/components/discovery/CourseDetailView.vue b/Frontend-Learner/components/discovery/CourseDetailView.vue index 8e741b69..380ee4c5 100644 --- a/Frontend-Learner/components/discovery/CourseDetailView.vue +++ b/Frontend-Learner/components/discovery/CourseDetailView.vue @@ -66,25 +66,31 @@ const handleEnroll = () => { - + 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