"use client"; import { createClient } from "@/utils/supabase/client"; import { CloudUpload, LoaderCircle } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { SSE } from "sse.js"; export default function UploadZone({ user }: { user?: { id: string } }) { const supabase = createClient(); const [uploading, setUploading] = useState(false); const [status, setStatus] = useState(""); const onUpload = async (file: File) => { setUploading(true); setStatus("Uploading..."); const { data, error } = await supabase.auth.getSession(); if (error) { toast.error("Failed to get user session."); setUploading(false); return; } const body = new FormData(); body.append("file", file); body.append("access_token", data.session?.access_token || ""); body.append("refresh_token", data.session?.refresh_token || ""); const edgeFunctionUrl = `${process.env.NEXT_PUBLIC_SUPABASE_URL}/functions/v1/process-document`; // Start listening to the SSE stream const eventSource = new SSE(edgeFunctionUrl, { payload: body, headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, Authorization: `Bearer ${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY}`, // "Content-Type": "multipart/form-data", }, }); eventSource.addEventListener("status", (event) => { const data = JSON.parse(event.data); console.log("Status Event:", data); supabase.auth.setSession; setStatus(data.message); }); eventSource.addEventListener("error", (event) => { console.error("SSE Error:", event); toast.error("An error occurred while processing the document.", { description: event.data || "Unknown error", }); setUploading(false); eventSource.close(); }); eventSource.addEventListener("complete", (event) => { const data = JSON.parse(event.data); console.log("Processing Complete:", data); toast.success("Document processing complete!"); setUploading(false); eventSource.close(); }); // // Invoke the serverless function // supabase.functions.invoke("process-document", { // body, // method: "POST", // }); toast.info( "Document is being processed in the background. You will be notified when it's ready." ); }; return ( <div className="flex flex-1 flex-col gap-4 px-4 py-10"> <div className="flex items-center justify-center w-full"> <label htmlFor="dropzone-file" className="flex flex-col items-center justify-center w-full h-64 border-2 border-muted border-dashed rounded-lg cursor-pointer bg-muted/50" > {uploading ? ( <div className="flex flex-col items-center justify-center pt-5 pb-5"> <LoaderCircle className="w-10 h-10 mb-4 text-slate-400 animate-spin" /> <p className="mb-2 text-sm text-slate-400">{status}</p> </div> ) : ( <> <div className="flex flex-col items-center justify-center pt-5 pb-5"> <CloudUpload className="w-10 h-10 mb-4 text-slate-400" /> <p className="mb-2 text-sm text-slate-400"> <span className="font-semibold">Click to upload</span> or drag and drop </p> </div> </> )} <input id="dropzone-file" type="file" className="hidden" accept="application/pdf" onChange={(e) => { const file = e.target.files?.[0]; if (file) { onUpload(file); } }} /> </label> </div> </div> ); }