From 04fc8a33abbe5e81428f846bbe00ec3873971ac3 Mon Sep 17 00:00:00 2001 From: Sosokker Date: Mon, 11 Nov 2024 03:04:12 +0700 Subject: [PATCH] refactor: extract function from project apply page --- src/app/project/apply/displayAlert.ts | 20 +++ src/app/project/apply/fileUploadService.ts | 6 + src/app/project/apply/page.tsx | 164 +++------------------ src/app/project/apply/projectService.ts | 38 +++++ 4 files changed, 84 insertions(+), 144 deletions(-) create mode 100644 src/app/project/apply/displayAlert.ts create mode 100644 src/app/project/apply/fileUploadService.ts create mode 100644 src/app/project/apply/projectService.ts diff --git a/src/app/project/apply/displayAlert.ts b/src/app/project/apply/displayAlert.ts new file mode 100644 index 0000000..29e2a41 --- /dev/null +++ b/src/app/project/apply/displayAlert.ts @@ -0,0 +1,20 @@ +import Swal from "sweetalert2"; +import toast from "react-hot-toast"; + +export const displayAlert = (error: any) => { + Swal.fire({ + icon: error == null ? "success" : "error", + title: error == null ? "Success" : `Error: ${error.code}`, + text: error == null ? "Your application has been submitted" : error.message, + confirmButtonColor: error == null ? "green" : "red", + allowOutsideClick: false, + }).then((result) => { + if (result.isConfirmed) { + if (error) { + toast.error("Error sending Project Application"); + } else { + toast.success("Your application has been submitted!"); + } + } + }); +}; diff --git a/src/app/project/apply/fileUploadService.ts b/src/app/project/apply/fileUploadService.ts new file mode 100644 index 0000000..3129909 --- /dev/null +++ b/src/app/project/apply/fileUploadService.ts @@ -0,0 +1,6 @@ +import { uploadFile } from "@/app/api/generalApi"; + +export const uploadFiles = async (files: File[], path: string) => { + const results = await Promise.all(files.map((file) => uploadFile(file, "project-application", path + file.name))); + return results; +}; diff --git a/src/app/project/apply/page.tsx b/src/app/project/apply/page.tsx index 6d84278..71cd0da 100644 --- a/src/app/project/apply/page.tsx +++ b/src/app/project/apply/page.tsx @@ -1,31 +1,25 @@ "use client"; -import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; +import { saveApplicationData, saveTags } from "./projectService"; +import { uploadFiles } from "./fileUploadService"; +import { displayAlert } from "./displayAlert"; import ProjectForm from "./ProjectForm"; -import { projectFormSchema } from "@/types/schemas/application.schema"; -import { z } from "zod"; -import { SubmitHandler } from "react-hook-form"; -import Swal from "sweetalert2"; -import { uploadFile } from "@/app/api/generalApi"; -import { useRouter } from "next/navigation"; -import toast from "react-hot-toast"; -import { useUserRole } from "@/hooks/useUserRole"; import { LegacyLoader } from "@/components/loading/LegacyLoader"; - -type projectSchema = z.infer; -const supabase = createSupabaseClient(); -const BUCKET_PITCH_APPLICATION_NAME = "project-application"; +import toast from "react-hot-toast"; +import { useRouter } from "next/navigation"; +import { useUserRole } from "@/hooks/useUserRole"; export default function ApplyProject() { const router = useRouter(); const { data, session, isLoading, error } = useUserRole(); - const userId = session?.user.id; const role: string = data?.role; if (isLoading || !session) { return ; } + const userId = session!.user.id; + if (error) { throw error; } @@ -36,139 +30,21 @@ export default function ApplyProject() { return; } - const displayAlert = (error: any) => { - Swal.fire({ - icon: error == null ? "success" : "error", - title: error == null ? "Success" : `Error: ${error.code}`, - text: error == null ? "Your application has been submitted" : error.message, - confirmButtonColor: error == null ? "green" : "red", - allowOutsideClick: false, - }).then((result) => { - if (result.isConfirmed) { - toast.error("Error sending Project Application"); - router.push("/"); + const sendApplication = async (data: any) => { + try { + const { projectId, error } = await saveApplicationData(data, userId); + if (error) { + displayAlert(error); + return; } - }); - }; - const saveApplicationData = async (recvData: any) => { - const pitchType = typeof recvData["projectPitchDeck"]; - const { data: projectData, error: projectError } = await supabase - .from("project_application") - .insert([ - { - user_id: userId, - pitch_deck_url: pitchType === "string" ? recvData["projectPitchDeck"] : "", - target_investment: recvData["targetInvest"], - deadline: recvData["deadline"], - project_name: recvData["projectName"], - project_type_id: recvData["projectType"], - short_description: recvData["shortDescription"], - min_investment: recvData["minInvest"], - }, - ]) - .select(); - - return { projectId: projectData?.[0]?.id, error: projectError }; - }; - - const saveTags = async (tags: string[], projectId: string) => { - const tagPromises = tags.map(async (tag) => { - const response = await supabase - .from("project_application_tag") - .insert([{ tag_id: tag, item_id: projectId }]) - .select(); - return response; - }); - - const results = await Promise.all(tagPromises); - const errors = results.filter((result) => result.error).map((result) => result.error); - - return { errors }; - }; - - const uploadPitchFile = async (file: File, projectId: string) => { - if (!file || !userId) return false; - - return await uploadFile(file, BUCKET_PITCH_APPLICATION_NAME, `${userId}/${projectId}/pitches/${file.name}`); - }; - - const uploadLogoAndPhotos = async (logoFile: File, photos: File[], projectId: string) => { - const uploadResults: { logo?: any; photos: any[] } = { photos: [] }; - - if (logoFile) { - const logoResult = await uploadFile( - logoFile, - BUCKET_PITCH_APPLICATION_NAME, - `${userId}/${projectId}/logo/${logoFile.name}` - ); - if (!logoResult.success) return { success: false, logo: logoResult, photos: [] }; - uploadResults.logo = logoResult; - } - - const uploadPhotoPromises = photos.map((image) => - uploadFile(image, BUCKET_PITCH_APPLICATION_NAME, `${userId}/${projectId}/photos/${image.name}`) - ); - - const photoResults = await Promise.all(uploadPhotoPromises); - uploadResults.photos = photoResults; - const allUploadsSuccessful = photoResults.every((result) => result.success); - - return { success: allUploadsSuccessful, logo: uploadResults.logo, photos: uploadResults.photos }; - }; - - const updateImageURL = async (url: string | string[], columnName: string, projectId: number) => { - const { error } = await supabase - .from("project_application") - .update({ [columnName]: url }) - .eq("id", projectId); - if (error) toast.error(error.message); - }; - - const getPrivateURL = async (path: string, bucketName: string) => { - const { data } = await supabase.storage.from(bucketName).createSignedUrl(path, 31560000); - return data; - }; - - const sendApplication = async (recvData: any) => { - const { projectId, error } = await saveApplicationData(recvData); - if (error) { + await saveTags(data["tag"], projectId); + await uploadFiles(data["projectPhotos"], `${userId}/${projectId}/photos/`); + displayAlert(null); + router.push("/"); + } catch (error) { displayAlert(error); - return; } - - await saveTags(recvData["tag"], projectId); - - if (typeof recvData["projectPitchDeck"] === "object") { - await uploadPitchFile(recvData["projectPitchDeck"], projectId); - } - - const { success, logo, photos } = await uploadLogoAndPhotos( - recvData["projectLogo"], - recvData["projectPhotos"], - projectId - ); - if (!success) toast.error("Error uploading media files."); - - const logoURL = await getPrivateURL(logo.data.path, BUCKET_PITCH_APPLICATION_NAME); - let photoURLsArray: string[] = []; - const photoURLPromises = photos.map(async (item) => { - const photoURL = await getPrivateURL(item.data.path, BUCKET_PITCH_APPLICATION_NAME); - if (photoURL?.signedUrl) photoURLsArray.push(photoURL.signedUrl); - }); - await Promise.all(photoURLPromises); - - if (logoURL?.signedUrl) await updateImageURL(logoURL.signedUrl, "project_logo", projectId); - await updateImageURL(photoURLsArray, "project_photos", projectId); - - if (error) { - displayAlert(error); - router.push("/project/apply"); - } - }; - - const onSubmit: SubmitHandler = async (data) => { - await sendApplication(data); }; return ( @@ -187,7 +63,7 @@ export default function ApplyProject() {
- +
); diff --git a/src/app/project/apply/projectService.ts b/src/app/project/apply/projectService.ts new file mode 100644 index 0000000..d45ebe1 --- /dev/null +++ b/src/app/project/apply/projectService.ts @@ -0,0 +1,38 @@ +import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; + +const supabase = createSupabaseClient(); + +export const saveApplicationData = async (data: any, userId: string) => { + const pitchType = typeof data["projectPitchDeck"]; + const { data: projectData, error } = await supabase + .from("project_application") + .insert([ + { + user_id: userId, + pitch_deck_url: pitchType === "string" ? data["projectPitchDeck"] : "", + target_investment: data["targetInvest"], + deadline: data["deadline"], + project_name: data["projectName"], + project_type_id: data["projectType"], + short_description: data["shortDescription"], + min_investment: data["minInvest"], + }, + ]) + .select(); + + return { projectId: projectData?.[0]?.id, error }; +}; + +export const saveTags = async (tags: string[], projectId: string) => { + const tagPromises = tags.map(async (tag) => { + const response = await supabase + .from("project_application_tag") + .insert([{ tag_id: tag, item_id: projectId }]) + .select(); + return response; + }); + + const results = await Promise.all(tagPromises); + const errors = results.filter((result) => result.error).map((result) => result.error); + return { errors }; +};