77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
/**
|
|
* useAnalysis — start an analysis + poll status until terminal.
|
|
*
|
|
* Contract lives in infinith-api/docs/API_CONTRACT.md §2-3.
|
|
* Replace `any` with generated types from `src/api-types/schema.d.ts`
|
|
* once backend `openapi.json` is stable.
|
|
*/
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import { apiClient } from '@/lib/apiClient'
|
|
|
|
type Status = 'pending' | 'discovering' | 'collecting' | 'generating' | 'complete' | 'partial' | 'error'
|
|
|
|
interface StatusResponse {
|
|
analysis_run_id: string
|
|
status: Status
|
|
progress: number
|
|
current_step: string
|
|
channel_errors: Record<string, string>
|
|
completed_at: string | null
|
|
}
|
|
|
|
interface ChannelHandles {
|
|
youtube?: string
|
|
instagram?: string[]
|
|
facebook?: string
|
|
naver_blog?: string
|
|
gangnam_unni?: string
|
|
}
|
|
|
|
const TERMINAL: Status[] = ['complete', 'partial', 'error']
|
|
|
|
export function useAnalysis() {
|
|
const [status, setStatus] = useState<StatusResponse | null>(null)
|
|
const [error, setError] = useState<Error | null>(null)
|
|
const pollerRef = useRef<number | null>(null)
|
|
|
|
useEffect(
|
|
() => () => {
|
|
if (pollerRef.current) window.clearInterval(pollerRef.current)
|
|
},
|
|
[],
|
|
)
|
|
|
|
async function start(input: { clinic_id?: string; url?: string; channels: ChannelHandles }) {
|
|
try {
|
|
const { data } = await apiClient.post('/api/analyses', input)
|
|
pollStatus(data.analysis_run_id)
|
|
return data.analysis_run_id as string
|
|
} catch (err) {
|
|
setError(err as Error)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
function pollStatus(runId: string) {
|
|
if (pollerRef.current) window.clearInterval(pollerRef.current)
|
|
pollerRef.current = window.setInterval(async () => {
|
|
try {
|
|
const { data } = await apiClient.get<StatusResponse>(`/api/analyses/${runId}/status`)
|
|
setStatus(data)
|
|
if (TERMINAL.includes(data.status) && pollerRef.current) {
|
|
window.clearInterval(pollerRef.current)
|
|
pollerRef.current = null
|
|
}
|
|
} catch (err) {
|
|
setError(err as Error)
|
|
if (pollerRef.current) {
|
|
window.clearInterval(pollerRef.current)
|
|
pollerRef.current = null
|
|
}
|
|
}
|
|
}, 2000)
|
|
}
|
|
|
|
return { start, pollStatus, status, error }
|
|
}
|