mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-19 05:54:06 +01:00
Refactor uploadFile function to improve folder management and error handling
This commit is contained in:
parent
87f8e13f37
commit
d32b8c5845
@ -1,48 +1,91 @@
|
|||||||
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
|
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
|
|
||||||
|
const supabase = createSupabaseClient();
|
||||||
|
|
||||||
|
async function checkFolderExists(bucketName: string, filePath: string) {
|
||||||
|
const { data, error } = await supabase.storage
|
||||||
|
.from(bucketName)
|
||||||
|
.list(filePath);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error(`Error checking for folder: ${error.message}`);
|
||||||
|
}
|
||||||
|
return { folderData: data, folderError: error };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function clearFolder(
|
||||||
|
bucketName: string,
|
||||||
|
folderData: any[],
|
||||||
|
filePath: string
|
||||||
|
) {
|
||||||
|
const errors: string[] = [];
|
||||||
|
|
||||||
|
for (const fileItem of folderData) {
|
||||||
|
const { error } = await supabase.storage
|
||||||
|
.from(bucketName)
|
||||||
|
.remove([`${filePath}/${fileItem.name}`]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
errors.push(`Error removing file (${fileItem.name}): ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadToFolder(
|
||||||
|
bucketName: string,
|
||||||
|
filePath: string,
|
||||||
|
file: File
|
||||||
|
) {
|
||||||
|
const { data, error } = await supabase.storage
|
||||||
|
.from(bucketName)
|
||||||
|
.upload(filePath, file, { upsert: true });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error(`Error uploading file: ${error.message}`);
|
||||||
|
}
|
||||||
|
return { uploadData: data, uploadError: error };
|
||||||
|
}
|
||||||
|
|
||||||
export async function uploadFile(
|
export async function uploadFile(
|
||||||
file: File,
|
file: File,
|
||||||
bucketName: string,
|
bucketName: string,
|
||||||
filePath: string
|
filePath: string
|
||||||
) {
|
) {
|
||||||
const supabase = createSupabaseClient();
|
const errorMessages: string[] = [];
|
||||||
let errorMessages: string[] = [];
|
|
||||||
|
|
||||||
// check if the folder exists
|
// check if the folder exists
|
||||||
const { data: folderData, error: folderError } = await supabase.storage
|
const { folderData, folderError } = await checkFolderExists(
|
||||||
.from(bucketName)
|
bucketName,
|
||||||
.list(filePath);
|
filePath
|
||||||
|
);
|
||||||
if (folderError) {
|
if (folderError) {
|
||||||
errorMessages.push(`Error checking for folder: ${folderError.message}`);
|
errorMessages.push(`Error checking for folder: ${folderError.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the folder exists, clear the folder
|
// clear the folder if it exists
|
||||||
if (folderData && folderData.length > 0) {
|
if (folderData && folderData.length > 0) {
|
||||||
for (const fileItem of folderData) {
|
const clearErrors = await clearFolder(bucketName, folderData, filePath);
|
||||||
const { error: removeError } = await supabase.storage
|
errorMessages.push(...clearErrors);
|
||||||
.from(bucketName)
|
|
||||||
.remove([`${filePath}/${fileItem.name}`]);
|
|
||||||
|
|
||||||
if (removeError) {
|
|
||||||
errorMessages.push(
|
|
||||||
`Error removing file (${fileItem.name}): ${removeError.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// upload the new file to the folder (if no folderError)
|
// upload the new file if there were no previous errors
|
||||||
|
let uploadData = null;
|
||||||
if (errorMessages.length === 0) {
|
if (errorMessages.length === 0) {
|
||||||
const { error: uploadError } = await supabase.storage
|
const { uploadData: data, uploadError } = await uploadToFolder(
|
||||||
.from(bucketName)
|
bucketName,
|
||||||
.upload(filePath, file);
|
filePath,
|
||||||
|
file
|
||||||
|
);
|
||||||
|
uploadData = data;
|
||||||
|
|
||||||
if (uploadError) {
|
if (uploadError) {
|
||||||
errorMessages.push(`Error uploading file: ${uploadError.message}`);
|
errorMessages.push(`Error uploading file: ${uploadError.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorMessages.length > 0) {
|
if (errorMessages.length > 0) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: "error",
|
icon: "error",
|
||||||
@ -50,7 +93,8 @@ export async function uploadFile(
|
|||||||
html: errorMessages.join("<br>"),
|
html: errorMessages.join("<br>"),
|
||||||
confirmButtonColor: "red",
|
confirmButtonColor: "red",
|
||||||
});
|
});
|
||||||
return false;
|
return { success: false, errors: errorMessages, data: null };
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
return { success: true, errors: null, data: uploadData };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export default function ApplyProject() {
|
|||||||
const onSubmit: SubmitHandler<projectSchema> = async (data) => {
|
const onSubmit: SubmitHandler<projectSchema> = async (data) => {
|
||||||
alert("มาแน้ววว");
|
alert("มาแน้ววว");
|
||||||
await sendApplication(data);
|
await sendApplication(data);
|
||||||
console.table(data);
|
// console.table(data);
|
||||||
// console.log(typeof data["projectPhotos"], data["projectPhotos"]);
|
// console.log(typeof data["projectPhotos"], data["projectPhotos"]);
|
||||||
};
|
};
|
||||||
const saveApplicationData = async (recvData: any, userId: string) => {
|
const saveApplicationData = async (recvData: any, userId: string) => {
|
||||||
@ -41,15 +41,19 @@ export default function ApplyProject() {
|
|||||||
};
|
};
|
||||||
const saveTags = async (tags: string[], projectId: string) => {
|
const saveTags = async (tags: string[], projectId: string) => {
|
||||||
const tagPromises = tags.map(async (tag) => {
|
const tagPromises = tags.map(async (tag) => {
|
||||||
const { data, error } = await supabase
|
const response = await supabase
|
||||||
.from("project_application_tag")
|
.from("project_application_tag")
|
||||||
.insert([{ tag_id: tag, project_id: projectId }])
|
.insert([{ tag_id: tag, item_id: projectId }])
|
||||||
.select();
|
.select();
|
||||||
|
|
||||||
return { data, error };
|
// console.log("Insert response for tag:", tag, response);
|
||||||
|
|
||||||
|
return response;
|
||||||
});
|
});
|
||||||
|
|
||||||
const results = await Promise.all(tagPromises);
|
const results = await Promise.all(tagPromises);
|
||||||
|
|
||||||
|
// Collect errors
|
||||||
const errors = results
|
const errors = results
|
||||||
.filter((result) => result.error)
|
.filter((result) => result.error)
|
||||||
.map((result) => result.error);
|
.map((result) => result.error);
|
||||||
@ -69,7 +73,7 @@ export default function ApplyProject() {
|
|||||||
|
|
||||||
return await uploadFile(
|
return await uploadFile(
|
||||||
file,
|
file,
|
||||||
"BUCKET_PITCH_APPLICATION_NAME",
|
BUCKET_PITCH_APPLICATION_NAME,
|
||||||
`${userId}/${projectId}/pitches/${file.name}`
|
`${userId}/${projectId}/pitches/${file.name}`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -80,29 +84,44 @@ export default function ApplyProject() {
|
|||||||
userId: string,
|
userId: string,
|
||||||
projectId: string
|
projectId: string
|
||||||
) => {
|
) => {
|
||||||
|
const uploadResults: { logo?: any; photos: any[] } = { photos: [] };
|
||||||
|
|
||||||
|
// upload logo
|
||||||
if (logoFile) {
|
if (logoFile) {
|
||||||
const uploadLogoSuccess = await uploadFile(
|
const logoResult = await uploadFile(
|
||||||
logoFile,
|
logoFile,
|
||||||
"BUCKET_PITCH_APPLICATION_NAME",
|
BUCKET_PITCH_APPLICATION_NAME,
|
||||||
`${userId}/${projectId}/logo/${logoFile.name}`
|
`${userId}/${projectId}/logo/${logoFile.name}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!uploadLogoSuccess) {
|
if (!logoResult.success) {
|
||||||
console.error("Error uploading logo.");
|
console.error("Error uploading logo:", logoResult.errors);
|
||||||
return false;
|
return { success: false, logo: logoResult, photos: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uploadResults.logo = logoResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upload each photo
|
||||||
const uploadPhotoPromises = photos.map((image) =>
|
const uploadPhotoPromises = photos.map((image) =>
|
||||||
uploadFile(
|
uploadFile(
|
||||||
image,
|
image,
|
||||||
"BUCKET_PITCH_APPLICATION_NAME",
|
BUCKET_PITCH_APPLICATION_NAME,
|
||||||
`${userId}/${projectId}/photos/${image.name}`
|
`${userId}/${projectId}/photos/${image.name}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const photoResults = await Promise.all(uploadPhotoPromises);
|
const photoResults = await Promise.all(uploadPhotoPromises);
|
||||||
return photoResults.every(Boolean); // Checks if all photos uploaded successfully
|
uploadResults.photos = photoResults;
|
||||||
|
|
||||||
|
// check if all uploads were successful
|
||||||
|
const allUploadsSuccessful = photoResults.every((result) => result.success);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: allUploadsSuccessful,
|
||||||
|
logo: uploadResults.logo,
|
||||||
|
photos: uploadResults.photos,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const displayAlert = (error: any) => {
|
const displayAlert = (error: any) => {
|
||||||
@ -114,7 +133,7 @@ export default function ApplyProject() {
|
|||||||
confirmButtonColor: error == null ? "green" : "red",
|
confirmButtonColor: error == null ? "green" : "red",
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
window.location.href = "/";
|
// window.location.href = "/";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -136,6 +155,11 @@ export default function ApplyProject() {
|
|||||||
displayAlert(error);
|
displayAlert(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const tagError = saveTags(recvData["tag"], projectId);
|
||||||
|
// if (tagError) {
|
||||||
|
// displayAlert(tagError);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
// upload pitch file if it’s a file
|
// upload pitch file if it’s a file
|
||||||
if (typeof recvData["projectPitchDeck"] === "object") {
|
if (typeof recvData["projectPitchDeck"] === "object") {
|
||||||
@ -153,18 +177,48 @@ export default function ApplyProject() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// upload logo and photos
|
// upload logo and photos
|
||||||
const uploadMediaSuccess = await uploadLogoAndPhotos(
|
const { success, logo, photos } = await uploadLogoAndPhotos(
|
||||||
recvData["projectLogo"],
|
recvData["projectLogo"],
|
||||||
recvData["projectPhotos"],
|
recvData["projectPhotos"],
|
||||||
user.id,
|
user.id,
|
||||||
projectId
|
projectId
|
||||||
);
|
);
|
||||||
|
if (!success) {
|
||||||
if (!uploadMediaSuccess) {
|
|
||||||
console.error("Error uploading media files.");
|
console.error("Error uploading media files.");
|
||||||
}
|
}
|
||||||
|
const folderPath = photos[0].data.path;
|
||||||
|
const lastSlashIndex = folderPath.lastIndexOf("/");
|
||||||
|
const photosPath = folderPath.substring(0, lastSlashIndex);
|
||||||
|
const logoURL = getPublicURL(
|
||||||
|
logo.data.path,
|
||||||
|
BUCKET_PITCH_APPLICATION_NAME
|
||||||
|
)?.publicUrl;
|
||||||
|
const photosURL = getPublicURL(
|
||||||
|
photosPath,
|
||||||
|
BUCKET_PITCH_APPLICATION_NAME
|
||||||
|
)?.publicUrl;
|
||||||
|
|
||||||
|
updateImageURL(logoURL, "project_logo", projectId);
|
||||||
|
// console.log(logoURL, photosUrl);
|
||||||
displayAlert(error);
|
displayAlert(error);
|
||||||
};
|
};
|
||||||
|
const updateImageURL = async (
|
||||||
|
url: string,
|
||||||
|
columnName: string,
|
||||||
|
projectId: number
|
||||||
|
) => {
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("project_application")
|
||||||
|
.update({ [columnName]: url })
|
||||||
|
.eq("id", projectId)
|
||||||
|
.select();
|
||||||
|
console.table(data);
|
||||||
|
};
|
||||||
|
const getPublicURL = (path: string, bucketName: string) => {
|
||||||
|
const { data } = supabase.storage.from(bucketName).getPublicUrl(path);
|
||||||
|
// console.table(data);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="grid grid-flow-row auto-rows-max w-full h-52 md:h-92 bg-gray-2s00 dark:bg-gray-800 p-5">
|
<div className="grid grid-flow-row auto-rows-max w-full h-52 md:h-92 bg-gray-2s00 dark:bg-gray-800 p-5">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user