diff --git a/src/app/api/upload/due-considerations/route.ts b/src/app/api/upload/due-considerations/route.ts index 9eb5872..46de42f 100644 --- a/src/app/api/upload/due-considerations/route.ts +++ b/src/app/api/upload/due-considerations/route.ts @@ -27,9 +27,9 @@ export async function POST(request: NextRequest) { try { const s3 = new S3({ signatureVersion: "v4", - region: process.env.PRESIGN_AWS_REGION, - accessKeyId: process.env.PRSIGN_AWS_ACCESS_KEY, - secretAccessKey: process.env.PRESIGN_AWS_SECRET_KEY, + region: process.env.DUE_CONSIDERATIONS_AWS_REGION, + accessKeyId: process.env.DUE_CONSIDERATIONS_AWS_ACCESS_KEY, + secretAccessKey: process.env.DUE_CONSIDERATIONS_AWS_SECRET_KEY, }); const { files } = validatedBody; @@ -37,7 +37,7 @@ export async function POST(request: NextRequest) { const preSignedUrls = await Promise.all( files.map(async (file: any) => { return s3.getSignedUrlPromise("putObject", { - Bucket: process.env.RETOFIT_PLAN_INPUT_BUCKET_NAME, + Bucket: process.env.DUE_CONSIDERATIONS_BUCKET, Key: file.fileKey, ContentType: file.contentType, Expires: 5 * 60, diff --git a/src/app/due-considerations/page.tsx b/src/app/due-considerations/page.tsx index 6b8d81f..8a31150 100644 --- a/src/app/due-considerations/page.tsx +++ b/src/app/due-considerations/page.tsx @@ -1,36 +1,106 @@ "use client"; -import { useState } from "react"; +import { useMemo, useState } from "react"; import { SelectFolder } from "../components/due-considerations/SelectFolder"; import { Button } from "../shadcn_components/ui/button"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import { useMutation } from "@tanstack/react-query"; -async function uploadDueConsiderationFiles(files: File[]) { - // Steps: - // 1) For each file, generate a presigned url - // 2) For each file, upload the file to the presigned url - // 3) Trigger the due considerations process - // 4) Profit???? +function generateDueConsiderationsS3Folder(userId: string) { + const timestamp = new Date().toISOString().replace(/[:.-]/g, ""); + const key = `${userId}/${timestamp}/`; + return key; +} - // Step 1: Generate presigned URLs - const response = await fetch("/path/to/your/api/endpoint", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - files: files.map((file) => ({ - fileKey: "your/folder/structure/" + file.name, // replace with your actual folder structure - contentType: file.type, - })), - }), +const useUploadFiles = ({ + dueConsiderationsFiles, + folderKey, +}: { + dueConsiderationsFiles: File[]; + folderKey: string; +}) => { + const { mutate: mutateUploadFiles, isLoading: isUploadLoading } = useMutation( + uploadFilesToS3, + { + onSuccess: () => { + console.log("Trigger the due considerations process"); + // You can replace the above log with the actual API call when it's implemented + }, + onError: (error) => { + console.error(error); + }, + } + ); + + const { mutate, isLoading: isGeneratingUrlLoading } = useMutation( + generatePresignedUrls, + { + onSuccess: (data) => { + try { + const response = mutateUploadFiles({ + presignedUrls: data.urls, + files: dueConsiderationsFiles, + }); + return response; + } catch (error) { + console.error(error); + } + }, + onError: (error) => { + console.error(error); + }, + } + ); + + const handleUpload = () => { + mutate({ folderKey: folderKey, files: dueConsiderationsFiles }); + // Navigate to a loading or success page if needed + }; + + return { + handleUpload, + isGeneratingUrlLoading, + isUploadLoading, + }; +}; + +async function generatePresignedUrls({ + folderKey, + files, +}: { + folderKey: string; + files: File[]; +}) { + const body = JSON.stringify({ + files: files.map((file) => ({ + fileKey: folderKey + file.name, + contentType: file.type, + })), }); - const { urls } = await response.json(); + const presignedResponse = await fetch("/api/upload/due-considerations", { + method: "POST", + body: body, + }); - // Step 2: Upload files to S3 + if (!presignedResponse.ok) { + throw new Error("Network response was not ok"); + } + const presignedUrls = await presignedResponse.json(); + return presignedUrls; +} + +async function uploadFilesToS3({ + presignedUrls, + files, +}: { + presignedUrls: string[]; + files: File[]; +}) { await Promise.all( files.map((file, index) => { - return fetch(urls[index], { + return fetch(presignedUrls[index], { method: "PUT", headers: { "Content-Type": file.type, @@ -42,10 +112,22 @@ async function uploadDueConsiderationFiles(files: File[]) { } export default function DueConsiderationsHome() { - const [files, setFile] = useState([]); + const [dueConsiderationsFiles, setDueConsiderationFile] = useState( + [] + ); const [buttonDisabled, setButtonDisabled] = useState(true); const [uploadMessage, setUploadMessage] = useState(""); + const session = useSession(); + const userId = String(session.data?.user.dbId); + const folderKey = useMemo( + () => generateDueConsiderationsS3Folder(userId), + [userId] + ); + + const { handleUpload, isGeneratingUrlLoading, isUploadLoading } = + useUploadFiles({ dueConsiderationsFiles, folderKey }); + function handleOnChange(e: React.ChangeEvent) { if (e.target.files && e.target.files.length === 3) { const filesArray = Array.from(e.target.files); @@ -58,7 +140,7 @@ export default function DueConsiderationsHome() { extensions.includes("pdf") && extensions.includes("docx") ) { - setFile(files); + setDueConsiderationFile(filesArray); setButtonDisabled(false); setUploadMessage(""); } else { @@ -71,10 +153,6 @@ export default function DueConsiderationsHome() { } } - function onUpload() { - // We want to upload the files to s3 via a presigned link - } - return (
@@ -97,7 +175,7 @@ export default function DueConsiderationsHome() {