Backend changes: - Disable PP-Structure debug file generation by default - Separate raw_ocr_regions.json generation from debug flag (critical file) - Add visualization folder download endpoint as ZIP - Add has_visualization field to TaskDetailResponse - Stop generating Markdown files - Save translated PDFs to task folder with caching Frontend changes: - Replace JSON/MD download buttons with PDF buttons in TaskHistoryPage - Add visualization download button in TaskDetailPage - Fix Processing page task switching issue (reset isNotFound) Archives two OpenSpec proposals: - optimize-task-files-and-visualization - simplify-frontend-add-billing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
91 lines
2.9 KiB
TypeScript
91 lines
2.9 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { AxiosError } from 'axios'
|
|
import { useUploadStore } from '@/store/uploadStore'
|
|
import { useTaskStore } from '@/store/taskStore'
|
|
import { apiClientV2 } from '@/services/apiV2'
|
|
import type { TaskDetail } from '@/types/apiV2'
|
|
|
|
interface UseTaskValidationResult {
|
|
taskId: string | null
|
|
taskDetail: TaskDetail | undefined
|
|
isLoading: boolean
|
|
isNotFound: boolean
|
|
clearAndReset: () => void
|
|
}
|
|
|
|
/**
|
|
* Hook for validating task existence and handling deleted tasks gracefully.
|
|
* Shows loading state first, then either returns task data or marks as not found.
|
|
*
|
|
* This hook integrates with both uploadStore (legacy) and taskStore (new).
|
|
* The taskId is sourced from uploadStore.batchId for backward compatibility,
|
|
* while task metadata is synced to taskStore for caching and state management.
|
|
*/
|
|
export function useTaskValidation(options?: {
|
|
refetchInterval?: number | false | ((query: any) => number | false)
|
|
}): UseTaskValidationResult {
|
|
// Legacy: Get taskId from uploadStore
|
|
const { batchId, clearUpload } = useUploadStore()
|
|
const taskId = batchId ? String(batchId) : null
|
|
|
|
// New: Use taskStore for caching and state management
|
|
const { updateTaskCache, removeFromCache, clearCurrentTask } = useTaskStore()
|
|
|
|
const [isNotFound, setIsNotFound] = useState(false)
|
|
|
|
// Reset isNotFound when taskId changes (new upload)
|
|
useEffect(() => {
|
|
setIsNotFound(false)
|
|
}, [taskId])
|
|
|
|
const { data: taskDetail, isLoading, error, isFetching } = useQuery({
|
|
queryKey: ['taskDetail', taskId],
|
|
queryFn: () => apiClientV2.getTask(taskId!),
|
|
enabled: !!taskId && !isNotFound,
|
|
retry: (failureCount, error: any) => {
|
|
// Don't retry on 404
|
|
if (error?.response?.status === 404) {
|
|
return false
|
|
}
|
|
return failureCount < 2
|
|
},
|
|
refetchInterval: options?.refetchInterval ?? false,
|
|
// Disable stale time to ensure we check fresh data
|
|
staleTime: 0,
|
|
})
|
|
|
|
// Sync task details to taskStore cache when data changes
|
|
useEffect(() => {
|
|
if (taskDetail) {
|
|
updateTaskCache(taskDetail)
|
|
}
|
|
}, [taskDetail, updateTaskCache])
|
|
|
|
// Handle 404 error - mark as not found and clean up cache
|
|
useEffect(() => {
|
|
if (error && error instanceof AxiosError && error.response?.status === 404) {
|
|
setIsNotFound(true)
|
|
if (taskId) {
|
|
removeFromCache(taskId)
|
|
}
|
|
}
|
|
}, [error, taskId, removeFromCache])
|
|
|
|
// Clear state and store
|
|
const clearAndReset = () => {
|
|
clearUpload() // Legacy store
|
|
clearCurrentTask() // New store
|
|
setIsNotFound(false)
|
|
}
|
|
|
|
return {
|
|
taskId,
|
|
taskDetail,
|
|
// Show loading if we have a taskId and are still fetching (but not if already marked as not found)
|
|
isLoading: !!taskId && !isNotFound && (isLoading || isFetching) && !taskDetail,
|
|
isNotFound,
|
|
clearAndReset,
|
|
}
|
|
}
|