# API Usage Examples - Lesson Prerequisites ## New Endpoints Usage Examples --- ## 1. Check Lesson Access (Student) ### GET `/students/courses/:courseId/lessons/:lessonId/access-check` **Purpose**: ตรวจสอบว่าสามารถเข้าถึง lesson ได้หรือไม่ โดยไม่ต้อง load content #### Request: ```http GET /api/students/courses/1/lessons/3/access-check Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` #### Response 200 (Can Access): ```json { "can_access": true, "lesson": { "id": 3, "title": "แบบทดสอบท้ายบท", "type": "quiz", "sort_order": 3 } } ``` #### Response 200 (Locked - Incomplete Prerequisites): ```json { "can_access": false, "reason": "incomplete_prerequisites", "message": "กรุณาเรียนบทเรียนก่อนหน้าให้เสร็จก่อน", "required_lessons": [ { "id": 1, "title": "บทที่ 1: แนะนำ", "type": "video", "is_completed": true }, { "id": 2, "title": "บทที่ 2: ตัวแปร", "type": "video", "is_completed": false } ], "missing_lessons": [2], "next_available_lesson": { "id": 2, "title": "บทที่ 2: ตัวแปร" } } ``` #### Response 200 (Locked - Quiz Not Passed): ```json { "can_access": false, "reason": "quiz_not_passed", "message": "กรุณาทำแบบทดสอบให้ผ่านก่อน", "required_quiz": { "lesson_id": 3, "title": "แบบทดสอบท้ายบท", "passing_score": 70, "your_best_score": 55, "attempts_used": 2, "max_attempts": 3 } } ``` --- ## 2. Get Learning Page with Lock Status (Student) ### GET `/students/courses/:courseId/learn` **Changes**: เพิ่ม `is_locked` และ `lock_reason` ในแต่ละ lesson #### Request: ```http GET /api/students/courses/1/learn Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` #### Response 200: ```json { "course": { "id": 1, "title": "Python สำหรับผู้เริ่มต้น" }, "enrollment": { "status": "enrolled", "progress_percentage": 35 }, "chapters": [ { "id": 1, "title": "บทที่ 1: พื้นฐาน", "sort_order": 1, "lessons": [ { "id": 1, "title": "1.1 แนะนำ Python", "type": "video", "duration": "00:15:30", "is_completed": true, "is_locked": false, "completed_at": "2024-12-23T10:00:00Z" }, { "id": 2, "title": "1.2 ตัวแปร", "type": "video", "duration": "00:20:00", "is_completed": false, "is_locked": false }, { "id": 3, "title": "1.3 แบบทดสอบ", "type": "quiz", "is_completed": false, "is_locked": true, "lock_reason": "incomplete_prerequisites", "required_lessons": [1, 2] }, { "id": 4, "title": "1.4 ขั้นสูง", "type": "video", "duration": "00:25:00", "is_completed": false, "is_locked": true, "lock_reason": "quiz_not_passed", "required_quiz": 3 } ] } ] } ``` --- ## 3. Get Lesson Content with Prerequisites Check (Student) ### GET `/students/courses/:courseId/lessons/:lessonId` **Changes**: ตรวจสอบ prerequisites ก่อน return content #### Request: ```http GET /api/students/courses/1/lessons/3 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` #### Response 403 (Locked): ```json { "error": { "code": "LESSON_LOCKED", "message": "Cannot access this lesson", "reason": "incomplete_prerequisites", "required_lessons": [1, 2], "completed_lessons": [1], "missing_lessons": [2], "next_available_lesson": { "id": 2, "title": "บทที่ 2: ตัวแปร", "type": "video" } } } ``` --- ## 4. Create Lesson with Prerequisites (Instructor) ### POST `/instructor/courses/:courseId/chapters/:chapterId/lessons` **Changes**: เพิ่ม fields สำหรับ prerequisites #### Request: ```http POST /api/instructor/courses/1/chapters/1/lessons Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json { "title": { "th": "แบบทดสอบท้ายบท", "en": "Chapter Quiz" }, "content": { "th": "

ทดสอบความเข้าใจ

", "en": "

Test your understanding

