"use client"; import { useEffect, useState } 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, 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"; 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: "", }, }); useEffect(() => { if (!id) return; fetchItem(id); }, [id]); const fetchItem = 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 || {}; 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); } }; 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?.source_file_path ? migrationService.getStagingFileUrl(item.aiIssues.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 ? (