| 'use client'; |
|
|
| import { useState } from 'react'; |
| import { useRouter } from 'next/navigation'; |
| import { motion } from 'framer-motion'; |
| import { PatentUpload } from '@/components/PatentUpload'; |
| import { uploadPatent, executeWorkflow } from '@/lib/api'; |
| import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; |
| import { Sparkles } from 'lucide-react'; |
| import { toast } from 'sonner'; |
|
|
| export default function UploadPage() { |
| const router = useRouter(); |
| const [uploading, setUploading] = useState(false); |
| const [error, setError] = useState<string | null>(null); |
|
|
| const handleUpload = async (file: File) => { |
| console.log('π― Parent handleUpload called with file:', file); |
|
|
| try { |
| setUploading(true); |
| setError(null); |
|
|
| |
| console.log('π€ Uploading patent:', file.name); |
| toast.info('Uploading patent...', { |
| description: `Uploading ${file.name}`, |
| }); |
|
|
| console.log('π Calling uploadPatent API...'); |
| const uploadResponse = await uploadPatent(file); |
| console.log('β
Upload response:', uploadResponse); |
|
|
| toast.success('Patent uploaded successfully!', { |
| description: `Patent ID: ${uploadResponse.patent_id.slice(0, 8)}...`, |
| }); |
|
|
| |
| console.log('π About to execute workflow for patent:', uploadResponse.patent_id); |
| toast.info('Starting analysis...', { |
| description: 'Initializing Patent Wake-Up workflow', |
| }); |
|
|
| console.log('π Calling executeWorkflow API...'); |
| const workflowResponse = await executeWorkflow(uploadResponse.patent_id); |
| console.log('β
Workflow response:', workflowResponse); |
|
|
| toast.success('Analysis started!', { |
| description: 'Redirecting to progress page...', |
| }); |
|
|
| |
| setTimeout(() => { |
| router.push(`/workflow/${workflowResponse.workflow_id}`); |
| }, 1500); |
| } catch (err: any) { |
| console.error('β Error in handleUpload:', err); |
| console.error('Error details:', { |
| message: err.message, |
| response: err.response?.data, |
| stack: err.stack |
| }); |
|
|
| const errorMessage = |
| err.response?.data?.detail || err.message || 'Failed to upload patent'; |
| setError(errorMessage); |
|
|
| toast.error('Upload failed', { |
| description: errorMessage, |
| duration: 10000, |
| }); |
| } finally { |
| setUploading(false); |
| } |
| }; |
|
|
| return ( |
| <div className="min-h-screen py-12"> |
| <div className="container mx-auto px-4"> |
| <motion.div |
| initial={{ opacity: 0, y: 20 }} |
| animate={{ opacity: 1, y: 0 }} |
| transition={{ duration: 0.5 }} |
| className="max-w-4xl mx-auto" |
| > |
| {/* Header */} |
| <div className="text-center mb-12"> |
| <div className="flex justify-center mb-4"> |
| <div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-blue-600 to-purple-600"> |
| <Sparkles className="h-8 w-8 text-white" /> |
| </div> |
| </div> |
| <h1 className="text-4xl sm:text-5xl font-bold mb-4"> |
| <span className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"> |
| Upload Your Patent |
| </span> |
| </h1> |
| <p className="text-xl text-gray-600 max-w-2xl mx-auto"> |
| Upload a patent PDF to begin the AI-powered analysis process. We'll identify |
| market opportunities and match you with relevant partners. |
| </p> |
| </div> |
| |
| {/* Upload Component */} |
| <PatentUpload onUpload={handleUpload} uploading={uploading} error={error} /> |
| |
| {/* Info Cards */} |
| <div className="grid md:grid-cols-3 gap-6 mt-12"> |
| <Card> |
| <CardHeader> |
| <CardTitle className="text-lg">π File Requirements</CardTitle> |
| </CardHeader> |
| <CardContent> |
| <ul className="text-sm text-gray-600 space-y-2"> |
| <li>β’ PDF format only</li> |
| <li>β’ Maximum 50MB</li> |
| <li>β’ Clear, readable text</li> |
| </ul> |
| </CardContent> |
| </Card> |
| |
| <Card> |
| <CardHeader> |
| <CardTitle className="text-lg">β‘ Processing Time</CardTitle> |
| </CardHeader> |
| <CardContent> |
| <ul className="text-sm text-gray-600 space-y-2"> |
| <li>β’ Patent Analysis: ~30s</li> |
| <li>β’ Market Research: ~1min</li> |
| <li>β’ Partner Matching: ~2min</li> |
| <li>β’ Total: 2-5 minutes</li> |
| </ul> |
| </CardContent> |
| </Card> |
| |
| <Card> |
| <CardHeader> |
| <CardTitle className="text-lg">π― What You'll Get</CardTitle> |
| </CardHeader> |
| <CardContent> |
| <ul className="text-sm text-gray-600 space-y-2"> |
| <li>β’ TRL Assessment</li> |
| <li>β’ Market Opportunities</li> |
| <li>β’ Partner Matches</li> |
| <li>β’ Valorization Brief</li> |
| </ul> |
| </CardContent> |
| </Card> |
| </div> |
| |
| {/* Features List */} |
| <motion.div |
| initial={{ opacity: 0, y: 20 }} |
| animate={{ opacity: 1, y: 0 }} |
| transition={{ duration: 0.5, delay: 0.2 }} |
| className="mt-12" |
| > |
| <Card className="bg-gradient-to-br from-blue-50 to-purple-50 border-blue-200"> |
| <CardContent className="p-8"> |
| <h3 className="text-xl font-semibold mb-4 text-center"> |
| π€ Powered by Multi-Agent AI System |
| </h3> |
| <div className="grid sm:grid-cols-2 gap-4 text-sm text-gray-700"> |
| <div className="flex items-start space-x-2"> |
| <span className="text-blue-600">β</span> |
| <span>PlannerAgent orchestrates the workflow</span> |
| </div> |
| <div className="flex items-start space-x-2"> |
| <span className="text-blue-600">β</span> |
| <span>CriticAgent ensures quality</span> |
| </div> |
| <div className="flex items-start space-x-2"> |
| <span className="text-purple-600">β</span> |
| <span>DocumentAnalysisAgent extracts innovations</span> |
| </div> |
| <div className="flex items-start space-x-2"> |
| <span className="text-purple-600">β</span> |
| <span>MarketAnalysisAgent finds opportunities</span> |
| </div> |
| <div className="flex items-start space-x-2"> |
| <span className="text-green-600">β</span> |
| <span>MatchmakingAgent finds partners</span> |
| </div> |
| <div className="flex items-start space-x-2"> |
| <span className="text-green-600">β</span> |
| <span>OutreachAgent generates brief</span> |
| </div> |
| </div> |
| </CardContent> |
| </Card> |
| </motion.div> |
| </motion.div> |
| </div> |
| </div> |
| ); |
| } |
|
|