feat: Dynamic student lesson discovery, lesson selector carousel, and live Socratic checkpoint streaming

This commit is contained in:
Hamza-Ayed
2026-08-28 04:08:04 +03:00
parent ab52d44c94
commit dc2ebb108c
3 changed files with 158 additions and 32 deletions
+43 -7
View File
@@ -297,6 +297,35 @@ class VideoController
]);
}
/**
* List all published lessons for student portal
* GET /api/student/lessons
*/
public function getStudentLessons(Request $request, Response $response): void
{
VideoService::ensureSchema();
CurriculumService::ensureSchema();
$courseId = (int)($request->getQuery('course_id') ?: 0);
$where = $courseId > 0 ? "WHERE l.course_id = {$courseId}" : "";
$lessons = Database::select(
"SELECT l.id, l.course_id, l.title, l.sequence_order, l.storage_type, l.video_uuid, l.hls_url, l.thumbnail_url,
l.duration_seconds, l.is_free_preview, l.created_at,
c.title as course_title,
(SELECT COUNT(*) FROM exams WHERE lesson_id = l.id AND scope = 'in_video_checkpoint') as checkpoints_count
FROM lessons l
JOIN courses c ON l.course_id = c.id
{$where}
ORDER BY l.id DESC"
);
$response->json([
'status' => 'success',
'data' => $lessons
]);
}
/**
* Get Lesson Playback Data with Chapters Roadmap and Socratic Checkpoints
* GET /api/lessons/{id}/playback
@@ -307,16 +336,23 @@ class VideoController
CurriculumService::ensureSchema();
$lessonId = (int)$request->getParam('id');
if (!$lessonId) {
$response->status(400)->json(['status' => 'error', 'message' => 'معرف الدرس مطلوب']);
$lesson = null;
if ($lessonId > 0) {
$lesson = Database::selectOne("SELECT * FROM lessons WHERE id = ? LIMIT 1", [$lessonId]);
}
if (!$lesson) {
// Fallback to latest available lesson
$lesson = Database::selectOne("SELECT * FROM lessons ORDER BY id DESC LIMIT 1");
}
if (!$lesson) {
$response->status(404)->json(['status' => 'error', 'message' => 'لا توجد دروس متاحة حالياً']);
return;
}
$lesson = Database::selectOne("SELECT * FROM lessons WHERE id = ? LIMIT 1", [$lessonId]);
if (!$lesson) {
$response->status(404)->json(['status' => 'error', 'message' => 'الدرس غير موجود']);
return;
}
$lessonId = (int)$lesson['id'];
// If lesson has no checkpoints yet, generate them autonomously
$existingCount = Database::selectOne("SELECT COUNT(*) as cnt FROM exams WHERE lesson_id = ? AND scope = 'in_video_checkpoint'", [$lessonId]);