fix
Some checks are pending
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions

This commit is contained in:
Dmitry 2025-12-17 04:15:30 +03:00
parent 0b14a7458e
commit c9f557b5b7
3 changed files with 85 additions and 32 deletions

View file

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react' import { useState, useEffect, useCallback } from 'react'
import type { Question, SimpleQuestion, InputButtonsQuestion } from '@/types/questions' import type { Question, SimpleQuestion, InputButtonsQuestion } from '@/types/questions'
import { QuestionType, isInputButtonsQuestion } from '@/types/questions' import { QuestionType, isInputButtonsQuestion } from '@/types/questions'
import { import {
@ -69,13 +69,38 @@ export function QuestionEditorDialog({
} }
}, [open, question]) }, [open, question])
const handleQuestionChange = ( const handleQuestionChange = useCallback((
updated: Partial<Question> | null, updated: Partial<Question> | null,
valid: boolean, valid: boolean,
) => { ) => {
setCurrentQuestion(updated) setCurrentQuestion(updated)
setIsValid(valid) setIsValid(valid)
} }, [])
const handleSimpleQuestionChange = useCallback((updated: Partial<SimpleQuestion>) => {
setCurrentQuestion({
...updated,
questionType: QuestionType.SIMPLE,
})
setIsValid(
!!(updated.word && updated.answer && updated.options?.length),
)
}, [])
const handleInputButtonsQuestionChange = useCallback((updated: Partial<InputButtonsQuestion>) => {
setCurrentQuestion({
...updated,
questionType: QuestionType.INPUT_BUTTONS,
})
setIsValid(
!!(
updated.word &&
updated.answer &&
updated.options?.length &&
updated.template
),
)
}, [])
const handleSave = () => { const handleSave = () => {
if (!currentQuestion || !isValid) { if (!currentQuestion || !isValid) {
@ -187,33 +212,12 @@ export function QuestionEditorDialog({
{questionType === QuestionType.SIMPLE ? ( {questionType === QuestionType.SIMPLE ? (
<SimpleQuestionForm <SimpleQuestionForm
question={(currentQuestion as Partial<SimpleQuestion>) || {}} question={(currentQuestion as Partial<SimpleQuestion>) || {}}
onChange={(updated) => { onChange={handleSimpleQuestionChange}
setCurrentQuestion({
...updated,
questionType: QuestionType.SIMPLE,
})
setIsValid(
!!(updated.word && updated.answer && updated.options?.length),
)
}}
/> />
) : ( ) : (
<InputButtonsQuestionForm <InputButtonsQuestionForm
question={(currentQuestion as Partial<InputButtonsQuestion>) || {}} question={(currentQuestion as Partial<InputButtonsQuestion>) || {}}
onChange={(updated) => { onChange={handleInputButtonsQuestionChange}
setCurrentQuestion({
...updated,
questionType: QuestionType.INPUT_BUTTONS,
})
setIsValid(
!!(
updated.word &&
updated.answer &&
updated.options?.length &&
updated.template
),
)
}}
/> />
)} )}
</div> </div>

View file

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react' import { useState, useEffect, useRef, useMemo } from 'react'
import type { InputButtonsQuestion, TestButton } from '@/types/questions' import type { InputButtonsQuestion, TestButton } from '@/types/questions'
import { QuestionType } from '@/types/questions' import { QuestionType } from '@/types/questions'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
@ -32,9 +32,34 @@ export function InputButtonsQuestionForm({
const [buttons, setButtons] = useState<TestButton[]>(question.options || []) const [buttons, setButtons] = useState<TestButton[]>(question.options || [])
const [answer, setAnswer] = useState(question.answer || '') const [answer, setAnswer] = useState(question.answer || '')
const [template, setTemplate] = useState(question.template || '') const [template, setTemplate] = useState(question.template || '')
const onChangeRef = useRef(onChange)
// Keep onChange ref up to date
useEffect(() => { useEffect(() => {
onChange({ onChangeRef.current = onChange
}, [onChange])
// Track the initial question to detect when we're editing a different question
const initialQuestionRef = useRef<string | undefined>(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, questionType: QuestionType.INPUT_BUTTONS,
word, word,
text: text || undefined, text: text || undefined,
@ -44,7 +69,7 @@ export function InputButtonsQuestionForm({
answer, answer,
template, template,
}) })
}, [word, text, image, audio, buttons, answer, template, onChange]) }, [word, text, image, audio, buttons, answer, template])
const addButton = () => { const addButton = () => {
const newButton: TestButton = { const newButton: TestButton = {

View file

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react' import { useState, useEffect, useRef, useMemo } from 'react'
import type { SimpleQuestion, TestButton } from '@/types/questions' import type { SimpleQuestion, TestButton } from '@/types/questions'
import { QuestionType } from '@/types/questions' import { QuestionType } from '@/types/questions'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
@ -31,9 +31,33 @@ export function SimpleQuestionForm({
const [audio, setAudio] = useState(question.audio || '') const [audio, setAudio] = useState(question.audio || '')
const [buttons, setButtons] = useState<TestButton[]>(question.options || []) const [buttons, setButtons] = useState<TestButton[]>(question.options || [])
const [answer, setAnswer] = useState(question.answer || '') const [answer, setAnswer] = useState(question.answer || '')
const onChangeRef = useRef(onChange)
// Keep onChange ref up to date
useEffect(() => { useEffect(() => {
onChange({ onChangeRef.current = onChange
}, [onChange])
// Track the initial question to detect when we're editing a different question
const initialQuestionRef = useRef<string | undefined>(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, questionType: QuestionType.SIMPLE,
word, word,
text: text || undefined, text: text || undefined,
@ -42,7 +66,7 @@ export function SimpleQuestionForm({
options: buttons, options: buttons,
answer, answer,
}) })
}, [word, text, image, audio, buttons, answer, onChange]) }, [word, text, image, audio, buttons, answer])
const addButton = () => { const addButton = () => {
const newButton: TestButton = { const newButton: TestButton = {