'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 { documentDate?: string; issuedDate?: string; receivedDate?: string; senderId?: string | number; disciplineId?: string | number; sourceFilePath?: string; keyPoints?: string[]; validationResults?: Array<{ message: string; severity: string }>; } const reviewFormSchema = z.object({ documentNumber: z.string().min(1, 'Document number is required'), subject: z.string().min(1, 'Subject is required'), category: z.string().min(1, 'Category is required'), documentDate: z.string().optional(), issuedDate: z.string().optional(), receivedDate: z.string().optional(), senderId: z.string().optional(), disciplineId: 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: { documentNumber: '', subject: '', category: '', documentDate: '', issuedDate: '', receivedDate: '', senderId: '', disciplineId: '', }, }); 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({ documentNumber: res.documentNumber || '', subject: res.title || res.originalTitle || '', category: res.aiSuggestedCategory || '', documentDate: issues.documentDate || '', issuedDate: issues.issuedDate || '', receivedDate: issues.receivedDate || '', senderId: issues.senderId ? String(issues.senderId) : '', disciplineId: issues.disciplineId ? String(issues.disciplineId) : '', }); } } 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 = { documentNumber: values.documentNumber, subject: values.subject, category: values.category, sourceFilePath: issues.sourceFilePath || '', migratedBy: 'SYSTEM_IMPORT', batchId: 'MANUAL_REVIEW_BATCH', projectId: 1, // Assumption or pulled from store documentDate: values.documentDate, issuedDate: values.issuedDate, receivedDate: values.receivedDate, senderId: values.senderId ? Number(values.senderId) : undefined, disciplineId: values.disciplineId ? Number(values.disciplineId) : undefined, details: { tags: issues.tags || [], aiConfidence: 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)?.sourceFilePath ? migrationService.getStagingFileUrl((item.aiIssues as MigrationAiIssues).sourceFilePath!) : null; return (

Review Document: {item.documentNumber}

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

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