118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
"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>
|
|
);
|
|
}
|