Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit
172 lines
4.7 KiB
TypeScript
172 lines
4.7 KiB
TypeScript
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
|
|
import {
|
|
useLazyCheckQueueStatusQuery,
|
|
useSubmitSolutionMutation,
|
|
} from '../__data__/api/api'
|
|
import type { ChallengeSubmission, QueueStatus } from '../__data__/types'
|
|
import { useChallenge } from '../context/ChallengeContext'
|
|
import { loadFinalAnswer, saveFinalAnswer } from '../utils/drafts'
|
|
|
|
interface UseSubmissionArgs {
|
|
taskId: string
|
|
}
|
|
|
|
interface SubmissionResult {
|
|
result: string
|
|
setResult: (value: string) => void
|
|
submit: () => Promise<void>
|
|
reset: () => void
|
|
queueStatus: QueueStatus | null
|
|
finalSubmission: ChallengeSubmission | null
|
|
isSubmitting: boolean
|
|
}
|
|
|
|
export const useSubmission = ({ taskId }: UseSubmissionArgs): SubmissionResult => {
|
|
const {
|
|
userId,
|
|
eventEmitter,
|
|
pollingManager,
|
|
behaviorTracker,
|
|
metricsCollector,
|
|
saveDraft,
|
|
loadDraft,
|
|
clearDraft,
|
|
} = useChallenge()
|
|
|
|
const [result, setResultState] = useState('')
|
|
const [queueId, setQueueId] = useState<string | null>(null)
|
|
const [queueStatus, setQueueStatus] = useState<QueueStatus | null>(null)
|
|
const [finalSubmission, setFinalSubmission] = useState<ChallengeSubmission | null>(null)
|
|
|
|
const [submitSolution, { isLoading: isSubmitting }] = useSubmitSolutionMutation()
|
|
const [triggerCheckStatus] = useLazyCheckQueueStatusQuery()
|
|
|
|
useEffect(() => {
|
|
behaviorTracker.reset()
|
|
|
|
// Сначала проверяем финальный ответ (если задание уже решалось)
|
|
const finalAnswer = loadFinalAnswer(taskId)
|
|
if (finalAnswer) {
|
|
setResultState(finalAnswer)
|
|
behaviorTracker.markDraftUsed()
|
|
} else {
|
|
// Если финального ответа нет, проверяем черновик
|
|
const draft = loadDraft(taskId)
|
|
if (draft) {
|
|
setResultState(draft)
|
|
behaviorTracker.markDraftUsed()
|
|
} else {
|
|
// Если ничего нет - пустое поле
|
|
setResultState('')
|
|
}
|
|
}
|
|
|
|
pollingManager.stop()
|
|
setQueueId(null)
|
|
setQueueStatus(null)
|
|
setFinalSubmission(null)
|
|
}, [behaviorTracker, loadDraft, pollingManager, taskId])
|
|
|
|
const setResult = useCallback(
|
|
(value: string) => {
|
|
setResultState(value)
|
|
behaviorTracker.onTextChange(value)
|
|
saveDraft(taskId, value)
|
|
},
|
|
[behaviorTracker, saveDraft, taskId],
|
|
)
|
|
|
|
const reset = useCallback(() => {
|
|
setResultState('')
|
|
setQueueId(null)
|
|
setQueueStatus(null)
|
|
setFinalSubmission(null)
|
|
behaviorTracker.reset()
|
|
pollingManager.stop()
|
|
clearDraft(taskId)
|
|
}, [behaviorTracker, clearDraft, pollingManager, taskId])
|
|
|
|
const submit = useCallback(async () => {
|
|
if (!userId) {
|
|
throw new Error('Пользователь не авторизован')
|
|
}
|
|
if (!result.trim()) {
|
|
return
|
|
}
|
|
|
|
pollingManager.stop()
|
|
setFinalSubmission(null)
|
|
setQueueStatus(null)
|
|
|
|
const { queueId: newQueueId } = await submitSolution({ userId, taskId, result }).unwrap()
|
|
setQueueId(newQueueId)
|
|
metricsCollector.startTracking(queueStatus?.position ?? 0)
|
|
|
|
pollingManager.start(async () => {
|
|
const status = await triggerCheckStatus(newQueueId, false).unwrap()
|
|
metricsCollector.incrementPoll()
|
|
setQueueStatus(status)
|
|
|
|
if (status.status === 'completed' && status.submission) {
|
|
const performanceMetrics = metricsCollector.getMetrics(status.submission)
|
|
const behaviorMetrics = behaviorTracker.getMetrics(result)
|
|
|
|
const eventPayload = {
|
|
submission: status.submission,
|
|
performanceMetrics,
|
|
behaviorMetrics,
|
|
}
|
|
|
|
eventEmitter.emit({
|
|
type: 'submission_completed',
|
|
timestamp: new Date().toISOString(),
|
|
userId,
|
|
data: eventPayload,
|
|
})
|
|
|
|
setFinalSubmission(status.submission)
|
|
// Сохраняем финальный ответ для восстановления при возврате
|
|
saveFinalAnswer(taskId, result)
|
|
// Очищаем черновик, так как теперь есть финальный ответ
|
|
clearDraft(taskId)
|
|
pollingManager.stop()
|
|
return false
|
|
}
|
|
|
|
if (status.status === 'error') {
|
|
pollingManager.stop()
|
|
return false
|
|
}
|
|
|
|
return true
|
|
})
|
|
}, [
|
|
behaviorTracker,
|
|
clearDraft,
|
|
eventEmitter,
|
|
metricsCollector,
|
|
pollingManager,
|
|
queueStatus?.position,
|
|
result,
|
|
submitSolution,
|
|
taskId,
|
|
triggerCheckStatus,
|
|
userId,
|
|
])
|
|
|
|
return useMemo(
|
|
() => ({
|
|
result,
|
|
setResult,
|
|
submit,
|
|
reset,
|
|
queueStatus,
|
|
finalSubmission,
|
|
isSubmitting,
|
|
}),
|
|
[finalSubmission, isSubmitting, queueStatus, reset, result, setResult, submit],
|
|
)
|
|
}
|
|
|