112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useRef } from "react";
|
||
|
||
import KatexRenderer from "@/components/math/KatexRenderer";
|
||
import type { GradeResult, ParenthesisSignProblem } from "@/lib/engine/types";
|
||
|
||
interface FeedbackPanelProps {
|
||
result: GradeResult;
|
||
problem: ParenthesisSignProblem;
|
||
isLastProblem: boolean;
|
||
onNext: () => void;
|
||
}
|
||
|
||
function formatSignedNumber(value: number) {
|
||
return value < 0 ? `(${value})` : `${value}`;
|
||
}
|
||
|
||
export default function FeedbackPanel({
|
||
result,
|
||
problem,
|
||
isLastProblem,
|
||
onNext,
|
||
}: FeedbackPanelProps) {
|
||
const nextButtonRef = useRef<HTMLButtonElement>(null);
|
||
const signedTerms = [
|
||
problem.a,
|
||
problem.operator === "-" ? -problem.b : problem.b,
|
||
] as const;
|
||
const feedbackItems = signedTerms.map((term, index) => ({
|
||
formulaLatex: `${formatSignedNumber(
|
||
problem.multiplier,
|
||
)}\\times ${formatSignedNumber(term)}`,
|
||
userAnswer: result.userAnswer[index],
|
||
correctAnswer: result.correctAnswer[index],
|
||
correct: result.userAnswer[index] === result.correctAnswer[index],
|
||
}));
|
||
|
||
useEffect(() => {
|
||
nextButtonRef.current?.focus();
|
||
}, []);
|
||
|
||
return (
|
||
<div
|
||
className={`rounded-md p-6 shadow-sm ring-1 ${
|
||
result.correct
|
||
? "bg-emerald-50 text-emerald-950 ring-emerald-200"
|
||
: "bg-red-50 text-red-950 ring-red-200"
|
||
}`}
|
||
>
|
||
<p className="text-lg font-bold">
|
||
{result.correct ? "정답입니다." : "오답입니다."}
|
||
</p>
|
||
<ul className="mt-5 space-y-3">
|
||
{feedbackItems.map((item, index) => (
|
||
<li
|
||
key={index}
|
||
className={`flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md px-4 py-3 text-lg font-semibold ring-1 ring-inset ${
|
||
item.correct
|
||
? "bg-emerald-100 text-emerald-950 ring-emerald-200"
|
||
: "bg-red-100 text-red-950 ring-red-200"
|
||
}`}
|
||
>
|
||
<KatexRenderer latex={item.formulaLatex} output="mathml" />
|
||
<span aria-hidden="true">=</span>
|
||
<span className={item.correct ? undefined : "text-red-700"}>
|
||
<KatexRenderer latex={`${item.userAnswer}`} output="mathml" />
|
||
</span>
|
||
{item.correct ? (
|
||
<span
|
||
aria-label="정답"
|
||
role="img"
|
||
className="inline-flex h-7 items-center text-2xl leading-none text-emerald-700"
|
||
>
|
||
○
|
||
</span>
|
||
) : (
|
||
<>
|
||
<span
|
||
aria-label="오답"
|
||
role="img"
|
||
className="mr-2 inline-flex h-7 items-center text-2xl leading-none text-red-700"
|
||
>
|
||
×
|
||
</span>
|
||
<span className="text-slate-700">
|
||
(
|
||
<span className="font-bold">
|
||
<KatexRenderer
|
||
latex={`${item.correctAnswer}`}
|
||
output="mathml"
|
||
/>
|
||
</span>
|
||
)
|
||
</span>
|
||
</>
|
||
)}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<button
|
||
ref={nextButtonRef}
|
||
type="button"
|
||
onClick={onNext}
|
||
className="mt-5 inline-flex h-11 items-center justify-center rounded-md bg-slate-950 px-5 text-base font-semibold text-white transition hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||
>
|
||
{isLastProblem ? "결과 보기" : "다음 문제"}
|
||
</button>
|
||
</div>
|
||
);
|
||
}
|