# Human Language Mobile Integration Guide This guide explains how to integrate the new **Human Language** feature in the **Yimaru learner mobile app** (not admin). It is designed to keep the existing non-language hierarchy intact while introducing a dedicated CEFR-based flow for language learning. --- ## 1) Scope and Goals ### What is new - A dedicated backend API namespace for Human Language: - `GET /api/v1/course-management/human-language/courses/:courseId/lessons?cefr_level=A1..C3` - `POST /api/v1/course-management/human-language/lessons` (admin/instructor side) - `PATCH /api/v1/course-management/human-language/lessons/:id` (admin/instructor side) - CEFR levels are fixed to: - `A1, A2, A3, B1, B2, B3, C1, C2, C3` - No custom sub-levels in Human Language flow. ### What remains unchanged - Existing non-human-language content hierarchy and APIs. - Existing course/category/sub-course endpoints for non-language domains (programming, etc.). --- ## 2) Target Hierarchy for Human Language - Course Category (Human Language) - Course (e.g., English) - CEFR Lesson Unit (A1..C3 only) - Intro/lesson videos - Practices - Audio questions Backend implementation stores CEFR lesson units using the existing sub-course model, with CEFR mapped internally and validated strictly. --- ## 3) Authentication and Access All Human Language endpoints are under `/api/v1` and require bearer token auth. - Header: - `Authorization: Bearer ` ### Permission notes - **Learner mobile app** typically needs only the `GET` endpoint. - `POST` and `PATCH` are content-management endpoints and should generally be used by admin/instructor clients, not learner clients. If learner roles do not currently have `learning_tree.get`, coordinate RBAC assignment for read-only access to the `GET` endpoint. --- ## 4) Endpoint Contracts ## 4.1 Fetch lessons by CEFR level (learner-facing) ### Request `GET /api/v1/course-management/human-language/courses/{courseId}/lessons?cefr_level={A1|A2|A3|B1|B2|B3|C1|C2|C3}` ### Example `GET /api/v1/course-management/human-language/courses/12/lessons?cefr_level=B1` ### Response (success) ```json { "message": "Human-language lessons retrieved successfully", "data": { "course_id": 12, "course_title": "English", "cefr_level": "B1", "lessons": [ { "id": 201, "course_id": 12, "title": "B1 Module 1", "description": "Intermediate conversational patterns", "thumbnail": "https://.../thumb.jpg", "display_order": 1, "level": "B1", "video_count": 3, "practice_count": 2, "videos": [ { "id": 9001, "title": "B1 Intro", "description": "Lesson intro", "video_url": "https://...", "duration": 420, "resolution": "1080p", "display_order": 1 } ], "practices": [ { "id": 4401, "title": "B1 Speaking Practice", "status": "PUBLISHED", "question_count": 10 } ] } ] }, "success": true, "status_code": 200, "metadata": null } ``` ### Validation errors - Invalid CEFR level: - `400` with error message: `Use one of: A1,A2,A3,B1,B2,B3,C1,C2,C3` - Course not in human language category: - `400` with error message indicating invalid human-language course. --- ## 4.2 Create Human Language lesson unit (admin/instructor) ### Request `POST /api/v1/course-management/human-language/lessons` ```json { "course_id": 12, "title": "A2 Module 1", "description": "A2 speaking fundamentals", "thumbnail": "https://...", "display_order": 1, "cefr_level": "A2" } ``` ### Response Returns created lesson metadata with CEFR-normalized level behavior. --- ## 4.3 Update Human Language lesson unit (admin/instructor) ### Request `PATCH /api/v1/course-management/human-language/lessons/{lessonId}` ```json { "title": "A2 Module 1 - Updated", "description": "Updated description", "cefr_level": "A3", "is_active": true } ``` --- ## 5) Recommended Mobile App Integration Flow ## Step 1: Discover courses under Human Language category Use existing endpoints: 1. `GET /course-management/categories` 2. Pick category where name indicates human language. 3. `GET /course-management/categories/:categoryId/courses` ## Step 2: Select CEFR level in UI Use static list in app: - `A1, A2, A3, B1, B2, B3, C1, C2, C3` Do not allow custom levels in mobile UI. ## Step 3: Fetch lessons by selected CEFR level Call: - `GET /course-management/human-language/courses/:courseId/lessons?cefr_level=` Render grouped lessons with nested videos/practices from response. ## Step 4: Navigate to learning/practice screens - Lesson video playback uses returned `videos[]`. - Practice entry uses returned `practices[]` IDs and existing practice-question endpoints. --- ## 6) Mobile UI/UX Recommendations - Use CEFR tabs/segmented control (`A1`...`C3`) at top. - Cache last selected level per course. - Show empty state per level: - "No lessons available for this level yet." - Sort by `display_order` and maintain backend order. - Show badges: - video count - practice count --- ## 7) Error Handling and Resilience - `400` invalid level: reset selection to previous valid CEFR value and show toast/snackbar. - `401/403`: trigger token refresh / re-login flow. - `5xx`: show retry UI with exponential backoff. - If category/course fetch succeeds but level fetch fails, keep course visible and allow manual retry. --- ## 8) Data Model Mapping (Mobile DTO) Suggested DTO for learner app: ```ts type CefrLevel = "A1"|"A2"|"A3"|"B1"|"B2"|"B3"|"C1"|"C2"|"C3"; interface HumanLanguageLessonDTO { id: number; courseId: number; title: string; description?: string; thumbnail?: string; order: number; level: CefrLevel; videoCount: number; practiceCount: number; videos: { id: number; title: string; url: string; duration: number; order: number; }[]; practices: { id: number; title: string; status: string; questionCount: number; }[]; } ``` --- ## 9) Backward Compatibility - Existing non-language content (programming and other categories) continues to use current APIs and hierarchy unchanged. - New Human Language endpoint is additive and isolated. - Mobile app can progressively enable the new flow for language categories only. --- ## 10) QA Checklist for Mobile Team - [ ] Category discovery correctly identifies Human Language category. - [ ] CEFR selector only allows A1..C3. - [ ] Fetch by CEFR level returns only matching lessons. - [ ] Video/practice counts match rendered lists. - [ ] Empty-level state works. - [ ] Unauthorized/session-expired flow works. - [ ] Non-language courses still load via existing app flow. --- ## 11) Example Call Matrix - Load language categories/courses: - `GET /course-management/categories` - `GET /course-management/categories/:id/courses` - Load A1 lessons: - `GET /course-management/human-language/courses/:courseId/lessons?cefr_level=A1` - Load B2 lessons: - `GET /course-management/human-language/courses/:courseId/lessons?cefr_level=B2` --- For backend ownership questions, refer to: - `internal/web_server/handlers/course_management.go` - `internal/web_server/routes.go`