"use client"; import { useState } from "react"; import { UploadDropzone } from "@uploadthing/react"; import { AlertCircle, Sparkles, Wand2, ShieldCheck, Loader2, } from "lucide-react"; import { Card } from "@/components/ui/card"; import { saveContract } from "@/features/contracts/api/contract.action"; import { toast } from "sonner"; import type { OurFileRouter } from "@/lib/upload"; import { useRouter } from "next/navigation"; export function ContractUploadForm({ onUploadSuccess, }: { onUploadSuccess: () => void; }) { const router = useRouter(); const [isAutoAnalyzing, setIsAutoAnalyzing] = useState(false); const emitNotificationRefresh = () => { window.dispatchEvent(new Event("notifications:refresh")); const channel = new BroadcastChannel("notifications-channel"); channel.postMessage({ type: "notifications:refresh" }); channel.close(); }; return (

AI-Ready Intake

Upload contracts for structured extraction

Clean intake pipeline for contract parsing, validation, and analysis.

Theme-aware secure upload
endpoint="contractUploader" onClientUploadComplete={async (res) => { if (!res || res.length === 0) { toast.error("Upload failed"); return; } const file = res[0]; setIsAutoAnalyzing(true); try { // Save to database const result = await saveContract({ fileName: file.name, fileUrl: file.url, fileSize: file.size, mimeType: file.type, }); if (result.success) { if ( (result as { analysisSuccess?: boolean }).analysisSuccess === false ) { toast.warning( (result as { analysisError?: string }).analysisError || "Contract uploaded, but analysis failed.", ); } else { toast.success("Contract uploaded and analyzed successfully!"); } emitNotificationRefresh(); onUploadSuccess(); router.refresh(); } else { const fallbackError = "error" in result ? result.error : "Failed to save contract"; toast.error(fallbackError); } } catch (error) { toast.error( error instanceof Error ? error.message : "Unexpected error during analysis", ); } finally { setIsAutoAnalyzing(false); } }} onUploadError={(error: Error) => { setIsAutoAnalyzing(false); toast.error(`Upload failed: ${error.message}`); }} appearance={{ container: "w-full cursor-pointer rounded-2xl border border-dashed border-primary/35 bg-background/85 px-4 py-8 backdrop-blur-sm transition-all duration-300 hover:border-primary/55 hover:bg-background ut-uploading:cursor-not-allowed", button: "bg-gradient-to-r from-primary to-accent text-white font-semibold px-6 py-3 rounded-xl transition-all duration-300 hover:from-primary/90 hover:to-accent/90 ut-uploading:cursor-not-allowed", label: "text-base md:text-lg text-foreground font-semibold", uploadIcon: "w-11 h-11 text-primary", allowedContent: "mt-2 text-sm text-muted-foreground", }} content={{ label: "Upload Your Contract", allowedContent: "PDF, JPG, PNG, WEBP up to 8MB", }} />
Formats
PDF, JPG, PNG, WEBP
Max Size
8 MB
AI Flow
Upload starts instant AI analysis + RAG indexing
Extraction quality improves as more contracts are analyzed.
{isAutoAnalyzing && (

Analyzing And Building RAG

Your contract is being analyzed and indexed for chat...

Processing

This may take up to 10 seconds

)}
); }