Quiz: selecting an option only highlights it blue; the answer is submitted by a «بررسی» button and green/red is shown after, then «ادامه»
This commit is contained in:
@@ -101,9 +101,15 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
};
|
};
|
||||||
}, [lessonId, nodeId, nodeMode, reload]);
|
}, [lessonId, nodeId, nodeMode, reload]);
|
||||||
|
|
||||||
async function choose(optionId: string) {
|
/** انتخاب فقط گزینه را آبی میکند؛ تا «بررسی» نزده، چیزی ثبت یا رو نمیشود و میشود عوضش کرد. */
|
||||||
if (!question || selected !== null || submitting) return;
|
function choose(optionId: string) {
|
||||||
|
if (!question || answer || submitting) return;
|
||||||
setSelected(optionId);
|
setSelected(optionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function check() {
|
||||||
|
if (!question || selected === null || answer || submitting) return;
|
||||||
|
const optionId = selected;
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
let key = answerKeys.current.get(question.id);
|
let key = answerKeys.current.get(question.id);
|
||||||
if (!key) {
|
if (!key) {
|
||||||
@@ -121,7 +127,7 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
sounds.wrong();
|
sounds.wrong();
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setSelected(null);
|
// گزینه انتخابشده میماند تا کاربر دوباره «بررسی» بزند.
|
||||||
if (err instanceof ApiError && err.code === 'no_hearts') {
|
if (err instanceof ApiError && err.code === 'no_hearts') {
|
||||||
setPhase({
|
setPhase({
|
||||||
kind: 'noHearts',
|
kind: 'noHearts',
|
||||||
@@ -239,7 +245,7 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
|
|
||||||
const mood: SeyarMood = !answer ? 'idle' : answer.correct ? 'excited' : outOfHearts ? 'depressed' : 'sad';
|
const mood: SeyarMood = !answer ? 'idle' : answer.correct ? 'excited' : outOfHearts ? 'depressed' : 'sad';
|
||||||
const bubble = !answer
|
const bubble = !answer
|
||||||
? 'جوابِ درست رو انتخاب کن!'
|
? selected === null ? 'جوابِ درست رو انتخاب کن!' : 'مطمئنی؟ «بررسی» رو بزن.'
|
||||||
: answer.correct
|
: answer.correct
|
||||||
? 'آفرین! درست بود'
|
? 'آفرین! درست بود'
|
||||||
: outOfHearts
|
: outOfHearts
|
||||||
@@ -248,7 +254,7 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
const shortOptions = question.options.every((o) => o.value.length <= 14);
|
const shortOptions = question.options.every((o) => o.value.length <= 14);
|
||||||
|
|
||||||
const optionClass = (id: string) => {
|
const optionClass = (id: string) => {
|
||||||
if (!answer) return selected === id ? 'border-coral bg-[#fff4f2] text-ink' : 'border-line bg-white text-ink';
|
if (!answer) return selected === id ? 'border-[#84D8FF] bg-[#DDF4FF] text-[#1581BA]' : 'border-line bg-white text-ink';
|
||||||
if (id === answer.correctOptionId) return 'border-green-400 bg-[#e5fdf0] text-green-700';
|
if (id === answer.correctOptionId) return 'border-green-400 bg-[#e5fdf0] text-green-700';
|
||||||
if (id === selected) return 'border-red-300 bg-[#fff0f0] text-red-500';
|
if (id === selected) return 'border-red-300 bg-[#fff0f0] text-red-500';
|
||||||
return 'border-line bg-white text-faint';
|
return 'border-line bg-white text-faint';
|
||||||
@@ -312,9 +318,10 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
<motion.button
|
<motion.button
|
||||||
key={option.id}
|
key={option.id}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => void choose(option.id)}
|
onClick={() => choose(option.id)}
|
||||||
disabled={selected !== null && !answer}
|
disabled={submitting || answer !== null}
|
||||||
whileTap={{ scale: selected === null ? 0.95 : 1 }}
|
aria-pressed={selected === option.id}
|
||||||
|
whileTap={{ scale: answer ? 1 : 0.95 }}
|
||||||
className={`flex min-h-14 items-center justify-center gap-1.5 rounded-2xl border-2 border-b-4 px-3 py-3 font-black transition-colors ${shortOptions ? 'text-xl' : 'text-base'} ${optionClass(option.id)}`}
|
className={`flex min-h-14 items-center justify-center gap-1.5 rounded-2xl border-2 border-b-4 px-3 py-3 font-black transition-colors ${shortOptions ? 'text-xl' : 'text-base'} ${optionClass(option.id)}`}
|
||||||
>
|
>
|
||||||
<span><MathText text={option.value} /></span>
|
<span><MathText text={option.value} /></span>
|
||||||
@@ -324,17 +331,24 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{answer && (
|
</div>
|
||||||
<motion.div initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} className="mt-1 flex flex-col gap-2.5">
|
|
||||||
|
<div className="flex flex-shrink-0 flex-col gap-2.5 border-t border-line bg-white px-4 pb-[max(env(safe-area-inset-bottom),1rem)] pt-3">
|
||||||
|
{answer ? (
|
||||||
|
<>
|
||||||
{!answer.correct && (
|
{!answer.correct && (
|
||||||
<button type="button" onClick={askWhy} className="flex items-center justify-center gap-2 rounded-2xl bg-[#F5F1FF] py-3 text-sm font-bold text-[#7857E0]">
|
<button type="button" onClick={askWhy} className="flex items-center justify-center gap-2 rounded-2xl bg-[#F5F1FF] py-3 text-sm font-bold text-[#7857E0]">
|
||||||
<Brain size={16} /> از پی بپرس چرا غلط شد
|
<Brain size={16} /> از پی بپرس چرا غلط شد
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<PrimaryButton color={answer.correct ? '#5FBF8F' : color} onClick={() => void next()}>
|
<PrimaryButton color={answer.correct ? '#5FBF8F' : color} onClick={() => void next()}>
|
||||||
{isLast ? 'پایانِ تمرین' : 'سوالِ بعدی'} <ChevronLeft size={18} />
|
{isLast ? 'پایانِ تمرین' : 'ادامه'} <ChevronLeft size={18} />
|
||||||
|
</PrimaryButton>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<PrimaryButton color={color} disabled={selected === null} loading={submitting} onClick={() => void check()}>
|
||||||
|
بررسی
|
||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
</motion.div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user