feat: Introduce core e-learning features with new pages for course details, dashboard, authentication, browsing, and learning, supported by a useCourse composable.
This commit is contained in:
parent
c982ab2c05
commit
0eb9b522f6
6 changed files with 109 additions and 38 deletions
|
|
@ -15,23 +15,36 @@ useHead({
|
|||
title: "รายการคอร์ส - e-Learning",
|
||||
});
|
||||
|
||||
// UI State
|
||||
// ==========================================
|
||||
// 1. ตัวแปร State (สถานะของ UI)
|
||||
// ==========================================
|
||||
// showDetail: ควบคุมการแสดงผลหน้ารายละเอียดคอร์ส (true = แสดง, false = แสดงรายการ)
|
||||
const showDetail = ref(false);
|
||||
// searchQuery: เก็บคำค้นหาที่ผู้ใช้พิมพ์
|
||||
const searchQuery = ref("");
|
||||
// isCategoryOpen: ควบคุมการเปิด/ปิดเมนูหมวดหมู่ด้านข้าง
|
||||
const isCategoryOpen = ref(true);
|
||||
|
||||
// Helper to get localized text
|
||||
// ==========================================
|
||||
// 2. ฟังก์ชันช่วยเหลือ (Helpers)
|
||||
// ==========================================
|
||||
// getLocalizedText: เลือกแสดงภาษาไทยหรืออังกฤษตามข้อมูลที่มี
|
||||
// ถ้าเป็น object {th, en} จะพยายามหา th ก่อน, ถ้าไม่มีให้ใช้ en
|
||||
const getLocalizedText = (text: string | { th: string; en: string } | undefined) => {
|
||||
if (!text) return ''
|
||||
if (typeof text === 'string') return text
|
||||
return text.th || text.en || ''
|
||||
}
|
||||
|
||||
// Categories Data
|
||||
// ==========================================
|
||||
// 3. จัดการข้อมูลหมวดหมู่ (Categories)
|
||||
// ==========================================
|
||||
// ใช้ useCategory composable เพื่อดึงข้อมูลหมวดหมู่จาก API
|
||||
const { fetchCategories } = useCategory();
|
||||
const categories = ref<any[]>([]);
|
||||
const showAllCategories = ref(false);
|
||||
const showAllCategories = ref(false); // ควบคุมการแสดงหมวดหมู่ทั้งหมด (Show More/Less)
|
||||
|
||||
// ฟังก์ชันโหลดข้อมูลหมวดหมู่
|
||||
const loadCategories = async () => {
|
||||
const res = await fetchCategories();
|
||||
if (res.success) {
|
||||
|
|
@ -39,22 +52,28 @@ const loadCategories = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
// คำนวณหมวดหมู่ที่จะแสดงผล (ถ้ากด Show More จะแสดงทั้งหมด, ปกติแสดงแค่ 8 รายการ)
|
||||
const visibleCategories = computed(() => {
|
||||
return showAllCategories.value ? categories.value : categories.value.slice(0, 8);
|
||||
});
|
||||
|
||||
// Courses Data
|
||||
// ==========================================
|
||||
// 4. จัดการข้อมูลคอร์ส (Courses)
|
||||
// ==========================================
|
||||
// ใช้ useCourse composable สำหรับจัดการคอร์สเรียน (ดึงข้อมูล, ลงทะเบียน)
|
||||
const { fetchCourses, fetchCourseById, enrollCourse } = useCourse();
|
||||
const courses = ref<any[]>([]);
|
||||
const isLoading = ref(false);
|
||||
const selectedCourse = ref<any>(null);
|
||||
const isLoadingDetail = ref(false);
|
||||
const isEnrolling = ref(false);
|
||||
const isLoading = ref(false); // สถานะกำลังโหลดรายการคอร์ส
|
||||
const selectedCourse = ref<any>(null); // คอร์สที่ถูกเลือกดูรายละเอียด
|
||||
const isLoadingDetail = ref(false); // สถานะกำลังโหลดรายละเอียดคอร์ส
|
||||
const isEnrolling = ref(false); // สถานะกำลังกดลงทะเบียน
|
||||
|
||||
// ฟังก์ชันโหลดข้อมูลคอร์สทั้งหมด
|
||||
const loadCourses = async () => {
|
||||
isLoading.value = true;
|
||||
const res = await fetchCourses();
|
||||
if (res.success) {
|
||||
// แปลงข้อมูลเบื้องต้นสำหรับแสดงผลในการ์ด
|
||||
courses.value = (res.data || []).map((c: any) => ({
|
||||
...c,
|
||||
rating: "0.0",
|
||||
|
|
@ -65,11 +84,13 @@ const loadCourses = async () => {
|
|||
isLoading.value = false;
|
||||
};
|
||||
|
||||
// ฟังก์ชันเลือกคอร์สเพื่อดูรายละเอียด
|
||||
const selectCourse = async (id: number) => {
|
||||
isLoadingDetail.value = true;
|
||||
selectedCourse.value = null;
|
||||
showDetail.value = true;
|
||||
showDetail.value = true; // เปลี่ยนหน้าเป็นแบบ Detail View
|
||||
|
||||
// ดึงข้อมูลรายละเอียดคอร์สจาก API โดยใช้ ID
|
||||
const res = await fetchCourseById(id);
|
||||
if (res.success) {
|
||||
selectedCourse.value = res.data;
|
||||
|
|
@ -77,14 +98,15 @@ const selectCourse = async (id: number) => {
|
|||
isLoadingDetail.value = false;
|
||||
};
|
||||
|
||||
// ฟังก์ชันลงทะเบียนเรียน (Enroll)
|
||||
const handleEnroll = async (id: number) => {
|
||||
if (isEnrolling.value) return;
|
||||
if (isEnrolling.value) return; // ป้องกันการกดรัว
|
||||
isEnrolling.value = true;
|
||||
|
||||
const res = await enrollCourse(id);
|
||||
|
||||
if (res.success) {
|
||||
// Navigate to my-courses where the success modal will be shown
|
||||
// ถ้าสำเร็จ ให้เปลี่ยนหน้าไปที่ "คอร์สของฉัน" พร้อมส่ง parameter enrolled=true เพื่อแสดง popup
|
||||
return navigateTo('/dashboard/my-courses?enrolled=true');
|
||||
} else {
|
||||
alert(res.error || 'Failed to enroll');
|
||||
|
|
@ -94,23 +116,28 @@ const handleEnroll = async (id: number) => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
// โหลดข้อมูลเมื่อหน้าเว็บเริ่มทำงาน
|
||||
loadCategories();
|
||||
loadCourses();
|
||||
});
|
||||
|
||||
// Filter Logic based on search query
|
||||
// Filter Logic based on search query and category
|
||||
// ==========================================
|
||||
// 5. ระบบกรองและค้นหา (Filter & Search)
|
||||
// ==========================================
|
||||
// selectedCategoryIds: เก็บ ID ของหมวดหมู่ที่ถูกติ๊กเลือก
|
||||
const selectedCategoryIds = ref<number[]>([]);
|
||||
|
||||
// คำนวณคอร์สที่จะแสดงผลจริง (Filter Logic)
|
||||
const filteredCourses = computed(() => {
|
||||
let result = courses.value;
|
||||
|
||||
// Filter by Category
|
||||
// 1. กรองตามหมวดหมู่ (Category Filter)
|
||||
if (selectedCategoryIds.value.length > 0) {
|
||||
result = result.filter(c => selectedCategoryIds.value.includes(c.category_id));
|
||||
}
|
||||
|
||||
// Filter by Search Query
|
||||
// 2. กรองตามคำค้นหา (Search Query) - ค้นหาจากชื่อหรือคำอธิบาย
|
||||
if (searchQuery.value) {
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
result = result.filter(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue