import React, { useCallback, useRef, useState } from 'react'; import Image from 'next/image'; import clsx from 'clsx'; import { FaFileUpload, FaCheckCircle, FaLock, FaTimes } from 'react-icons/fa'; import { capitalize } from 'lodash'; import { Module } from '@/interfaces'; import { toast } from 'react-toastify'; import useExamEditorStore from '@/stores/examEditor'; import { LevelPart, ListeningPart, ReadingPart } from '@/interfaces/exam'; import { defaultSectionSettings } from '@/stores/examEditor/defaults'; import Templates from './Templates'; import { IoInformationCircleOutline } from 'react-icons/io5'; const WordUploader: React.FC<{ module: Module, setNumberOfLevelParts: (parts: number) => void; }> = ({ module, setNumberOfLevelParts }) => { const { currentModule, dispatch } = useExamEditorStore(); const examInputRef = useRef(null); const solutionsInputRef = useRef(null); const [showUploaders, setShowUploaders] = useState(false); const [examFile, setExamFile] = useState(null); const [solutionsFile, setSolutionsFile] = useState(null); const [templateState, setTemplateState] = useState<{ isOpen: boolean, type: "exam" | "solutions" }>({ isOpen: false, type: "exam" }); const handleExamChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { if (file.type === 'application/msword' || file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { setExamFile(file); } } }; const handleSolutionsChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { if (file.type === 'application/msword' || file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { setSolutionsFile(file); } } }; const handleImport = useCallback(async () => { try { if (!examFile) { toast.error('Exam file is required'); return; } dispatch({ type: "UPDATE_MODULE", payload: { updates: { importing: true }, module } }) const formData = new FormData(); formData.append('exercises', examFile); if (solutionsFile) { formData.append('solutions', solutionsFile); } const response = await fetch(`/api/exam/${module}/import/`, { method: 'POST', body: formData, }); if (!response.ok) { toast.error(`An unknown error has occured while import ${module} exam!`); return; } const data = await response.json(); toast.success(`${capitalize(module)} exam imported successfully!`); setExamFile(null); setSolutionsFile(null); setShowUploaders(false); const newSectionsStates = data.parts.map( (part: ReadingPart | ListeningPart | LevelPart, index: number) => defaultSectionSettings(module, index + 1, part) ); if (module === "level") { setNumberOfLevelParts(data.parts.length); } dispatch({ type: "UPDATE_MODULE", payload: { updates: { sections: newSectionsStates, minTimer: data.minTimer, importModule: false, importing: false, }, module } }); } catch (error) { toast.error(`Make sure you've imported a valid word document (.docx)!`); } finally { dispatch({ type: "UPDATE_MODULE", payload: { updates: { importing: false }, module } }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ examFile, solutionsFile, dispatch, currentModule ]); return ( <> {!showUploaders ? (
setShowUploaders(true)} className="flex flex-col items-center gap-6 h-full justify-center p-8 border-2 border-blue-200 rounded-xl bg-gradient-to-b from-blue-50 to-blue-100 hover:from-blue-100 hover:to-blue-200 cursor-pointer transition-all duration-300 shadow-sm hover:shadow-md group" >
Upload Word
Upload {capitalize(module)} Exam
) : (
examInputRef.current?.click()} className={clsx( "relative p-6 border-2 border-dashed rounded-lg cursor-pointer transition-all duration-300", examFile ? "border-green-300 bg-green-50" : "border-gray-300 hover:border-blue-400 hover:bg-blue-50" )} >

Exam Document

Required

{examFile ? (
) : ( )}
{examFile && (
{examFile.name}
)}
solutionsInputRef.current?.click()} className={clsx( "relative p-6 border-2 border-dashed rounded-lg cursor-pointer transition-all duration-300", solutionsFile ? "border-green-300 bg-green-50" : "border-gray-300 hover:border-blue-400 hover:bg-blue-50" )} >

Solutions Document

Optional

{solutionsFile ? (
) : ( <> OPTIONAL )}
{solutionsFile && (
{solutionsFile.name}
)}
)} ); }; export default WordUploader;