Reverted Level to only utas placement test exercises, Speaking, bug fixes, placeholder

This commit is contained in:
Carlos-Mesquita
2024-11-10 04:24:23 +00:00
parent c507eae507
commit 322d7905c3
39 changed files with 1251 additions and 279 deletions

View File

@@ -10,6 +10,8 @@ import useSectionEdit from "../../Hooks/useSectionEdit";
import useExamEditorStore from "@/stores/examEditor";
import { InteractiveSpeakingExercise } from "@/interfaces/exam";
import { BsFileText } from "react-icons/bs";
import { FaChevronLeft, FaChevronRight } from "react-icons/fa6";
import { RiVideoLine } from "react-icons/ri";
interface Props {
sectionId: number;
@@ -20,6 +22,8 @@ const InteractiveSpeaking: React.FC<Props> = ({ sectionId, exercise }) => {
const { currentModule, dispatch } = useExamEditorStore();
const [local, setLocal] = useState(exercise);
const [currentVideoIndex, setCurrentVideoIndex] = useState(0);
const { generating, genResult } = useExamEditorStore(
(state) => state.modules[currentModule].sections.find((section) => section.sectionId === sectionId)!
);
@@ -86,6 +90,42 @@ const InteractiveSpeaking: React.FC<Props> = ({ sectionId, exercise }) => {
const isUnedited = local.prompts.length === 0;
useEffect(() => {
if (genResult && generating === "media") {
setLocal({ ...local, prompts: genResult[0].prompts });
dispatch({ type: "UPDATE_SECTION_STATE", payload: { sectionId, update: { ...local, prompts: genResult[0].prompts } } });
dispatch({
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "generating",
value: undefined
}
});
dispatch({
type: "UPDATE_SECTION_SINGLE_FIELD",
payload: {
sectionId,
module: currentModule,
field: "genResult",
value: undefined
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [genResult, generating]);
const handlePrevVideo = () => {
setCurrentVideoIndex((prev) => (prev > 0 ? prev - 1 : prev));
};
const handleNextVideo = () => {
setCurrentVideoIndex((prev) =>
(prev < local.prompts.length - 1 ? prev + 1 : prev)
);
};
return (
<>
<div className='relative pb-4'>
@@ -100,12 +140,65 @@ const InteractiveSpeaking: React.FC<Props> = ({ sectionId, exercise }) => {
module="speaking"
/>
</div>
{generating ? (
{generating && generating === "context" ? (
<GenLoader module={currentModule} />
) : (
<>
{editing ? (
<>
{local.prompts.every((p) => p.video_url !== "") && (
<Card>
<CardContent className="pt-6">
<div className="flex flex-col items-start gap-3">
<div className="flex flex-row mb-3 gap-4 w-full justify-between items-center">
<div className="flex flex-row gap-4">
<RiVideoLine className="h-5 w-5 text-amber-500 mt-1" />
<h3 className="font-semibold text-xl">Videos</h3>
</div>
<div className="flex items-center gap-4">
<button
onClick={handlePrevVideo}
disabled={currentVideoIndex === 0}
className={`p-2 rounded-full ${currentVideoIndex === 0
? 'text-gray-400 cursor-not-allowed'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
<FaChevronLeft className="w-4 h-4" />
</button>
<span className="text-sm text-gray-600">
{currentVideoIndex + 1} / {local.prompts.length}
</span>
<button
onClick={handleNextVideo}
disabled={currentVideoIndex === local.prompts.length - 1}
className={`p-2 rounded-full ${currentVideoIndex === local.prompts.length - 1
? 'text-gray-400 cursor-not-allowed'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
<FaChevronRight className="w-4 h-4" />
</button>
</div>
</div>
<div className="flex flex-col gap-4 w-full items-center">
<div className="w-full">
<video
key={local.prompts[currentVideoIndex].video_url}
controls
className="w-full rounded-xl"
>
<source src={local.prompts[currentVideoIndex].video_url} />
</video>
</div>
</div>
</div>
</CardContent>
</Card>
)}
{generating && generating === "media" &&
<GenLoader module={currentModule} custom="Generating the videos ... This may take a while ..." />
}
<Card>
<CardContent>
<div className="flex flex-col py-2 mt-2">