Completed due considerations file upload

This commit is contained in:
Khalim Conn-Kowlessar 2023-09-24 19:11:26 +01:00
parent 93ea63930d
commit 3a4aa6ce49
2 changed files with 111 additions and 33 deletions

View file

@ -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,

View file

@ -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<File[]>([]);
const [dueConsiderationsFiles, setDueConsiderationFile] = useState<File[]>(
[]
);
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<HTMLInputElement>) {
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 (
<div className="flex flex-col items-center mt-20 tracking-wider leading-loose">
<div className="text-center">
@ -97,7 +175,7 @@ export default function DueConsiderationsHome() {
<Button
disabled={buttonDisabled}
className="bg-brandblue hover:bg-hoverblue"
onClick={onUpload}
onClick={handleUpload}
>
Upload
</Button>