Complete Example
import { useState, useEffect } from "react";
import {
TeachariumPlayer,
type TeachariumLessonExport,
type SessionState,
type CompletionResult,
} from "@teacharium/player";
import { getWidgets } from "@teacharium/widget";
// Media resolution
const mediaFiles: Record<string, string> = {
"media:intro-image": "/lessons/intro/images/intro.png",
};
function useMediaUrl(mediaId: string | undefined) {
if (!mediaId) return { data: null };
return { data: mediaFiles[mediaId] ?? null };
}
function useVoiceoverUrl(
contentHash: string | undefined,
voice: string | undefined,
) {
if (!contentHash || !voice) return { data: null };
return { data: `/lessons/intro/audio/${contentHash}.mp3` };
}
export function LessonPage({
lessonData,
}: {
lessonData: TeachariumLessonExport;
}) {
const [initialSession, setInitialSession] = useState<
SessionState | undefined
>();
const [isReviewMode, setIsReviewMode] = useState(false);
// Load saved session on mount
useEffect(() => {
const saved = localStorage.getItem(`session-${lessonData.lesson.id}`);
if (saved) {
const session = JSON.parse(saved) as SessionState;
setInitialSession(session);
setIsReviewMode(session.progress.status === "completed");
}
}, [lessonData.lesson.id]);
// Save session state at step boundaries
const handleStepChange = (state: SessionState) => {
localStorage.setItem(
`session-${lessonData.lesson.id}`,
JSON.stringify(state),
);
};
// Handle completion
const handleComplete = (result: CompletionResult) => {
localStorage.setItem(
`session-${lessonData.lesson.id}`,
JSON.stringify(result.sessionState),
);
console.log("Lesson completed!", {
score: result.score,
maxScore: result.maxScore,
variables: result.finalVariables,
});
};
return (
<div className="h-screen">
<TeachariumPlayer
lesson={lessonData}
widgets={getWidgets()}
mediaResolvers={{ useMediaUrl, useVoiceoverUrl }}
initialSessionState={initialSession}
mode={isReviewMode ? "review" : "player"}
onStepChange={isReviewMode ? undefined : handleStepChange}
onComplete={handleComplete}
config={{
showProgress: true,
allowPreviousStep: true,
}}
showStartButton={true}
startButtonText="Begin Lesson"
/>
</div>
);
}