" }, "type": "quiz", "sort_order": 3, "is_sequential": true, "prerequisite_lesson_ids": [1, 2], "require_pass_quiz": true } ``` #### Response 201: ```json { "id": 3, "chapter_id": 1, "title": { "th": "แบบทดสอบท้ายบท", "en": "Chapter Quiz" }, "type": "quiz", "sort_order": 3, "is_sequential": true, "prerequisite_lesson_ids": [1, 2], "require_pass_quiz": true, "created_at": "2024-12-23T14:00:00Z" } ``` #### Response 422 (Validation Error): ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid prerequisites", "details": [ { "field": "prerequisite_lesson_ids", "message": "Lesson ID 99 does not exist" } ] } } ``` --- ## 5. View Lesson Prerequisites (Instructor) ### GET `/instructor/courses/:courseId/lessons/:lessonId/prerequisites` #### Request: ```http GET /api/instructor/courses/1/lessons/4/prerequisites Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` #### Response 200: ```json { "lesson": { "id": 4, "title": "บทที่ 3: ขั้นสูง", "type": "video", "sort_order": 4 }, "is_sequential": true, "prerequisites": [ { "id": 3, "title": "แบบทดสอบท้ายบท", "type": "quiz", "require_pass": true, "passing_score": 70 } ], "affected_students": { "total_enrolled": 150, "can_access": 85, "locked": 65, "breakdown": { "incomplete_prerequisites": 45, "quiz_not_passed": 20 } } } ``` --- ## 6. Update Lesson Prerequisites (Instructor) ### POST `/instructor/courses/:courseId/lessons/:lessonId/prerequisites` #### Request: ```http POST /api/instructor/courses/1/lessons/4/prerequisites Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json { "is_sequential": true, "prerequisite_lesson_ids": [3], "require_pass_quiz": false } ``` #### Response 200: ```json { "lesson_id": 4, "is_sequential": true, "prerequisites": [ { "id": 3, "title": "แบบทดสอบท้ายบท", "type": "quiz", "require_pass": false } ], "message": "Prerequisites updated successfully", "affected_students": { "newly_unlocked": 20, "still_locked": 45 } } ``` --- ## Error Codes ### New Error Codes for Prerequisites | Code | Description | |------|-------------| | `LESSON_LOCKED` | Cannot access lesson due to prerequisites | | `INCOMPLETE_PREREQUISITES` | Required lessons not completed | | `QUIZ_NOT_PASSED` | Required quiz not passed | | `INVALID_PREREQUISITES` | Invalid prerequisite configuration | | `CIRCULAR_DEPENDENCY` | Circular dependency detected | --- ## Frontend Integration Examples ### 1. Display Locked Lesson ```javascript function LessonItem({ lesson }) { if (lesson.is_locked) { return (
{lesson.title} {lesson.lock_reason === 'incomplete_prerequisites' && ( กรุณาเรียนบทเรียนก่อนหน้าให้เสร็จก่อน
    {lesson.required_lessons.map(id => (
  • Lesson {id}
  • ))}
)} {lesson.lock_reason === 'quiz_not_passed' && ( กรุณาทำแบบทดสอบให้ผ่านก่อน (ต้องได้ 70% ขึ้นไป) )}
); } return ( {lesson.is_completed ? : } {lesson.title} ); } ``` ### 2. Check Access Before Navigation ```javascript async function navigateToLesson(courseId, lessonId) { try { const response = await fetch( `/api/students/courses/${courseId}/lessons/${lessonId}/access-check`, { headers: { 'Authorization': `Bearer ${token}` } } ); const data = await response.json(); if (data.can_access) { // Navigate to lesson router.push(`/courses/${courseId}/lessons/${lessonId}`); } else { // Show lock message if (data.reason === 'incomplete_prerequisites') { showAlert(`กรุณาเรียนบทเรียนก่อนหน้าให้เสร็จก่อน`); // Highlight next available lesson highlightLesson(data.next_available_lesson.id); } else if (data.reason === 'quiz_not_passed') { showAlert(`กรุณาทำแบบทดสอบให้ผ่านก่อน`); // Navigate to quiz router.push(`/courses/${courseId}/lessons/${data.required_quiz.lesson_id}`); } } } catch (error) { console.error('Error checking lesson access:', error); } } ``` --- ## Summary **New Endpoints**: 3 - `GET /students/courses/:courseId/lessons/:lessonId/access-check` - `GET /instructor/courses/:courseId/lessons/:lessonId/prerequisites` - `POST /instructor/courses/:courseId/lessons/:lessonId/prerequisites` **Modified Endpoints**: 4 - `GET /students/courses/:courseId/learn` - เพิ่ม lock status - `GET /students/courses/:courseId/lessons/:lessonId` - เช็ค prerequisites - `POST /instructor/courses/:courseId/chapters/:chapterId/lessons` - รองรับ prerequisites - `PUT /instructor/courses/:courseId/lessons/:lessonId` - รองรับ prerequisites