diff --git a/mnemo_cards_admin/src/components/QuestionEditorDialog.tsx b/mnemo_cards_admin/src/components/QuestionEditorDialog.tsx index d31e3c4..3a83cef 100644 --- a/mnemo_cards_admin/src/components/QuestionEditorDialog.tsx +++ b/mnemo_cards_admin/src/components/QuestionEditorDialog.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useCallback } from 'react' import type { Question, SimpleQuestion, InputButtonsQuestion } from '@/types/questions' import { QuestionType, isInputButtonsQuestion } from '@/types/questions' import { @@ -69,13 +69,38 @@ export function QuestionEditorDialog({ } }, [open, question]) - const handleQuestionChange = ( + const handleQuestionChange = useCallback(( updated: Partial | null, valid: boolean, ) => { setCurrentQuestion(updated) setIsValid(valid) - } + }, []) + + const handleSimpleQuestionChange = useCallback((updated: Partial) => { + setCurrentQuestion({ + ...updated, + questionType: QuestionType.SIMPLE, + }) + setIsValid( + !!(updated.word && updated.answer && updated.options?.length), + ) + }, []) + + const handleInputButtonsQuestionChange = useCallback((updated: Partial) => { + setCurrentQuestion({ + ...updated, + questionType: QuestionType.INPUT_BUTTONS, + }) + setIsValid( + !!( + updated.word && + updated.answer && + updated.options?.length && + updated.template + ), + ) + }, []) const handleSave = () => { if (!currentQuestion || !isValid) { @@ -187,33 +212,12 @@ export function QuestionEditorDialog({ {questionType === QuestionType.SIMPLE ? ( ) || {}} - onChange={(updated) => { - setCurrentQuestion({ - ...updated, - questionType: QuestionType.SIMPLE, - }) - setIsValid( - !!(updated.word && updated.answer && updated.options?.length), - ) - }} + onChange={handleSimpleQuestionChange} /> ) : ( ) || {}} - onChange={(updated) => { - setCurrentQuestion({ - ...updated, - questionType: QuestionType.INPUT_BUTTONS, - }) - setIsValid( - !!( - updated.word && - updated.answer && - updated.options?.length && - updated.template - ), - ) - }} + onChange={handleInputButtonsQuestionChange} /> )} diff --git a/mnemo_cards_admin/src/components/forms/InputButtonsQuestionForm.tsx b/mnemo_cards_admin/src/components/forms/InputButtonsQuestionForm.tsx index f4baac7..d2bf592 100644 --- a/mnemo_cards_admin/src/components/forms/InputButtonsQuestionForm.tsx +++ b/mnemo_cards_admin/src/components/forms/InputButtonsQuestionForm.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef, useMemo } from 'react' import type { InputButtonsQuestion, TestButton } from '@/types/questions' import { QuestionType } from '@/types/questions' import { Label } from '@/components/ui/label' @@ -32,9 +32,34 @@ export function InputButtonsQuestionForm({ const [buttons, setButtons] = useState(question.options || []) const [answer, setAnswer] = useState(question.answer || '') const [template, setTemplate] = useState(question.template || '') + const onChangeRef = useRef(onChange) + // Keep onChange ref up to date useEffect(() => { - onChange({ + onChangeRef.current = onChange + }, [onChange]) + + // Track the initial question to detect when we're editing a different question + const initialQuestionRef = useRef(question.id) + + // Initialize state when question prop changes (e.g., when editing a different question) + useEffect(() => { + // Only sync if the question id changed (different question) or if this is the first render + if (initialQuestionRef.current !== question.id) { + initialQuestionRef.current = question.id + setWord(question.word || '') + setText(question.text || '') + setImage(question.image || '') + setAudio(question.audio || '') + setButtons(question.options || []) + setAnswer(question.answer || '') + setTemplate(question.template || '') + } + }, [question.id, question.word, question.text, question.image, question.audio, question.options, question.answer, question.template]) + + // Notify parent of changes + useEffect(() => { + onChangeRef.current({ questionType: QuestionType.INPUT_BUTTONS, word, text: text || undefined, @@ -44,7 +69,7 @@ export function InputButtonsQuestionForm({ answer, template, }) - }, [word, text, image, audio, buttons, answer, template, onChange]) + }, [word, text, image, audio, buttons, answer, template]) const addButton = () => { const newButton: TestButton = { diff --git a/mnemo_cards_admin/src/components/forms/SimpleQuestionForm.tsx b/mnemo_cards_admin/src/components/forms/SimpleQuestionForm.tsx index b4c5243..2e237bc 100644 --- a/mnemo_cards_admin/src/components/forms/SimpleQuestionForm.tsx +++ b/mnemo_cards_admin/src/components/forms/SimpleQuestionForm.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef, useMemo } from 'react' import type { SimpleQuestion, TestButton } from '@/types/questions' import { QuestionType } from '@/types/questions' import { Label } from '@/components/ui/label' @@ -31,9 +31,33 @@ export function SimpleQuestionForm({ const [audio, setAudio] = useState(question.audio || '') const [buttons, setButtons] = useState(question.options || []) const [answer, setAnswer] = useState(question.answer || '') + const onChangeRef = useRef(onChange) + // Keep onChange ref up to date useEffect(() => { - onChange({ + onChangeRef.current = onChange + }, [onChange]) + + // Track the initial question to detect when we're editing a different question + const initialQuestionRef = useRef(question.id) + + // Initialize state when question prop changes (e.g., when editing a different question) + useEffect(() => { + // Only sync if the question id changed (different question) or if this is the first render + if (initialQuestionRef.current !== question.id) { + initialQuestionRef.current = question.id + setWord(question.word || '') + setText(question.text || '') + setImage(question.image || '') + setAudio(question.audio || '') + setButtons(question.options || []) + setAnswer(question.answer || '') + } + }, [question.id, question.word, question.text, question.image, question.audio, question.options, question.answer]) + + // Notify parent of changes + useEffect(() => { + onChangeRef.current({ questionType: QuestionType.SIMPLE, word, text: text || undefined, @@ -42,7 +66,7 @@ export function SimpleQuestionForm({ options: buttons, answer, }) - }, [word, text, image, audio, buttons, answer, onChange]) + }, [word, text, image, audio, buttons, answer]) const addButton = () => { const newButton: TestButton = {