🌱 Mầm Văn — Sơ đồ toàn bộ luồng đã làm
Mỗi nút ghi kèm file code + hàm (dòng nhỏ) · Kéo / chụm 2 ngón: di chuyển & phóng to · Bấm vào 1 nút: mọi thứ liên quan sẽ sáng lên · Bấm ra khoảng trống: bỏ chọn
Giáo viên
Học sinh
Tổng quan
+ To
- Nhỏ
Ẩn đường quan hệ
xuất bản → báo bài mới bài nộp vào hàng đợi chấm AI tạo → nháp chờ duyệt duyệt xong mới vào kho lấy câu hỏi từ kho huấn luyện gợi ý chấm điểm chốt → kết quả của HS yêu cầu → hàng đợi GV duyệt từ chối → hoàn XP vào ví cấp XP cho các bước cấp XP cho các bước cùng một hàm tính năng lực dữ liệu nền cho phân tích GV/Admin xem thử như HS Admin đóng vai GV tạo bài liên kết điểm danh tính vào mốc mở rương mở chi tiết để xử lý mở Studio từ Ngân hàng ôn từ mục Cần ôn lại hiển thị % năng lực cho HS 1. GIÁO VIÊN 📁 screens/TeacherPortal.tsx ƒ TeacherPortal · TeacherSidebar · TeacherTopbar 1.1 Tổng quan 📁 screens/teacher/TeacherOverviewScreen.tsx 📁 analytics/metricsEngine.ts ƒ TeacherOverviewScreen · computeOverviewMetrics Chỉ tính học sinh thuộc lớp của GV đang đăng nhập (chốt phạm vi — hết lẫn học sinh lớp khác) 📁 screens/teacher/TeacherOverviewScreen.tsx 📁 analytics/filterUtils.ts 📁 analytics/metricsEngine.ts ƒ filterStudents · computeOverviewMetrics Thẻ chỉ số tổng quan lớp (computeOverviewMetrics) 📁 analytics/metricsEngine.ts 📁 screens/teacher/TeacherOverviewScreen.tsx ƒ computeOverviewMetrics Thời gian học tích cực theo ngày: tổng phút cả lớp + số học sinh tham gia từng ngày 📁 analytics/engagementAnalytics.ts 📁 screens/teacher/TeacherOverviewScreen.tsx ƒ computeDailyALT Phân bổ Mastery theo 4 mức (%): Vững / Đang tiến bộ / Cần ôn lại / Chưa đủ dữ liệu 📁 analytics/masteryAnalytics.ts 📁 logic/mastery.ts ƒ computeMasteryDistribution · calculateAllMastery Tiến độ hoàn thành theo chủ đề: tỉ lệ học sinh đã hoàn thành các bước học 📁 analytics/engagementAnalytics.ts ƒ computeTopicProgressList Học sinh cần quan tâm (detectStudentsNeedingAttention) — hiện đúng TÊN lớp, không in mã UUID 📁 analytics/metricsEngine.ts ƒ detectStudentsNeedingAttention Gợi ý sư phạm tự động (generatePedagogicalInsights) 📁 analytics/metricsEngine.ts ƒ generatePedagogicalInsights Mọi số liệu tính từ dữ liệu thật — đã gỡ toàn bộ số bịa thời demo 📁 analytics/metricsEngine.ts 📁 analytics/engagementAnalytics.ts 📁 analytics/masteryAnalytics.ts 1.2 Lớp & học sinh 📁 screens/teacher/ClassesAndStudentsScreen.tsx ƒ ClassesAndStudentsScreen Tạo lớp mới (cảnh báo trùng tên + năm học) 📁 screens/teacher/ClassesAndStudentsScreen.tsx 📁 services/index.ts ƒ handleCreateClass · classService Thẻ lớp: sĩ số, hoạt động 7 ngày, nút Vào lớp 📁 screens/teacher/ClassesAndStudentsScreen.tsx ƒ ClassesAndStudentsScreen Lưu trữ lớp — lớp đã lưu trữ không còn xuất hiện trong các ô chọn 📁 screens/teacher/ClassesAndStudentsScreen.tsx 📁 services/mock/mockRepositories.ts ƒ handleUpdateClass · MockClassRepository Tìm lớp theo tên 📁 screens/teacher/ClassesAndStudentsScreen.tsx ƒ ClassesAndStudentsScreen Vào lớp → bảng học sinh của lớp 📁 screens/teacher/ClassesAndStudentsScreen.tsx 📁 components/teacher/AddStudentModal.tsx ƒ ClassesAndStudentsScreen · AddStudentModal Thêm học sinh thủ công: họ tên + lớp 📁 components/teacher/AddStudentModal.tsx ƒ handleSubmitManual · handleAddManualRow Tên đăng nhập TỰ SINH xác định (số nhỏ nhất chưa dùng) — hết cảnh trùng tên phải tự sửa 📁 services/mock/credentialUtils.ts ƒ generateUsername · removeVietnameseTones Mã HS TỰ SINH (HS0001, HS0002… số trống nhỏ nhất); để trống là hệ thống tự cấp 📁 services/mock/credentialUtils.ts ƒ generateStudentCode Không còn trường Ngày sinh 📁 components/teacher/AddStudentModal.tsx 📁 screens/teacher/ClassesAndStudentsScreen.tsx Nhập học sinh bằng Excel: xem trước; lỗi thì báo rõ thay vì bảng trống im lặng 📁 components/teacher/AddStudentModal.tsx 📁 utils/excelUtils.ts ƒ handleSubmitExcel · handleFileSelected downloadStudentTemplateExcel Đặt lại mật khẩu: GV TỰ ĐẶT mật khẩu mới (tối thiểu 6 ký tự) hoặc để trống để hệ thống sinh ngẫu nhiên 📁 screens/teacher/ClassesAndStudentsScreen.tsx 📁 services/mock/credentialUtils.ts ƒ handleResetPassword · generateFriendlyPassword Xóa học sinh — đọc lỗi DB thì báo thật, không báo thành công giả 📁 screens/teacher/ClassesAndStudentsScreen.tsx ƒ handleDeleteStudent Đã bỏ mục 'Danh sách học sinh' toàn cục — quản lý học sinh nằm trong từng lớp 📁 components/teacher/TeacherSidebar.tsx 📁 screens/teacher/ClassesAndStudentsScreen.tsx ƒ TeacherSidebar 1.3 Nội dung học 📁 screens/teacher/TeacherContentScreen.tsx ƒ TeacherContentScreen Cây chủ đề (khung trái) 📁 components/teacher/content/TopicTreeSidebar.tsx ƒ TopicTreeSidebar Chủ đề: tạo / sửa / xóa — hộp thoại xác nhận giữa màn hình, cảnh báo số bài liên quan 📁 components/teacher/content/TopicModal.tsx 📁 screens/teacher/TeacherContentScreen.tsx 📁 components/teacher/ui/ConfirmDialog.tsx ƒ TopicModal · handleSubmit · handleDeleteTopic confirmDeleteTopic · ConfirmDialog Màu nhận diện nhuộm cả thẻ + viền; tiêu đề 16px; nhãn trạng thái rút gọn không xuống dòng ('Có sửa chưa đăng') 📁 components/teacher/content/TopicTreeSidebar.tsx 📁 components/teacher/content/StatusBadge.tsx ƒ TopicTreeSidebar · StatusBadge Kéo–thả sắp xếp thứ tự chủ đề, lưu ngay 📁 components/teacher/content/TopicTreeSidebar.tsx 📁 screens/teacher/TeacherContentScreen.tsx ƒ handleTopicDrop · handleReorderTopics Tạo chủ đề mới xong: tự chọn chủ đề + tự tạo nháp 'Bài giảng Video mới' + mở ngay trình soạn video 📁 screens/teacher/TeacherContentScreen.tsx ƒ handleSaveTopic · createVideoDraftInTopic Mỗi chủ đề chứa: Video / Lý thuyết / Bài luyện tập / Bài kiểm tra / Bài tập về nhà 📁 components/teacher/content/TopicTreeSidebar.tsx ƒ TopicTreeSidebar Nút '+ Tạo mới' (5 loại × tạo thủ công hoặc Tạo với AI) và nút 'Thêm vào chủ đề' ở trang chi tiết chủ đề 📁 screens/teacher/TeacherContentScreen.tsx ƒ handleCreateNewManual · handleOpenAiModal Trình soạn Video 📁 components/teacher/content/VideoLessonEditor.tsx ƒ VideoLessonEditor · handleSaveDraft Nguồn video: tải lên / liên kết; thời lượng 📁 components/teacher/content/VideoLessonEditor.tsx 📁 services/supabase/storage.ts ƒ handleFileSelect · LESSON_MEDIA_BUCKET Các ý trọng tâm (điểm tóm tắt) + tiểu mục 📁 components/teacher/content/VideoLessonEditor.tsx ƒ handleAddPoint · handleUpdatePoint handleDeletePoint · handleMovePoint Gắn 3 bài liên kết: Luyện tập / Kiểm tra nhanh / Mastery Check — tạo mới ngay trong trình soạn, ID được ghi ngược vào bài gốc 📁 screens/teacher/TeacherContentScreen.tsx 📁 components/teacher/content/VideoLessonEditor.tsx ƒ handleCreateLinkedQuiz Quay lại về trang chủ đề · Xem trước như học sinh · Lưu nháp · Cập nhật lên web học sinh (xuất bản) 📁 components/teacher/content/VideoLessonEditor.tsx 📁 components/teacher/content/StudentPreviewModal.tsx ƒ handleSaveDraft · StudentPreviewModal Trình soạn Lý thuyết 📁 components/teacher/content/TheoryLessonEditor.tsx ƒ TheoryLessonEditor · handleSaveDraft Soạn theo khối nội dung (tiêu đề / đoạn văn…); thời gian đọc tối thiểu (giây) 📁 components/teacher/content/TheoryLessonEditor.tsx ƒ handleAddBlock · handleUpdateBlock handleDeleteBlock · handleMoveBlock Gắn bài Luyện tập + bài Kiểm tra lý thuyết 📁 screens/teacher/TeacherContentScreen.tsx 📁 components/teacher/content/TheoryLessonEditor.tsx ƒ handleCreateLinkedQuiz Quay lại / Xem trước / Lưu nháp / Xuất bản 📁 components/teacher/content/TheoryLessonEditor.tsx 📁 components/teacher/content/StudentPreviewModal.tsx ƒ handleSaveDraft · StudentPreviewModal Trình tạo Bài tập (QuizBuilder) 📁 components/teacher/content/QuizBuilder.tsx ƒ QuizBuilder · performSave Loại bài: Luyện tập / Kiểm tra nhanh (7 phút) / Mastery Check (15 phút) / BTVN (+20 XP) / Đọc hiểu / Cuối kỳ 📁 components/teacher/content/QuizBuilder.tsx ƒ QUIZ_KIND_CONFIG · handleKindChange Soạn câu hỏi: lấy từ Ngân hàng hoặc tạo mới 📁 components/teacher/content/QuizBuilder.tsx 📁 components/teacher/content/QuestionBankModal.tsx ƒ handleImportFromBank · handleAddQuestion QuestionBankModal Dọn đáp án khi xóa lựa chọn; chặn xuất bản khi đáp án không còn trong danh sách lựa chọn 📁 components/teacher/content/QuizBuilder.tsx ƒ handleUpdateQuestion · handleDeleteQuestion Nút Quay lại trở về ĐÚNG bài gốc (video/lý thuyết) đã tạo liên kết — không văng về trang chủ đề 📁 screens/teacher/TeacherContentScreen.tsx 📁 components/teacher/content/QuizBuilder.tsx ƒ quizReturnTo · handleCreateLinkedQuiz Xuất bản (PublishModal) 📁 components/teacher/content/PublishModal.tsx ƒ PublishModal · handleConfirm Chọn lớp áp dụng; tùy chọn thông báo học sinh 📁 components/teacher/content/PublishModal.tsx ƒ handleToggleClass · handleConfirm Cảnh báo: video chưa gắn bài luyện tập · bài kiểm tra dưới 3 câu · bài đã có học sinh làm 📁 screens/teacher/TeacherContentScreen.tsx ƒ handleOpenPublishModalForCurrent Xuất bản xong: học sinh đúng lớp nhận thông báo bài mới (xem 2.10) 📁 components/teacher/content/PublishModal.tsx 📁 logic/studentNotifications.ts ƒ handleConfirm · buildStudentNotifications Trạng thái nội dung: Nháp / Đã xuất bản / Có sửa chưa đăng 📁 components/teacher/content/StatusBadge.tsx ƒ StatusBadge 1.4 Ngân hàng câu hỏi 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen Kho ngân hàng: câu hỏi + video + lý thuyết tham chiếu 📁 screens/teacher/TeacherQuestionBankScreen.tsx 📁 services/index.ts ƒ TeacherQuestionBankScreen · quizService 4 dạng câu: Trắc nghiệm 1 đáp án / Chọn nhiều đáp án / Điền vào ô trống / Tự luận (Rubric) 📁 screens/teacher/TeacherQuestionBankScreen.tsx 📁 types.ts ƒ QuestionType Tô sáng đáp án đúng — nhận cả 2 dạng lưu (chữ cái & toàn văn) 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen Đáp án điền khuyết được chuẩn hóa về dạng danh sách (gốc của lỗi không nộp được bài — đã vá) 📁 services/supabase/supabaseRepositories.ts 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ normalizeAnswerForType Bộ lọc dạng DANH SÁCH 3 nhóm, gập/mở được, tiêu đề hiện lựa chọn đang áp dụng 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen 1) Dạng học liệu 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen 2) Năng lực: Nhận biết / Thông hiểu / Phân tích / Vận dụng 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen 3) Độ khó: Dễ / Trung bình / Khó 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ TeacherQuestionBankScreen Thêm câu hỏi thủ công; xóa câu hỏi bằng hộp thoại xác nhận của app 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ handleSaveQuestionForm · handleOpenAddQuestionModal confirmDeleteQuestion Tab Bản nháp (huy hiệu đếm số chờ duyệt) 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ readQuestionDraftSets · readTheoryDrafts QUESTION_DRAFT_PREFIX · THEORY_DRAFT_PREFIX Bộ câu hỏi & lý thuyết do AI tạo mà chưa duyệt đều nằm ở đây 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ readQuestionDraftSets · readTheoryDrafts Mở xem từng câu → tích chọn câu đạt → 'Đưa vào Ngân hàng'; câu chưa chọn ở lại nháp 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ handlePushDraftQuestions handleReviewDraftInStudio Xóa nháp có hỏi xác nhận 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ handleDeleteDraft Nguyên tắc xuyên suốt: chưa duyệt thì chưa vào Ngân hàng 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ readQuestionDraftSets · readTheoryDrafts QUESTION_DRAFT_PREFIX · THEORY_DRAFT_PREFIX 1.5 Mầm AI Studio 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ AiContentStudioModal 3 panel kéo chỉnh độ rộng / thu thành thanh dọc 46px (lưu theo máy) 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ AiContentStudioModal · onMove Panel 1: Nguồn tài liệu 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ AiContentStudioModal · onMove Panel 2: Trò chuyện & tra cứu tài liệu 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ AiContentStudioModal · onMove Panel 3: Xưởng tạo đầu ra 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ AiContentStudioModal · onMove Trợ lý trò chuyện 'Tôi là trợ lý Mầm AI' — tra cứu trên tài liệu đã nạp (RAG) 📁 components/teacher/ai/AiContentStudioModal.tsx 📁 services/ai/AIService.ts ƒ handleSendMessage · FormattedChatMessage · AIService Tạo đầu ra theo CƠ CẤU LOẠI CÂU: 4 dòng số lượng (Chọn 1 / Chọn nhiều / Điền khuyết / Tự luận), nút −/+ từng loại, tổng tự cộng, khóa nút tạo khi tổng = 0 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ handleGenerateDraft Cơ cấu loại câu truyền thẳng vào prompt Gemini — loại để 0 thì không sinh câu loại đó 📁 services/ai/GeminiAIService.ts ƒ GeminiAIService Sinh bằng Gemini (model AI-2.5-flash); khi Gemini lỗi → bản dự phòng MockAI và BÁO RÕ '(Bản dự phòng — Gemini lỗi)', không giả danh AI thật 📁 services/ai/GeminiAIService.ts 📁 services/ai/index.ts 📁 services/ai/MockAIService.ts ƒ GeminiAIService · SmartAIService · getLastAiFallback MockAIService Bộ câu hỏi AI → BẢN NHÁP BỀN: tự lưu (đóng xưởng / chuyển màn / tải lại trang vẫn còn); thanh BẢN NHÁP báo số câu + giờ lưu 📁 components/teacher/ai/AiContentStudioModal.tsx 📁 screens/teacher/TeacherQuestionBankScreen.tsx ƒ handleGenerateDraft · QUESTION_DRAFT_PREFIX readQuestionDraftSets Duyệt → Lưu vào Ngân hàng: chỉ lưu câu đã tích chọn; tiêu đề 'Bộ câu hỏi: <chủ đề>', thời lượng = max(7 phút, số câu), XP = số câu × 5 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ handleSaveReviewedQuestions · handleToggleDraftId handleToggleSelectAllDrafts Lý thuyết AI → màn DUYỆT LÝ THUYẾT xem trước đúng dạng học sinh sẽ đọc → ưng ý mới 'Lưu lý thuyết vào học liệu'; nháp lý thuyết cũng tự lưu bền 📁 components/teacher/ai/AiContentStudioModal.tsx ƒ handleApplyTheoryDraft · handleDiscardTheoryDraft 1.6 Chấm bài 📁 screens/teacher/TeacherGradingScreen.tsx ƒ TeacherGradingScreen Hàng đợi GOM THEO HỌC SINH — mỗi em đúng 1 dòng (khử trùng bài theo nội dung + quy về đúng 1 học sinh thật dù lệch định danh giữa các nguồn) 📁 components/teacher/grading/GradingQueueTable.tsx 📁 screens/teacher/TeacherGradingScreen.tsx ƒ GradingQueueTable Bảng 6 cột theo mẫu: Học sinh | Lớp | Chủ đề đã làm (x/y) | Bài chờ chấm (0 thì làm mờ) | Chờ lâu nhất (đỏ + '(quá hẹn)' khi quá 24 giờ) | Xem chi tiết 📁 components/teacher/grading/GradingQueueTable.tsx 📁 components/teacher/grading/StudentGradingDetail.tsx ƒ GradingQueueTable · waitingHours · formatSubmittedAt 2 thẻ thống kê: 'Cần chấm' (chờ chấm + đã có gợi ý AI, có nút lọc riêng gợi ý AI) · 'Chờ > 24 giờ' (bấm → sắp xếp chờ lâu nhất lên đầu) 📁 screens/teacher/TeacherGradingScreen.tsx 📁 components/teacher/grading/GradingQueueTable.tsx ƒ handleToolbarPick Bộ lọc gộp 1 ô duy nhất: Trạng thái / Sắp xếp 📁 components/teacher/grading/GradingQueueTable.tsx ƒ handleToolbarPick 'Chấm ngay' mở thẳng bài chờ lâu nhất chưa chấm của em 📁 screens/teacher/TeacherGradingScreen.tsx ƒ TeacherGradingScreen Xem chi tiết theo học sinh 📁 components/teacher/grading/StudentGradingDetail.tsx ƒ StudentGradingDetail Thẻ 'Họ tên · Lớp' + thanh tổng kết: x/y bài kiểm tra đã làm, số bài chờ chấm, số bài quá hạn, ĐTB, công tắc 'Chỉ hiện bài chưa chấm' 📁 components/teacher/grading/StudentGradingDetail.tsx ƒ StudentGradingDetail Bài gom theo CHỦ ĐỀ: dòng nhóm '… – bài chờ chấm: N' / '… – (Hoàn thành)' 📁 components/teacher/grading/StudentGradingDetail.tsx ƒ StudentGradingDetail Cột Điểm hiện 'Gợi ý Xđ' cho bài AI đã gợi ý 📁 components/teacher/grading/StudentGradingDetail.tsx 📁 utils/scoreFormat.ts ƒ formatScore Màn chấm bài (SplitGradingWorkspace) 📁 components/teacher/grading/SplitGradingWorkspace.tsx ƒ SplitGradingWorkspace Nội dung bài tự luận + thông tin bài / năng lực / chủ đề 📁 components/teacher/grading/SplitGradingWorkspace.tsx ƒ SplitGradingWorkspace 'Gợi ý chấm tự động bởi AI': điểm gợi ý làm tròn 1 chữ số thập phân; chưa có gợi ý thì không bịa số 📁 components/teacher/grading/SplitGradingWorkspace.tsx 📁 services/ai/AIService.ts ƒ handleAcceptAllAI · handleClearAI AIEssayGradingResult 'Tiêu chí đánh giá & Chấm điểm': chấm theo Rubric từng tiêu chí; gõ số thập phân / xóa trắng bình thường; Rubric không lưu khi tổng trọng số ≠ 100 📁 components/teacher/grading/SplitGradingWorkspace.tsx 📁 components/teacher/content/QuizBuilder.tsx ƒ SplitGradingWorkspace · DEFAULT_ESSAY_RUBRIC Câu nhận xét mẫu nhanh — bấm để chèn 📁 components/teacher/grading/SplitGradingWorkspace.tsx ƒ SplitGradingWorkspace Chốt điểm → ghi đúng chủ đề / năng lực + nhật ký kiểm toán + thông báo cho học sinh (ở cả 2 kho dữ liệu) 📁 components/teacher/grading/SplitGradingWorkspace.tsx 📁 screens/teacher/TeacherGradingScreen.tsx ƒ handleFinalize · handleFinalizeGrading Huấn luyện AI (AiTrainingStudio): rubric + bài mẫu chấm để AI học cách gợi ý điểm 📁 components/teacher/grading/AiTrainingStudio.tsx ƒ AiTrainingStudio · handleSaveConfig · handleRunSandbox handleCloneRubric Bài tự luận không bao giờ bị gán nhầm cho 'học sinh đầu tiên' khi không tra được chủ nhân 📁 screens/teacher/TeacherGradingScreen.tsx 📁 services/supabase/supabaseRepositories.ts ƒ SupabaseEssayRepository 1.7 Quà tặng 📁 screens/teacher/TeacherRewardsScreen.tsx ƒ TeacherRewardsScreen Hàng đợi yêu cầu đổi quà — số liệu thật (XP tuần / điểm danh / tên lớp tính từ state thật) 📁 screens/teacher/TeacherRewardsScreen.tsx 📁 services/index.ts ƒ TeacherRewardsScreen · rewardService Duyệt / Từ chối / Trao / Mở — trạng thái GIVEN/OPENED không bị ghi nhầm thành REJECTED (migration_003) 📁 screens/teacher/TeacherRewardsScreen.tsx 📁 components/teacher/rewards/RejectRewardModal.tsx 📁 database/migration_003_reward_status.sql ƒ handleApprove · handleGive · RejectRewardModal Từ chối → HOÀN đầy đủ XP đã trừ vào TỔNG XP của học sinh (kể cả từ chối hàng loạt) 📁 screens/teacher/TeacherRewardsScreen.tsx 📁 services/mock/mockRepositories.ts 📁 services/supabase/supabaseRepositories.ts ƒ handleConfirmReject · MockRewardRepository SupabaseRewardRepository Duyệt / trao hàng loạt chỉ tính yêu cầu hợp lệ 📁 screens/teacher/TeacherRewardsScreen.tsx ƒ handleBatchApprove · handleBatchGive Xuất CSV theo đúng bộ lọc đang xem 📁 screens/teacher/TeacherRewardsScreen.tsx 📁 utils/exportUtils.ts ƒ handleExportHistoryCSV · exportToCsv Danh mục quà GV tùy biến là nguồn dự phòng; giá XP chuẩn theo danh mục học sinh nhìn thấy 📁 screens/teacher/TeacherRewardsScreen.tsx 📁 components/teacher/rewards/RewardMilestoneModal.tsx 📁 data/rewards.ts ƒ handleSaveMilestone · RewardMilestoneModal REWARDS_CATALOG 1.8 Phân tích 📁 screens/teacher/TeacherAnalyticsScreen.tsx ƒ TeacherAnalyticsScreen metricsEngine: computeOverviewMetrics / detectStudentsNeedingAttention / generatePedagogicalInsights 📁 analytics/metricsEngine.ts ƒ computeOverviewMetrics · detectStudentsNeedingAttention generatePedagogicalInsights Phổ điểm (Histogram): tính theo TỪNG HỌC SINH — điểm TB của mỗi em xếp vào đúng 1 dải; tổng các cột luôn khớp sĩ số thật (đã sửa lỗi đếm theo câu hỏi) 📁 analytics/scoreAnalytics.ts 📁 components/teacher/analytics/ScoreAnalyticsTab.tsx ƒ computeScoreDistribution · ScoreAnalyticsTab Bản đồ nhiệt năng lực (masteryAnalytics) · Tương tác & chuyên cần (engagementAnalytics) · Phân tích câu hỏi (questionAnalytics) · Hồ sơ học sinh (studentProfileAnalytics) 📁 analytics/masteryAnalytics.ts 📁 analytics/engagementAnalytics.ts 📁 analytics/questionAnalytics.ts 📁 analytics/studentProfileAnalytics.ts ƒ computeStudentTopicHeatmap · computeMasteryDistribution computeQuestionAnalytics · computeStudentProfileData Tên lớp tra theo danh sách thật ở cả 3 nơi — không in UUID, không bịa tên lớp 📁 screens/teacher/TeacherAnalyticsScreen.tsx 📁 analytics/filterUtils.ts ƒ filterStudents Toàn bộ biểu đồ tính từ dữ liệu thật (điểm danh, nhật ký XP, kết quả câu hỏi, bước đã học); tuần không có điểm thì để trống — hết số bịa (13/18, 7.5đ, 82%, chuỗi 78→91%…) 📁 analytics/scoreAnalytics.ts 📁 analytics/masteryAnalytics.ts 📁 analytics/engagementAnalytics.ts 📁 analytics/questionAnalytics.ts 1.9 Cài đặt 📁 screens/teacher/TeacherSettingsScreen.tsx ƒ TeacherSettingsScreen Cấu hình ngưỡng XP — kiểm tra thứ tự ngưỡng, chặn giá trị 0 / trống trước khi lưu 📁 screens/teacher/TeacherSettingsScreen.tsx 📁 config.ts ƒ handleSaveSettings · getEffectiveXpConfig · XP_CONFIG Mô hình Mầm AI: chọn model Gemini; cảnh báo API Key đang lưu trong trình duyệt 📁 screens/teacher/TeacherSettingsScreen.tsx 📁 services/ai/index.ts ƒ handleSaveAiConfig · handleTestAiConnection setGeminiApiKey · setGeminiModel Đổi mật khẩu: kiểm tra mật khẩu hiện tại + lưu thật 📁 screens/teacher/TeacherSettingsScreen.tsx ƒ handleChangePassword Cỡ chữ hiển thị (Chuẩn / Lớn 112% / Rất lớn 125%) — phóng toàn cục theo đúng tỉ lệ 📁 screens/teacher/TeacherSettingsScreen.tsx 📁 config.ts ƒ handleSaveSettings · getSavedSystemSettings Đã gỡ khu vực 'Đặt lại dữ liệu demo' khỏi bản khách thật 📁 screens/teacher/TeacherSettingsScreen.tsx 📁 components/DevPanel.tsx ƒ DevPanel 2. HỌC SINH 📁 App.tsx 📁 components/Navbar.tsx ƒ Navbar · NotificationBell 2.1 Trang chủ 📁 screens/HomeScreen.tsx ƒ HomeScreen Lời chào theo hồ sơ thật (đúng tên, đúng lớp) — học sinh mới bắt đầu TRẮNG, không thừa hưởng tiến độ mẫu 📁 screens/HomeScreen.tsx 📁 services/mock/seedData.ts ƒ createFreshStudentState Chủ đề học kỳ này: thẻ cao đều nhau, chân thẻ ghim đáy ('X bài giảng · Vào học') 📁 screens/HomeScreen.tsx 📁 components/VideoCard.tsx ƒ VideoCard · getVideoCardStatus Điểm danh mỗi ngày (+2 XP) 📁 screens/HomeScreen.tsx 📁 App.tsx 📁 logic/xpEngine.ts 📁 config.ts ƒ handleCheckInClick · handleAttendanceCheckIn · awardXP ATTENDANCE_CONFIG Biểu ngữ bài mới nhất chưa đọc + nút 'Vào làm ngay' 📁 logic/studentNotifications.ts 📁 screens/HomeScreen.tsx 📁 App.tsx ƒ buildStudentNotifications · handleOpenNotification Gợi ý bài học tiếp theo 📁 screens/HomeScreen.tsx ƒ HomeScreen Tiến độ năng lượng học tập hôm nay (phút học tích cực / trần XP ngày) 📁 screens/HomeScreen.tsx 📁 logic/useActiveLearningTimer.ts 📁 logic/xpEngine.ts ƒ useActiveLearningTimer · getCurrentDailyXpCap Khu Bài tập về nhà – Bài kiểm tra – Bài luyện tập 📁 screens/HomeScreen.tsx ƒ HomeScreen Cần ôn lại (các chủ đề yếu) 📁 screens/HomeScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery Rương quà bí mật (gợi mở sang mục Đổi quà) 📁 screens/HomeScreen.tsx 📁 components/rewards/RewardTrack.tsx ƒ RewardTrack Xem trước Cây tri thức 📁 screens/HomeScreen.tsx 📁 components/GrowthTree.tsx ƒ GrowthTree 2.2 Học bài 📁 screens/LearnScreen.tsx ƒ LearnScreen Danh sách chủ đề → chọn bài Video hoặc Lý thuyết chi tiết 📁 screens/LearnScreen.tsx 📁 components/VideoCard.tsx ƒ getVideoCardStatus Học dở được khôi phục đúng bước đang học (khóa bước ổn định — không bắt đầu lại từ bước 0) 📁 screens/LearnScreen.tsx 📁 screens/VideoLessonScreen.tsx 📁 logic/studentStateUtils.ts ƒ rolloverStudentState 2.3 Luồng Video — tổng 48 XP 📁 screens/VideoLessonScreen.tsx 📁 config.ts ƒ VideoLessonScreen · TOTAL_VIDEO_XP Bước 1: Xem video đạt 80% → +5 XP 📁 screens/VideoLessonScreen.tsx 📁 logic/xpEngine.ts ƒ handleProceedFromVideo · awardXP Bước 2: Đọc lý thuyết tóm tắt (các ý trọng tâm) → +2 XP 📁 screens/VideoLessonScreen.tsx ƒ handleProceedFromSummary Bước 3: Bài luyện tập → +5 XP 📁 screens/VideoLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteQuizStep · QuizRunner Bước 4: Kiểm tra nhanh → +8 XP 📁 screens/VideoLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteQuizStep · QuizRunner Bước 5: Mastery Check → +8 XP 📁 screens/VideoLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteQuizStep · QuizRunner Bước 6: Hoàn thành toàn luồng → +20 XP 📁 screens/VideoLessonScreen.tsx 📁 config.ts ƒ TOTAL_VIDEO_XP 2.4 Luồng Lý thuyết chi tiết — tổng 41 XP 📁 screens/TheoryLessonScreen.tsx 📁 config.ts ƒ TheoryLessonScreen · XP_CONFIG Bước 1: Đọc hết khối nội dung (đủ thời gian đọc tối thiểu) + xác nhận đã hiểu → +10 XP 📁 screens/TheoryLessonScreen.tsx ƒ handleUnderstood · handleNotUnderstood Bước 2: Bài luyện tập sau lý thuyết → +5 XP 📁 screens/TheoryLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteTheoryQuiz · QuizRunner Bước 3: Bài kiểm tra lý thuyết 1 → +8 XP 📁 screens/TheoryLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteTheoryQuiz · QuizRunner Bước 4: Bài kiểm tra lý thuyết 2 → +8 XP 📁 screens/TheoryLessonScreen.tsx 📁 components/QuizRunner.tsx ƒ handleCompleteTheoryQuiz · QuizRunner Bước 5: Hoàn thành toàn luồng → +10 XP (trước đây bị thiếu — đã cộng đúng như cấu hình hứa) 📁 screens/TheoryLessonScreen.tsx 📁 config.ts ƒ XP_CONFIG 2.5 Làm bài (QuizRunner — dùng chung cho mọi loại bài) 📁 components/QuizRunner.tsx ƒ QuizRunner 4 dạng câu: Chọn 1 đáp án / Chọn nhiều đáp án / Điền vào ô trống / Tự luận 📁 components/QuizRunner.tsx 📁 types.ts ƒ QuizRunner · QuestionType Đồng hồ đếm ngược theo thời lượng bài; HẾT GIỜ TỰ NỘP phần đã làm (đã sửa lỗi nộp bài trống) 📁 components/QuizRunner.tsx ƒ handleSubmitFinal Hộp xác nhận nộp bài: báo số câu chưa trả lời; chống nộp 2 lần 📁 components/QuizRunner.tsx ƒ handleSubmitScoring · handleSubmitFinal Bài có câu điền khuyết không còn chết im lặng khi nộp: đáp án được chuẩn hóa về dạng danh sách; lỗi lạ thì báo rõ + mở lại nút nộp để nộp lại 📁 components/QuizRunner.tsx 📁 services/supabase/supabaseRepositories.ts ƒ normalizeAnswerForType Màn hình KẾT QUẢ sau mỗi quiz: điểm /10, XP THỰC NHẬN, xem lại từng câu với đúng câu hỏi đã làm (kể cả câu do GV/AI tạo) 📁 components/QuizResult.tsx 📁 components/QuizRunner.tsx ƒ QuizResult Câu tự luận → tạo bài nộp mang đúng mã học sinh → vào hàng đợi chấm của giáo viên 📁 components/QuizRunner.tsx 📁 services/index.ts 📁 services/supabase/supabaseRepositories.ts ƒ essayService · SupabaseEssayRepository Bài tập về nhà hoàn thành → +20 XP 📁 components/QuizRunner.tsx 📁 logic/xpEngine.ts 📁 config.ts ƒ awardXP · XP_CONFIG Ôn lại phần yếu: +3 XP khi nâng được điểm (tối đa 1 lần / chủ đề) 📁 components/QuizRunner.tsx 📁 logic/xpEngine.ts ƒ awardXP 2.6 Cây tri thức — Vườn Văn Mầm Mục 📁 screens/TreeScreen.tsx 📁 components/GrowthTree.tsx ƒ TreeScreen · GrowthTree 6 giai đoạn theo số bước học đã hoàn thành 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Hạt mầm (0 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Nảy mầm (3 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Chồi non (8 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Cây con (18 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Cây ra hoa (32 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Cây kết trái (50 bước) 📁 config.ts 📁 components/GrowthTree.tsx ƒ TREE_STAGES_CONFIG · GrowthTree Tưới nước: mỗi bước học tạo 'Nước tưới Mầm Mực' nuôi cây lớn 📁 screens/TreeScreen.tsx 📁 components/GrowthTree.tsx ƒ handleWaterTree · handleLeafPress 15 vị trí lá trên tán cây 📁 components/GrowthTree.tsx ƒ GrowthTree · TopicLeafData 4 lá chính đầu tiên = 4 chủ đề đầu trong thứ tự khóa học (lá to, có nhãn tên) 📁 components/GrowthTree.tsx ƒ GrowthTree · TopicLeafData Từ chủ đề thứ 5: hiện ở 11 'lá ẩn' còn lại (lá nhỏ hơn, rê chuột xem tên + %) 📁 components/GrowthTree.tsx ƒ GrowthTree · TopicLeafData Màu lá: Hoàn thành ≥80% = xanh lá đậm · Đang học 50–79% = xanh biển · Cần ôn lại <50% = vàng · Chưa học = xám (có hàng chú thích) 📁 components/GrowthTree.tsx 📁 logic/mastery.ts ƒ GrowthTree · calculateAllMastery Hiệu ứng NHẤP lá đã hoàn thành: lá lún xuống như bị ấn vào tán cây + vòng sáng lan tỏa 📁 components/GrowthTree.tsx ƒ handleLeafPress Ma trận năng lực: từng chủ đề × 4 năng lực 📁 screens/TreeScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery · calculateLevelMastery Huy hiệu đạt được 📁 screens/TreeScreen.tsx 📁 data/mockData.ts ƒ BADGES_CATALOG 2.7 Kết quả học tập 📁 screens/LearningResultsScreen.tsx ƒ LearningResultsScreen Thẻ tổng quan: Tổng XP tích lũy (+ XP hôm nay) · Huy hiệu đạt được — đã bỏ 2 thẻ 'Câu hỏi đã làm' & 'Điểm trung bình' 📁 screens/LearningResultsScreen.tsx ƒ LearningResultsScreen Điểm theo từng chủ đề 📁 screens/LearningResultsScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery 4 thanh năng lực (%) + điểm trung bình + trạng thái: Đã hoàn thành / Đang học / Cần ôn lại / Chưa học 📁 screens/LearningResultsScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery Khối chủ đề nhuộm nền + viền theo đúng màu của chủ đề đó 📁 screens/LearningResultsScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery Bấm tên chủ đề → tới bài học 📁 screens/LearningResultsScreen.tsx 📁 logic/mastery.ts ƒ calculateAllMastery Dùng chung hàm calculateAllMastery với Cây tri thức — số liệu nhất quán 📁 logic/mastery.ts ƒ calculateAllMastery · calculateLevelMastery Biểu đồ tiến bộ 6 tuần — dạng ĐƯỜNG MỐC TUẦN 📁 screens/LearningResultsScreen.tsx 📁 utils/scoreFormat.ts ƒ LearningResultsScreen · ONE_WEEK · formatScore Mỗi mốc là vòng tròn chứa điểm trung bình của tuần; tuần này to nhất, viền cam nổi bật 📁 screens/LearningResultsScreen.tsx 📁 utils/scoreFormat.ts ƒ LearningResultsScreen · ONE_WEEK · formatScore Tuần chưa học hiện mốc xám 'Chưa học' thay vì biến mất 📁 screens/LearningResultsScreen.tsx 📁 utils/scoreFormat.ts ƒ LearningResultsScreen · ONE_WEEK · formatScore Nhãn tuần dễ hiểu ('Tuần trước', '2 tuần trước'…) + số câu đã làm dưới mỗi mốc 📁 screens/LearningResultsScreen.tsx 📁 utils/scoreFormat.ts ƒ LearningResultsScreen · ONE_WEEK · formatScore Góc phải thẻ: tổng số câu + điểm tuần này 📁 screens/LearningResultsScreen.tsx 📁 utils/scoreFormat.ts ƒ LearningResultsScreen · ONE_WEEK · formatScore Thành tích & huy hiệu: toàn bộ danh mục, phân biệt đã đạt / chưa đạt 📁 screens/LearningResultsScreen.tsx 📁 data/mockData.ts ƒ BADGES_CATALOG 2.8 Đổi quà 📁 screens/RewardsScreen.tsx ƒ RewardsScreen Ví chi tiêu = TỔNG XP của tài khoản (vĩnh viễn — chỉ giảm khi xin quà); MỐC MỞ RƯƠNG xét theo XP TUẦN + số ngày điểm danh (quyết định chốt của chủ dự án) 📁 screens/RewardsScreen.tsx 📁 App.tsx 📁 config.ts ƒ handleRequestReward · CHEST_TIERS · getChestTierConfig Các rương theo cấu hình: Rương Hạt / Rương Lá / Rương Hoa / Rương Vàng 📁 config.ts 📁 components/rewards/ChestCard.tsx 📁 components/rewards/ChestIllustration.tsx ƒ CHEST_TIERS · ChestCard · ChestIllustration Danh mục quà thật (XP / ngày điểm danh yêu cầu) 📁 data/rewards.ts ƒ REWARDS_CATALOG Bookmark Mầm Mực thủ công — 280 XP · 4 ngày 📁 data/rewards.ts ƒ REWARDS_CATALOG Quyền chọn bài đọc cho cả lớp — 320 XP · 4 ngày 📁 data/rewards.ts ƒ REWARDS_CATALOG Bút mực xanh Giấy & Mực — 450 XP · 5 ngày 📁 data/rewards.ts ƒ REWARDS_CATALOG Sổ tay Giấy & Mực bìa cứng — 650 XP · 5 ngày 📁 data/rewards.ts ƒ REWARDS_CATALOG Rương Vàng: Bút mài nét hoa & Bộ quà lưu niệm Mầm Văn — 750 XP · 6 ngày 📁 data/rewards.ts ƒ REWARDS_CATALOG Nội dung quà thuộc loại 'secret' — học sinh không được biết trước bên trong có gì 📁 types.ts 📁 screens/RewardsScreen.tsx ƒ RewardTierSecret Gửi yêu cầu: TRỪ NGAY vào Tổng XP (ghi deductedXp); chặn khi Tổng XP không đủ; chặn gửi trùng khi đang có yêu cầu chưa bị từ chối 📁 App.tsx 📁 screens/RewardsScreen.tsx ƒ handleRequestReward · handleConfirmClaim Trạng thái: Chờ duyệt → Được duyệt → Đã trao → Đã mở 📁 components/rewards/RequestHistory.tsx 📁 components/rewards/ChestOpeningModal.tsx 📁 screens/RewardsScreen.tsx ƒ RequestHistory · ChestOpeningModal · handleOpenChest handleCollect Bị từ chối → HOÀN 100% XP đã trừ vào Tổng XP 📁 App.tsx 📁 services/mock/mockRepositories.ts 📁 services/supabase/supabaseRepositories.ts ƒ MockRewardRepository · SupabaseRewardRepository 2.9 Hồ sơ 📁 screens/ProfileScreen.tsx ƒ ProfileScreen Thông tin tài khoản học sinh 📁 screens/ProfileScreen.tsx ƒ ProfileScreen Thẻ dưới chân thanh điều hướng: TỔNG XP tích lũy là số chính, XP hôm nay ở dòng nhỏ bên dưới 📁 components/Navbar.tsx 📁 screens/ProfileScreen.tsx ƒ Navbar Cỡ chữ hiển thị (phóng toàn cục 112% / 125%) 📁 screens/ProfileScreen.tsx 📁 config.ts ƒ getSavedSystemSettings Đăng xuất — xóa sạch phiên, kể cả phiên đang đóng vai 📁 App.tsx 📁 screens/ProfileScreen.tsx ƒ handleLogout 2.10 Thông báo bài mới 📁 logic/studentNotifications.ts ƒ buildStudentNotifications Chuông thông báo trên thanh điều hướng (máy tính + điện thoại) + huy hiệu đỏ đếm số chưa đọc 📁 components/Navbar.tsx 📁 App.tsx ƒ NotificationBell · handleMarkAllNotificationsRead Danh sách kiểu tin nhắn: loại bài + tiêu đề + chủ đề + thời gian; bấm vào là vào làm bài đó ngay 📁 logic/studentNotifications.ts 📁 components/Navbar.tsx ƒ formatRelativeTime · QUIZ_KIND_LABELS NotificationBell Thông báo suy ra từ mốc xuất bản thật của nội dung: trong vòng 14 ngày, đúng lớp được giao 📁 logic/studentNotifications.ts ƒ buildStudentNotifications · FOURTEEN_DAYS Trạng thái đã đọc lưu THEO TÀI KHOẢN → đồng bộ mọi thiết bị (thay cơ chế cũ chỉ lưu trên máy giáo viên) 📁 logic/studentNotifications.ts 📁 App.tsx ƒ handleMarkAllNotificationsRead 3. ADMIN 📁 screens/admin/AdminPortal.tsx ƒ AdminPortal Quản lý tài khoản giáo viên: danh sách, tạo mới (họ tên, tên đăng nhập, mật khẩu, liên hệ, ghi chú), sửa thông tin 📁 screens/admin/AdminPortal.tsx ƒ CreateTeacherModal · EditTeacherModal · handleSubmit Tạm khóa / Mở khóa tài khoản giáo viên 📁 screens/admin/AdminPortal.tsx ƒ handleToggleLock Xóa tài khoản giáo viên 📁 screens/admin/AdminPortal.tsx ƒ handleConfirmDelete 'Truy cập với tư cách Giáo viên này' — đóng vai GV để hỗ trợ 📁 screens/admin/AdminPortal.tsx 📁 screens/TeacherPortal.tsx ƒ AdminPortal · TeacherPortal Tải lại danh sách · Đăng xuất khỏi Cổng Admin 📁 screens/admin/AdminPortal.tsx ƒ AdminPortal ĐIỂM ĐANG CHỜ QUYẾT ĐỊNH: đăng nhập Admin vẫn là thông tin cứng trong mã nguồn (repo công khai) — phương án vá đã chuẩn bị, chờ chủ dự án duyệt 📁 services/supabase/supabaseRepositories.ts 📁 services/mock/mockRepositories.ts ƒ SupabaseAuthRepository · MockAuthRepository 4. HỆ THỐNG & DỮ LIỆU (dùng chung) 📁 services/index.ts ƒ useLiveQuery 4.1 Đăng nhập & phiên 📁 screens/LoginScreen.tsx ƒ LoginScreen · handleLoginSubmit 3 vai trò: Học sinh / Giáo viên / Admin — đăng nhập bằng tên đăng nhập + mật khẩu thật trong DB 📁 screens/LoginScreen.tsx 📁 types.ts ƒ handleRoleSelect · Role ĐÃ XÓA cửa hậu mật khẩu phổ thông ở cả 2 kho dữ liệu (trước đây mọi tài khoản vào được bằng mật khẩu mặc định, kể cả sau khi chủ tài khoản đã đổi mật khẩu khác) 📁 services/mock/mockRepositories.ts 📁 services/supabase/supabaseRepositories.ts ƒ MockAuthRepository · SupabaseAuthRepository Lỗi đăng nhập báo rõ; không còn gợi ý mật khẩu trong thông báo lỗi 📁 screens/LoginScreen.tsx ƒ handleLoginSubmit 'Xem góc Học sinh' cho GV/Admin: lưu phiên gốc, thanh cảnh báo cố định + nút 'Thoát xem thử' quay về đúng phiên 📁 App.tsx ƒ handleSwitchToStudentView · handleExitStudentPreview Đăng xuất xóa cả phiên đóng vai — hết đường leo quyền trở lại 📁 App.tsx ƒ handleLogout Bộ đếm giờ học tích cực chỉ chạy khi người dùng thật là học sinh 📁 logic/useActiveLearningTimer.ts 📁 App.tsx ƒ useActiveLearningTimer 4.2 Máy XP (xpEngine) 📁 logic/xpEngine.ts ƒ awardXP XP phẳng theo HOÀN THÀNH — không gắn với điểm số (quyết định chốt của chủ dự án) 📁 logic/xpEngine.ts 📁 config.ts ƒ awardXP · XP_CONFIG awardXP lật ngày / tuần theo GIỜ ĐỊA PHƯƠNG: ngày mới từ 00:00 giờ VN (đã sửa lỗi ngày UTC bắt đầu 07:00 khiến điểm danh 2 lần trong một buổi sáng); khóa tuần theo thứ Hai 📁 logic/xpEngine.ts 📁 logic/studentStateUtils.ts ƒ awardXP · getLocalTodayStr · getWeekKey rolloverStudentState Trần XP ngày theo phút học tích cực: dưới 45 phút → tối đa 130 XP · 45–90 phút → 150 XP · quá 90 phút không cộng thêm (vẫn học bình thường) 📁 logic/xpEngine.ts 📁 config.ts ƒ getCurrentDailyXpCap · XP_CONFIG Trần XP tuần: 900 XP — đạt trần hiện thông báo nghỉ ngơi / tiếp tục nuôi Cây 📁 config.ts 📁 logic/xpEngine.ts ƒ XP_CONFIG · getEffectiveXpConfig Tách 'tiến độ học' khỏi 'đã trả XP' (xpAwardedSteps): học lúc chạm trần vẫn ghi tiến độ cho Cây / Năng lực; hôm sau làm lại được trả XP đúng 1 lần — hết mất XP vĩnh viễn, hết lỗi 'từ ngày thứ 2 mọi lần cộng XP đều trả về 0' 📁 logic/studentStateUtils.ts 📁 logic/xpEngine.ts 📁 types.ts ƒ countLearningSteps · xpAwardedSteps · awardXP Thông báo XP hiển thị số THỰC NHẬN, kể cả khi bị trần chặn 📁 logic/xpEngine.ts ƒ XPCalculationResult · awardXP 4.3 Kho dữ liệu 2 lớp 📁 services/supabase/client.ts 📁 services/supabase/supabaseRepositories.ts ƒ supabase · isSupabaseReady Supabase (PostgreSQL) là kho chính — 12 bảng: học sinh, giáo viên, lớp, chủ đề, video, lý thuyết, quiz, câu hỏi, bài nộp tự luận, state học sinh, yêu cầu quà… 📁 services/supabase/client.ts 📁 services/supabase/supabaseRepositories.ts ƒ supabase · SupabaseContentRepository Kho mock (localStorage) làm dự phòng khi mất kết nối: đọc GỘP dữ liệu 2 nơi (bài nộp, học sinh, lớp) để không bao giờ thất lạc dữ liệu 📁 services/mock/mockRepositories.ts 📁 services/supabase/payloadStore.ts ƒ readStorage · writeStorage · bootstrapStorage readLocalList · writeLocalList Cổng chặn ghi state: chỉ lưu sau khi state THẬT của đúng học sinh đã nạp xong — hết lỗi state mẫu (310 XP, huy hiệu sẵn) ghi đè lên DB 📁 services/supabase/supabaseRepositories.ts 📁 logic/studentStateUtils.ts ƒ SupabaseAttemptRepository · rolloverStudentState Học sinh mới bắt đầu TRẮNG với hồ sơ thật (đúng tên + đúng lớp) ở cả 2 nhánh đọc state 📁 services/mock/seedData.ts ƒ createFreshStudentState useLiveQuery + eventBus: đồng bộ tức thời giữa các màn hình theo đúng khóa sự kiện (quiz / content / class…) 📁 services/index.ts 📁 services/mock/eventBus.ts ƒ useLiveQuery · syncEventBus · SyncEventBus Migration chờ chủ dự án chạy trong Supabase SQL Editor: 003 (trạng thái quà GIVEN/OPENED) + 004 (cột payload giữ đủ trường câu hỏi) — app đang chạy chế độ tương thích an toàn trong lúc chờ 📁 database/migration_003_reward_status.sql 📁 database/migration_004_question_payload.sql Đã sao lưu toàn bộ 12 bảng trước khi dọn dữ liệu test: xóa 21 HS test + 15 bài nộp test; giữ lại hs001, 5 giáo viên, 4 lớp, toàn bộ nội dung thật (6 chủ đề, 97 câu hỏi, 33 quiz, 19 video, 6 lý thuyết) 📁 services/supabase/supabaseRepositories.ts 📁 services/mock/mockRepositories.ts 4.4 Giao diện & hiệu năng 📁 components/teacher/ui/ConfirmDialog.tsx ƒ ConfirmDialog Mọi hộp thoại xác nhận dùng ConfirmDialog giữa màn hình (6 chỗ từng dùng hộp thoại mặc định của trình duyệt đã thay hết) 📁 components/teacher/ui/ConfirmDialog.tsx ƒ ConfirmDialog Nút điều hướng tự nhả focus sau khi bấm — hết vòng đen focus bám trên nút menu 📁 components/Navbar.tsx 📁 components/teacher/TeacherSidebar.tsx ƒ Navbar · TeacherSidebar Tải lười (React.lazy): gói JS ban đầu 2,37 MB → ~0,79 MB; phần giáo viên (~1,08 MB) và thư viện biểu đồ (~0,39 MB) chỉ tải khi vào đúng khu vực 📁 App.tsx 📁 screens/TeacherPortal.tsx ƒ LearnScreen · TeacherPortal DevPanel (cộng XP / tự duyệt quà / tự chấm 9.0 / đặt lại dữ liệu demo) CHỈ có ở bản development — đã kiểm chứng bị loại khỏi gói production 📁 components/DevPanel.tsx 📁 App.tsx ƒ DevPanel · handleResetData 5. KHUNG ĐO NĂNG LỰC (từ sơ đồ gốc của chủ dự án — đã có dữ liệu đỡ) 📁 logic/mastery.ts ƒ calculateAllMastery · calculateLevelMastery Mỗi lần làm bài xong, đo được từ học sinh: điểm theo câu / chủ đề, năng lực, độ khó, tỉ lệ đúng, thời gian 📁 components/QuizRunner.tsx 📁 services/index.ts ƒ QuizRunner · attemptService 4 năng lực × dạng đo × độ khó 📁 types.ts 📁 logic/mastery.ts ƒ SkillLevel · Difficulty · SKILL_METADATA Nhận biết → Trắc nghiệm — Dễ 📁 types.ts 📁 logic/mastery.ts ƒ SkillLevel · Difficulty · SKILL_METADATA Thông hiểu → Trắc nghiệm — Trung bình 📁 types.ts 📁 logic/mastery.ts ƒ SkillLevel · Difficulty · SKILL_METADATA Phân tích → Trắc nghiệm — Khó · Tự luận chấm Rubric — Khó 📁 types.ts 📁 logic/mastery.ts ƒ SkillLevel · Difficulty · SKILL_METADATA Vận dụng → Tự luận / viết văn (đoạn 5–7 câu, bài 150–200 chữ) chấm Rubric — Khó 📁 types.ts 📁 logic/mastery.ts ƒ SkillLevel · Difficulty · SKILL_METADATA Biểu thị khách quan: % thành thạo từng năng lực theo chủ đề (calculateLevelMastery / calculateAllMastery) + trạng thái Vững / Đang tiến bộ / Cần ôn lại / Chưa học 📁 logic/mastery.ts ƒ calculateLevelMastery · calculateAllMastery Dữ liệu nền cho phân tích 📁 analytics/engagementAnalytics.ts 📁 analytics/questionAnalytics.ts ƒ computeQuestionAnalytics Đăng nhập & chuyên cần: có thường xuyên vào học không, ai ít đăng nhập (điểm danh + phút học tích cực theo ngày) 📁 analytics/engagementAnalytics.ts ƒ computeWeeklyAttendance · computeDailyALT Năng lực qua bài tập: kết quả từng câu gắn năng lực + độ khó 📁 analytics/questionAnalytics.ts 📁 analytics/scoreAnalytics.ts ƒ computeQuestionAnalytics · computeAvgScoreByTopic Đầu ra đã nối chung 1 hàm tính: Kết quả học tập của học sinh · Ma trận năng lực ở Cây tri thức · Phân tích của giáo viên 📁 logic/mastery.ts 📁 screens/LearningResultsScreen.tsx 📁 screens/TreeScreen.tsx 📁 screens/teacher/TeacherAnalyticsScreen.tsx ƒ calculateAllMastery 6. KIỂM CHỨNG & TRẠNG THÁI DỰ ÁN 📁 docs/CHANGELOG.md 📁 scripts/test_round2_logic.ts Cổng TypeScript trong lệnh build (tsc --noEmit && vite build): 18 lỗi type ban đầu → 0 lỗi 📁 package.json ƒ tsc Test logic tự động scripts/test_round2_logic.ts: 35/35 đạt (XP, lật ngày/tuần, đổi quà trừ TỔNG XP + hoàn khi từ chối, sinh tên đăng nhập / mã HS) 📁 scripts/test_round2_logic.ts Đợt 0–6 + QA vòng 2 + các đợt tinh chỉnh ngày 18/10: đã đẩy nhánh dev (81c8bc1) và deploy production https://mamvan.vercel.app 📁 docs/CHANGELOG.md Đợt bảo mật 21/10 (theo audit): vercel.json thêm header bảo mật production (CSP, X-Frame-Options SAMEORIGIN, CORS thu hẹp về mamvan.vercel.app, nosniff, Referrer-Policy, Permissions-Policy, HSTS) + gỡ email hardcode khỏi TeacherTopbar — commit 1eb682d, đã deploy và kiểm chứng header trực tiếp trên production 📁 vercel.json 📁 components/teacher/TeacherTopbar.tsx ƒ TeacherTopbar Còn treo 📁 docs/CHANGELOG.md Kiểm chứng trực tiếp luồng nộp bài bằng tài khoản hs001 trên production (đang chờ nhập mật khẩu qua thẻ bảo mật) 📁 docs/CHANGELOG.md 📁 scripts/test_round2_logic.ts Chủ dự án tự merge nhánh dev → main 📁 docs/CHANGELOG.md Chạy migration 003 + 004 trong Supabase SQL Editor 📁 database/migration_003_reward_status.sql 📁 database/migration_004_question_payload.sql 📁 docs/CHANGELOG.md Quyết định vá đăng nhập Admin cứng trong mã nguồn 📁 services/supabase/supabaseRepositories.ts 📁 services/mock/mockRepositories.ts 📁 docs/CHANGELOG.md ƒ SupabaseAuthRepository · MockAuthRepository Đổi mật khẩu database — đã thống nhất để sau 📁 docs/CHANGELOG.md