forked from Tadrisino/MathApp_frontend
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]);
|
||||
|
||||
async function choose(optionId: string) {
|
||||
if (!question || selected !== null || submitting) return;
|
||||
/** انتخاب فقط گزینه را آبی میکند؛ تا «بررسی» نزده، چیزی ثبت یا رو نمیشود و میشود عوضش کرد. */
|
||||
function choose(optionId: string) {
|
||||
if (!question || answer || submitting) return;
|
||||
setSelected(optionId);
|
||||
}
|
||||
|
||||
async function check() {
|
||||
if (!question || selected === null || answer || submitting) return;
|
||||
const optionId = selected;
|
||||
setSubmitting(true);
|
||||
let key = answerKeys.current.get(question.id);
|
||||
if (!key) {
|
||||
@@ -121,7 +127,7 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
||||
sounds.wrong();
|
||||
}
|
||||
} catch (err) {
|
||||
setSelected(null);
|
||||
// گزینه انتخابشده میماند تا کاربر دوباره «بررسی» بزند.
|
||||
if (err instanceof ApiError && err.code === 'no_hearts') {
|
||||
setPhase({
|
||||
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 bubble = !answer
|
||||
? 'جوابِ درست رو انتخاب کن!'
|
||||
? selected === null ? 'جوابِ درست رو انتخاب کن!' : 'مطمئنی؟ «بررسی» رو بزن.'
|
||||
: answer.correct
|
||||
? 'آفرین! درست بود'
|
||||
: 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 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 === selected) return 'border-red-300 bg-[#fff0f0] text-red-500';
|
||||
return 'border-line bg-white text-faint';
|
||||
@@ -312,9 +318,10 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
||||
<motion.button
|
||||
key={option.id}
|
||||
type="button"
|
||||
onClick={() => void choose(option.id)}
|
||||
disabled={selected !== null && !answer}
|
||||
whileTap={{ scale: selected === null ? 0.95 : 1 }}
|
||||
onClick={() => choose(option.id)}
|
||||
disabled={submitting || answer !== null}
|
||||
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)}`}
|
||||
>
|
||||
<span><MathText text={option.value} /></span>
|
||||
@@ -324,17 +331,24 @@ export function QuizScreen({ lessonId, nodeId }: { lessonId?: number; nodeId?: s
|
||||
))}
|
||||
</div>
|
||||
|
||||
{answer && (
|
||||
<motion.div initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} className="mt-1 flex flex-col gap-2.5">
|
||||
</div>
|
||||
|
||||
<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 && (
|
||||
<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} /> از پی بپرس چرا غلط شد
|
||||
</button>
|
||||
)}
|
||||
<PrimaryButton color={answer.correct ? '#5FBF8F' : color} onClick={() => void next()}>
|
||||
{isLast ? 'پایانِ تمرین' : 'سوالِ بعدی'} <ChevronLeft size={18} />
|
||||
{isLast ? 'پایانِ تمرین' : 'ادامه'} <ChevronLeft size={18} />
|
||||
</PrimaryButton>
|
||||
</motion.div>
|
||||
</>
|
||||
) : (
|
||||
<PrimaryButton color={color} disabled={selected === null} loading={submitting} onClick={() => void check()}>
|
||||
بررسی
|
||||
</PrimaryButton>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user