feat: Improve QuizBlockComponent UI and interaction with responsive design and enhanced user experience

This commit is contained in:
swve 2025-02-26 11:50:05 +01:00
parent 5dd9d5d749
commit 2175534e8f

View file

@ -50,6 +50,7 @@ function QuizBlockComponent(props: any) {
const refreshUserSubmission = () => { const refreshUserSubmission = () => {
setUserAnswers([]) setUserAnswers([])
setSubmitted(false) setSubmitted(false)
setSubmissionMessage('')
} }
const handleUserSubmission = () => { const handleUserSubmission = () => {
@ -124,7 +125,7 @@ function QuizBlockComponent(props: any) {
correct: false, correct: false,
} }
// check if there is already more thqn 5 answers // check if there is already more than 5 answers
const question: any = questions.find( const question: any = questions.find(
(question: Question) => question.question_id === question_id (question: Question) => question.question_id === question_id
) )
@ -206,11 +207,11 @@ function QuizBlockComponent(props: any) {
return ( return (
<NodeViewWrapper className="block-quiz"> <NodeViewWrapper className="block-quiz">
<div <div
//style={{ background: "radial-gradient(152.15% 150.08% at 56.45% -6.67%, rgba(180, 255, 250, 0.10) 5.53%, rgba(202, 201, 255, 0.10) 66.76%)" }} className="rounded-xl px-3 sm:px-5 py-2 bg-slate-100 transition-all ease-linear"
className="rounded-xl px-5 py-2 bg-slate-100 transition-all ease-linear"
> >
<div className="flex space-x-2 pt-1 items-center text-sm overflow-hidden"> {/* Header section */}
{submitted && submissionMessage == 'All answers are correct!' && ( <div className="flex flex-wrap gap-2 pt-1 items-center text-sm">
{submitted && submissionMessage === 'All answers are correct!' && (
<ReactConfetti <ReactConfetti
numberOfPieces={submitted ? 1400 : 0} numberOfPieces={submitted ? 1400 : 0}
recycle={false} recycle={false}
@ -223,7 +224,21 @@ function QuizBlockComponent(props: any) {
Quiz Quiz
</p> </p>
</div> </div>
<div className="grow flex items-center justify-center"></div>
{/* Submission message */}
{submitted && (
<div className={`text-xs font-medium px-2 py-1 rounded-md ${
submissionMessage === 'All answers are correct!'
? 'bg-lime-100 text-lime-700'
: 'bg-red-100 text-red-700'
}`}>
{submissionMessage}
</div>
)}
<div className="grow"></div>
{/* Action buttons */}
{isEditable ? ( {isEditable ? (
<div> <div>
<button <button
@ -237,10 +252,11 @@ function QuizBlockComponent(props: any) {
<div className="flex space-x-1 items-center"> <div className="flex space-x-1 items-center">
<div <div
onClick={() => refreshUserSubmission()} onClick={() => refreshUserSubmission()}
className="cursor-pointer px-2" className="cursor-pointer p-1.5 rounded-md hover:bg-slate-200"
title="Reset answers"
> >
<RefreshCcw <RefreshCcw
className="text-slate-400 cursor-pointer" className="text-slate-500"
size={15} size={15}
/> />
</div> </div>
@ -254,8 +270,9 @@ function QuizBlockComponent(props: any) {
)} )}
</div> </div>
{/* Questions section */}
{questions.map((question: Question) => ( {questions.map((question: Question) => (
<div key={question.question_id} className="pt-1 space-y-2"> <div key={question.question_id} className="pt-3 space-y-2">
<div className="question"> <div className="question">
<div className="flex space-x-2 items-center"> <div className="flex space-x-2 items-center">
<div className="flex-grow"> <div className="flex-grow">
@ -269,10 +286,10 @@ function QuizBlockComponent(props: any) {
e.target.value e.target.value
) )
} }
className="text-slate-800 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-md font-bold w-full" className="text-slate-800 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-md font-bold w-full p-2"
></input> ></input>
) : ( ) : (
<p className="text-slate-800 bg-[#00008b00] rounded-md text-md font-bold w-full"> <p className="text-slate-800 bg-[#00008b00] rounded-md text-md font-bold w-full p-2 break-words">
{question.question} {question.question}
</p> </p>
)} )}
@ -280,25 +297,27 @@ function QuizBlockComponent(props: any) {
{isEditable && ( {isEditable && (
<div <div
onClick={() => deleteQuestion(question.question_id)} onClick={() => deleteQuestion(question.question_id)}
className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer" className="w-[24px] flex-none flex items-center h-[24px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer"
> >
<Minus className="mx-auto text-slate-400" size={12} /> <Minus className="mx-auto text-slate-500" size={14} />
</div> </div>
)} )}
</div> </div>
<div className="answers flex py-2 space-x-3">
{/* Answers section - changed to vertical layout for better responsiveness */}
<div className="answers flex flex-col py-2 space-y-2">
{question.answers.map((answer: Answer) => ( {question.answers.map((answer: Answer) => (
<div <div
key={answer.answer_id} key={answer.answer_id}
className={twMerge( className={twMerge(
'outline outline-3 pr-2 shadow w-full flex items-center space-x-2 h-[30px] bg-opacity-50 hover:bg-opacity-100 hover:shadow-md rounded-s rounded-lg bg-white text-sm duration-150 cursor-pointer ease-linear', 'outline outline-2 pr-2 shadow w-full flex items-stretch space-x-2 min-h-[36px] bg-opacity-50 hover:bg-opacity-100 hover:shadow-md rounded-lg bg-white text-sm duration-150 cursor-pointer ease-linear',
answer.correct && isEditable ? 'outline-lime-300' : 'outline-white', answer.correct && isEditable ? 'outline-lime-300' : 'outline-white',
userAnswers.some( userAnswers.some(
(userAnswer: any) => (userAnswer: any) =>
userAnswer.question_id === question.question_id && userAnswer.question_id === question.question_id &&
userAnswer.answer_id === answer.answer_id && userAnswer.answer_id === answer.answer_id &&
!isEditable !isEditable && !submitted
) ? 'outline-slate-300' : '', ) ? 'outline-blue-400' : '',
submitted && answer.correct ? 'outline-lime-300 text-lime' : '', submitted && answer.correct ? 'outline-lime-300 text-lime' : '',
submitted && submitted &&
!answer.correct && !answer.correct &&
@ -314,10 +333,16 @@ function QuizBlockComponent(props: any) {
> >
<div <div
className={twMerge( className={twMerge(
'bg-white font-bold text-base flex items-center h-full w-[40px] rounded-l-md text-slate-800', 'font-bold text-base flex items-center justify-center self-stretch w-[40px] rounded-l-md text-slate-800 bg-white',
answer.correct && isEditable answer.correct && isEditable
? 'bg-lime-300 text-lime-800 outline-none' ? 'bg-lime-300 text-lime-800 outline-none'
: 'bg-white', : 'bg-white',
userAnswers.some(
(userAnswer: any) =>
userAnswer.question_id === question.question_id &&
userAnswer.answer_id === answer.answer_id &&
!isEditable && !submitted
) ? 'bg-blue-400 text-white outline-none' : '',
submitted && answer.correct submitted && answer.correct
? 'bg-lime-300 text-lime-800 outline-none' ? 'bg-lime-300 text-lime-800 outline-none'
: '', : '',
@ -332,7 +357,7 @@ function QuizBlockComponent(props: any) {
: '' : ''
)} )}
> >
<p className="mx-auto font-bold text-sm "> <p className="font-bold text-sm">
{getAnswerID( {getAnswerID(
question.answers.indexOf(answer), question.answers.indexOf(answer),
question.question_id question.question_id
@ -350,33 +375,37 @@ function QuizBlockComponent(props: any) {
) )
} }
placeholder="Answer" placeholder="Answer"
className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-sm font-bold" className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] border-2 border-gray-200 rounded-md border-dotted text-sm font-bold py-1.5"
></input> ></input>
) : ( ) : (
<p className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] rounded-md ext-sm font-bold"> <p className="w-full mx-2 px-3 pr-6 text-neutral-600 bg-[#00008b00] rounded-md text-sm font-bold py-1.5 break-words">
{answer.answer} {answer.answer}
</p> </p>
)} )}
{isEditable && ( {isEditable && (
<div className="flex space-x-1 items-center"> <div className="flex space-x-1 items-center">
<div <div
onClick={() => onClick={(e) => {
e.stopPropagation();
markAnswerCorrect( markAnswerCorrect(
question.question_id, question.question_id,
answer.answer_id answer.answer_id
) );
} }}
className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-lime-300 hover:bg-lime-400 transition-all ease-linear text-sm cursor-pointer " className="w-[24px] flex-none flex items-center h-[24px] rounded-lg bg-lime-300 hover:bg-lime-400 transition-all ease-linear text-sm cursor-pointer"
title={answer.correct ? "Mark as incorrect" : "Mark as correct"}
> >
<Check className="mx-auto text-lime-800" size={12} /> <Check className="mx-auto text-lime-800" size={14} />
</div> </div>
<div <div
onClick={() => onClick={(e) => {
deleteAnswer(question.question_id, answer.answer_id) e.stopPropagation();
} deleteAnswer(question.question_id, answer.answer_id);
className="w-[20px] flex-none flex items-center h-[20px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer" }}
className="w-[24px] flex-none flex items-center h-[24px] rounded-lg bg-slate-200 hover:bg-slate-300 text-sm transition-all ease-linear cursor-pointer"
title="Delete answer"
> >
<Minus className="mx-auto text-slate-400" size={12} /> <Minus className="mx-auto text-slate-500" size={14} />
</div> </div>
</div> </div>
)} )}
@ -385,9 +414,10 @@ function QuizBlockComponent(props: any) {
{isEditable && ( {isEditable && (
<div <div
onClick={() => addAnswer(question.question_id)} onClick={() => addAnswer(question.question_id)}
className="outline outline-3 w-[30px] flex-none flex items-center h-[30px] outline-white hover:bg-opacity-100 hover:shadow-md rounded-lg bg-white text-sm hover:scale-105 active:scale-110 duration-150 cursor-pointer ease-linear" className="outline outline-2 w-full flex-none flex items-center h-[36px] outline-white hover:bg-opacity-100 hover:shadow-md rounded-lg bg-white text-sm hover:scale-[1.01] active:scale-[1.02] duration-150 cursor-pointer ease-linear justify-center"
> >
<Plus className="mx-auto text-slate-800" size={15} /> <Plus className="text-slate-800 mr-1" size={15} />
<span className="text-slate-800 text-sm">Add Answer</span>
</div> </div>
)} )}
</div> </div>