'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import { Button } from '@/components/ui/button'; import { toast } from 'sonner'; import { Sparkles, Loader2 } from 'lucide-react'; import type { JobStatus } from '@/lib/types/analyzer'; interface AnalyzeButtonProps { ticketNumber: string; /** Force a re-run even if the content hash matches an existing analysis. */ force?: boolean; variant?: 'default' | 'outline' | 'secondary'; label?: string; } const STAGE_LABEL: Record = { queued: 'Queued…', fetching: 'Fetching…', triaging: 'Triaging…', itglue: 'Searching IT Glue…', analyzing: 'Analyzing…', deep_review: 'Deep review…', complete: 'Done', failed: 'Failed', }; export function AnalyzeButton({ ticketNumber, force = false, variant = 'default', label = 'Analyze', }: AnalyzeButtonProps) { const router = useRouter(); const [status, setStatus] = useState('idle'); async function pollJob(jobId: string) { const start = Date.now(); const TIMEOUT_MS = 5 * 60 * 1000; while (Date.now() - start < TIMEOUT_MS) { await new Promise((r) => setTimeout(r, 2000)); const res = await fetch(`/api/analyzer/jobs/${jobId}`); if (!res.ok) throw new Error(`Job poll failed: ${res.status}`); const { job } = (await res.json()) as { job: { status: JobStatus; resultAnalysisId: string | null; errorMessage: string | null }; }; setStatus(job.status); if (job.status === 'complete' && job.resultAnalysisId) { return job.resultAnalysisId; } if (job.status === 'failed') { throw new Error(job.errorMessage ?? 'Analysis failed'); } } throw new Error('Analysis timed out after 5 minutes'); } async function handleClick() { setStatus('queued'); try { const res = await fetch( `/api/analyzer/tickets/${encodeURIComponent(ticketNumber)}/analyze`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ force }), } ); if (!res.ok) { const error = (await res.json().catch(() => ({}))) as { error?: string }; throw new Error(error.error ?? `Request failed: ${res.status}`); } const data = (await res.json()) as | { status: 'complete'; existingAnalysisId: string } | { status: 'queued'; jobId: string }; if (data.status === 'complete') { router.push(`/analyzer/analysis/${data.existingAnalysisId}`); return; } const analysisId = await pollJob(data.jobId); router.push(`/analyzer/analysis/${analysisId}`); } catch (err) { const msg = err instanceof Error ? err.message : 'Unknown error'; toast.error(msg); setStatus('idle'); } } const isRunning = status !== 'idle' && status !== 'failed'; return ( ); }