'use client'; import { useEffect, useState, useCallback } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { migrationService } from '@/lib/services/migration.service'; import { MigrationReviewQueueItem } from '@/types/migration'; import { Button } from '@/components/ui/button'; import { Form, FormControl, FormDescription as _FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { ArrowLeftIcon, CheckCircleIcon, XCircleIcon } from 'lucide-react'; import Link from 'next/link'; import { toast } from 'sonner'; import { Card, CardContent } from '@/components/ui/card'; interface MigrationAiIssues { document_date?: string; issued_date?: string; received_date?: string; sender_id?: string | number; discipline_id?: string | number; source_file_path?: string; key_points?: string[]; validation_results?: Array<{ message: string; severity: string }>; } const reviewFormSchema = z.object({ document_number: z.string().min(1, 'Document number is required'), subject: z.string().min(1, 'Subject is required'), category: z.string().min(1, 'Category is required'), document_date: z.string().optional(), issued_date: z.string().optional(), received_date: z.string().optional(), sender_id: z.string().optional(), discipline_id: z.string().optional(), }); type ReviewFormValues = z.infer; export default function MigrationReviewPage() { const params = useParams(); const router = useRouter(); const id = Number(params.id); const [item, setItem] = useState(null); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const form = useForm({ resolver: zodResolver(reviewFormSchema), defaultValues: { document_number: '', subject: '', category: '', document_date: '', issued_date: '', received_date: '', sender_id: '', discipline_id: '', }, }); const fetchItem = useCallback( async (itemId: number) => { try { setLoading(true); const res = await migrationService.getQueueItem(itemId); setItem(res); if (res) { // Pre-fill form from database item and aiIssues payload const issues = (res.aiIssues || {}) as MigrationAiIssues; form.reset({ document_number: res.documentNumber || '', subject: res.title || res.originalTitle || '', category: res.aiSuggestedCategory || '', document_date: issues.document_date || '', issued_date: issues.issued_date || '', received_date: issues.received_date || '', sender_id: issues.sender_id ? String(issues.sender_id) : '', discipline_id: issues.discipline_id ? String(issues.discipline_id) : '', }); } } catch (_error) { toast.error('Failed to load queue item'); } finally { setLoading(false); } }, [form] ); useEffect(() => { if (!id) return; fetchItem(id); }, [id, fetchItem]); const onSubmit = async (values: ReviewFormValues) => { if (!item) return; try { setSubmitting(true); const issues = item.aiIssues || {}; const payload = { document_number: values.document_number, subject: values.subject, category: values.category, source_file_path: issues.source_file_path || '', migrated_by: 'SYSTEM_IMPORT', batch_id: 'MANUAL_REVIEW_BATCH', project_id: 1, // Assumption or pulled from store document_date: values.document_date, issued_date: values.issued_date, received_date: values.received_date, sender_id: values.sender_id ? Number(values.sender_id) : undefined, discipline_id: values.discipline_id ? Number(values.discipline_id) : undefined, details: { tags: issues.tags || [], ai_confidence: item.aiConfidence, }, }; // Mock idempotency key based on timestamp to ensure uniqueness per approval retry const idempotencyKey = `review-${item.id}-${Date.now()}`; await migrationService.approveQueueItem(item.id, payload, idempotencyKey); toast.success('Document approved and imported successfully'); router.push('/admin/migration'); } catch (error: unknown) { const err = error as { response?: { data?: { message?: string } } }; toast.error(err?.response?.data?.message || 'Failed to approve and import'); } finally { setSubmitting(false); } }; const onReject = async () => { if (!item || !confirm('Are you sure you want to REJECT this document? It will not be imported.')) return; try { setSubmitting(true); await migrationService.rejectQueueItem(item.id); toast.success('Document rejected'); router.push('/admin/migration'); } catch (_error: unknown) { toast.error('Failed to reject document'); } finally { setSubmitting(false); } }; if (loading) { return
Loading document data...
; } if (!item) { return
Document not found
; } const pdfUrl = (item.aiIssues as MigrationAiIssues)?.source_file_path ? migrationService.getStagingFileUrl((item.aiIssues as MigrationAiIssues).source_file_path!) : null; return (

Review Document: {item.documentNumber}

Status: {item.status} {' | '} Confidence:{' '} {item.aiConfidence ? (item.aiConfidence * 100).toFixed(1) + '%' : 'N/A'}

{/* Left Side: PDF Viewer */} {pdfUrl ? (