import { useState, useCallback } from "react"; import DashboardLayout from "@/components/DashboardLayout"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { trpc } from "@/lib/trpc"; import { Upload as UploadIcon, FileText, Loader2, CheckCircle, AlertCircle } from "lucide-react"; import { toast } from "sonner"; import { useLocation } from "wouter"; export default function Upload() { const [, setLocation] = useLocation(); const [isDragging, setIsDragging] = useState(false); const [uploading, setUploading] = useState(false); const [sourceFileId, setSourceFileId] = useState(null); const uploadMutation = trpc.invoices.upload.useMutation({ onSuccess: (data) => { setSourceFileId(data.sourceFileId); toast.success("Fichier uploadé avec succès"); }, onError: (error) => { toast.error(error.message || "Erreur lors de l'upload"); setUploading(false); }, }); // Poll source file status const { data: sourceFiles } = trpc.sourceFiles.getByIds.useQuery( { ids: sourceFileId ? [sourceFileId] : [] }, { enabled: !!sourceFileId, refetchInterval: (query) => { const data = query.state.data; if (!data || data.length === 0) return false; const file = data[0]; if (!file || file.processingStatus === "completed" || file.processingStatus === "error") { return false; } return 2000; // Poll every 2 seconds }, } ); const sourceFile = sourceFiles && sourceFiles.length > 0 ? sourceFiles[0] : undefined; const handleDragOver = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }, []); const handleDragLeave = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }, []); const handleDrop = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const files = Array.from(e.dataTransfer.files); const pdfFile = files.find((f) => f.type === "application/pdf"); if (!pdfFile) { toast.error("Veuillez sélectionner un fichier PDF"); return; } handleFileUpload(pdfFile); }, []); const handleFileSelect = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; if (file.type !== "application/pdf") { toast.error("Veuillez sélectionner un fichier PDF"); return; } handleFileUpload(file); }; const handleFileUpload = async (file: File) => { setUploading(true); setSourceFileId(null); try { // Convert file to base64 const reader = new FileReader(); reader.onload = async () => { const base64 = (reader.result as string).split(",")[1]; uploadMutation.mutate({ fileName: file.name, fileData: base64!, }); }; reader.readAsDataURL(file); } catch (error) { toast.error("Erreur lors de la lecture du fichier"); setUploading(false); } }; const handleViewInvoices = () => { setLocation("/invoices"); }; return (

Importer des factures

Uploadez un fichier PDF contenant une ou plusieurs factures

Upload de fichier Glissez-déposez un fichier PDF ou cliquez pour sélectionner
{/* Processing status */} {sourceFile && ( Traitement en cours {sourceFile.fileName}
{sourceFile.processingStatus === "processing" && ( <>
Extraction en cours...
{sourceFile.processingProgress}
)} {sourceFile.processingStatus === "completed" && ( <>
Traitement terminé
{sourceFile.totalInvoicesDetected} facture(s) détectée(s)
)} {sourceFile.processingStatus === "error" && ( <>
Erreur de traitement
{sourceFile.processingProgress}
)}
{sourceFile.processingStatus === "completed" && ( )}
)}
); }