diff --git a/frontend/src/hooks/useJob.ts b/frontend/src/hooks/useJob.ts index dd5887a..34e2d20 100644 --- a/frontend/src/hooks/useJob.ts +++ b/frontend/src/hooks/useJob.ts @@ -29,6 +29,10 @@ export function useJob(jobId: string) { enabled: !!jobId, staleTime: 30000, // 30 seconds refetchOnWindowFocus: false, + refetchInterval: (query) => { + const status = query.state.data?.status; + return status === 'rendering_qc' ? 5000 : false; + }, }); } diff --git a/frontend/src/routes/admin/QCDetail.tsx b/frontend/src/routes/admin/QCDetail.tsx index a69c730..3633c2a 100644 --- a/frontend/src/routes/admin/QCDetail.tsx +++ b/frontend/src/routes/admin/QCDetail.tsx @@ -1,4 +1,5 @@ import { useState, useEffect, useRef, useMemo } from 'react'; +import { useQueryClient } from '@tanstack/react-query'; import { useParams, useNavigate } from 'react-router-dom'; import { useJob, useApproveEnglish, useRejectJob, useJobVttContent, useUpdateJobVtt, useJobDownloads, useAdjustVttTiming, useUpdateTTSPreferences } from '../../hooks/useJob'; import { @@ -88,6 +89,7 @@ export function QCDetail() { const [adVttUploaded, setAdVttUploaded] = useState(false); const captionsFileInputRef = useRef(null); const adFileInputRef = useRef(null); + const prevJobStatusRef = useRef(undefined); const [ttsPreferences, setTtsPreferences] = useState({ provider: 'gemini', default_voice: 'Kore', @@ -119,6 +121,20 @@ export function QCDetail() { setLastDeletedAdCue(null); }, [selectedLanguage]); + // Refresh edit state when render completes (rendering_qc → pending_qc transition) + const queryClient = useQueryClient(); + useEffect(() => { + if ( + prevJobStatusRef.current === 'rendering_qc' && + job?.status === 'pending_qc' + ) { + queryClient.invalidateQueries({ + queryKey: ['jobs', id, 'accessible-video', selectedLanguage, 'edit-state'], + }); + } + prevJobStatusRef.current = job?.status; + }, [job?.status, id, selectedLanguage, queryClient]); + // Sync pending regenerations from server edit state useEffect(() => { if (editState?.tts_regeneration_queue) {