feat: Implement video play count tracking, refactor user update API, add missing CMS delete functions, and update database transaction handling.
This commit is contained in:
@@ -159,6 +159,33 @@ export default function LessonPlayerPage({ params }: { params: { id: string, les
|
||||
media_type={block.media_type || 'video'}
|
||||
config={block.config}
|
||||
onTimeUpdate={setCurrentTime}
|
||||
initialPlayCount={
|
||||
userGrade?.metadata?.play_counts
|
||||
? (userGrade.metadata.play_counts as Record<string, number>)[block.id] || 0
|
||||
: 0
|
||||
}
|
||||
onPlay={async () => {
|
||||
if (user && lesson.max_attempts && (!userGrade || userGrade.attempts_count < lesson.max_attempts)) {
|
||||
const currentPlayCounts = (userGrade?.metadata?.play_counts as Record<string, number>) || {};
|
||||
const newPlayCounts = {
|
||||
...currentPlayCounts,
|
||||
[block.id]: (currentPlayCounts[block.id] || 0) + 1
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await lmsApi.submitScore(
|
||||
user.id,
|
||||
params.id,
|
||||
params.lessonId,
|
||||
userGrade?.score || 0,
|
||||
{ ...userGrade?.metadata, play_counts: newPlayCounts }
|
||||
);
|
||||
setUserGrade(res);
|
||||
} catch (err) {
|
||||
console.error("Failed to persist play count", err);
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{block.type === 'quiz' && (
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useAuth } from "@/context/AuthContext";
|
||||
import { lmsApi } from "@/lib/api";
|
||||
import { User, Save, Shield, Mail, User as UserIcon, Building, Trophy, Flame } from "lucide-react";
|
||||
import { Save, Shield, Mail, User as UserIcon, Building, Trophy, Flame } from "lucide-react";
|
||||
|
||||
export default function ProfilePage() {
|
||||
const { user, logout } = useAuth();
|
||||
|
||||
@@ -11,11 +11,13 @@ interface MediaPlayerProps {
|
||||
config?: {
|
||||
maxPlays?: number;
|
||||
};
|
||||
initialPlayCount?: number;
|
||||
onTimeUpdate?: (time: number) => void;
|
||||
onPlay?: () => void;
|
||||
}
|
||||
|
||||
export default function MediaPlayer({ id, title, url, media_type, config, onTimeUpdate }: MediaPlayerProps) {
|
||||
const [playCount, setPlayCount] = useState(0);
|
||||
export default function MediaPlayer({ id, title, url, media_type, config, initialPlayCount, onTimeUpdate, onPlay }: MediaPlayerProps) {
|
||||
const [playCount, setPlayCount] = useState(initialPlayCount || 0);
|
||||
const [hasStarted, setHasStarted] = useState(false);
|
||||
const [locked, setLocked] = useState(false);
|
||||
|
||||
@@ -44,6 +46,7 @@ export default function MediaPlayer({ id, title, url, media_type, config, onTime
|
||||
if (!hasStarted) {
|
||||
setPlayCount(prev => prev + 1);
|
||||
setHasStarted(true);
|
||||
if (onPlay) onPlay();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -190,10 +190,10 @@ export const lmsApi = {
|
||||
return apiFetch(`/enrollments/${userId}`);
|
||||
},
|
||||
|
||||
async submitScore(userId: string, courseId: string, lessonId: string, score: number): Promise<UserGrade> {
|
||||
async submitScore(userId: string, course_id: string, lessonId: string, score: number, metadata: Record<string, unknown> = {}): Promise<UserGrade> {
|
||||
return apiFetch('/grades', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ user_id: userId, course_id: courseId, lesson_id: lessonId, score })
|
||||
body: JSON.stringify({ user_id: userId, course_id, lesson_id: lessonId, score, metadata })
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user