문제 풀이 화면의 입력 항 진행 상태 표시 방법 개선

This commit is contained in:
2026-05-30 18:39:22 +09:00
parent 282e4d64cf
commit 33e065301f
4 changed files with 151 additions and 104 deletions
@@ -5,11 +5,11 @@ import { useCallback, useEffect, useRef, useState } from "react";
import type { FormEvent } from "react";
import { flushSync } from "react-dom";
import AnswerForm from "@/components/game/AnswerForm";
import NumberAnswerForm from "@/components/game/NumberAnswerForm";
import type {
ActiveAnswerInput,
AnswerFormHandle,
} from "@/components/game/AnswerForm";
NumberAnswerFormHandle,
} from "@/components/game/NumberAnswerForm";
import FeedbackPanel from "@/components/game/FeedbackPanel";
import ScoreSummary from "@/components/game/ScoreSummary";
import StageIndicator from "@/components/game/StageIndicator";
@@ -46,7 +46,7 @@ export default function NumberPlayClient({
const resetSession = useGameStore((state) => state.resetSession);
const problemCardRef = useRef<HTMLDivElement>(null);
const answerFormRef = useRef<AnswerFormHandle>(null);
const answerFormRef = useRef<NumberAnswerFormHandle>(null);
const [answerA, setAnswerA] = useState("");
const [answerB, setAnswerB] = useState("");
@@ -184,6 +184,10 @@ export default function NumberPlayClient({
const submitted = currentResult !== null;
const isLastProblem = session.currentIndex === session.problems.length - 1;
const pendingAnswerLabels: [string, string] = [
String(currentProblem.a),
String(currentProblem.operator === "-" ? -currentProblem.b : currentProblem.b),
];
return (
<main className="min-h-screen bg-slate-50 px-6 py-10 text-slate-950">
@@ -225,12 +229,13 @@ export default function NumberPlayClient({
</div>
{!submitted ? (
<AnswerForm
<NumberAnswerForm
ref={answerFormRef}
answerA={answerA}
answerB={answerB}
activeInput={activeInput}
error={inputError}
pendingAnswerLabels={pendingAnswerLabels}
onActiveInputChange={setActiveInput}
onAnswerAChange={setAnswerA}
onAnswerBChange={setAnswerB}
@@ -9,6 +9,7 @@ import VariableChoiceAnswerForm from "@/components/game/VariableChoiceAnswerForm
import VariableFeedbackPanel from "@/components/game/VariableFeedbackPanel";
import VariableScoreSummary from "@/components/game/VariableScoreSummary";
import KatexRenderer from "@/components/math/KatexRenderer";
import { formatVariableTermLatex } from "@/lib/engine/variable-parenthesis";
import {
useVariableGameStore,
type VariableProblemCount,
@@ -72,22 +73,27 @@ export default function VariablePlayClient({
}, [currentProblem?.key]);
function handleSelectChoice(termIndex: 0 | 1, choiceId: string) {
setSelectedChoiceIds((current) => {
const next: [string | null, string | null] = [...current];
next[termIndex] = choiceId;
return next;
});
const nextSelectedChoiceIds: [string | null, string | null] = [
...selectedChoiceIds,
];
nextSelectedChoiceIds[termIndex] = choiceId;
setSelectedChoiceIds(nextSelectedChoiceIds);
if (termIndex === 0) {
setActiveTermIndex(1);
return;
}
}
function handleSubmit() {
if (currentResult || !currentProblem) return;
if (selectedChoiceIds[0] === null || selectedChoiceIds[1] === null) return;
if (
nextSelectedChoiceIds[0] === null ||
nextSelectedChoiceIds[1] === null
) {
return;
}
submitAnswer({ selectedChoiceIds });
submitAnswer({ selectedChoiceIds: nextSelectedChoiceIds });
}
function handleNextProblem() {
@@ -134,6 +140,16 @@ export default function VariablePlayClient({
const submitted = currentResult !== null;
const isLastProblem = session.currentIndex === session.problems.length - 1;
const pendingChoiceLabels: [string, string] = [
formatVariableTermLatex(currentProblem.firstTerm),
formatVariableTermLatex({
...currentProblem.secondTerm,
coefficient:
currentProblem.operator === "-"
? -currentProblem.secondTerm.coefficient
: currentProblem.secondTerm.coefficient,
}),
];
return (
<main className="min-h-screen bg-slate-50 px-6 py-10 text-slate-950">
@@ -176,8 +192,8 @@ export default function VariablePlayClient({
choices={currentProblem.choices}
selectedChoiceIds={selectedChoiceIds}
activeTermIndex={activeTermIndex}
pendingChoiceLabels={pendingChoiceLabels}
onSelectChoice={handleSelectChoice}
onSubmit={handleSubmit}
/>
) : null}