From ec17305e16239975390e439a08e902aa34b5fee5 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Mon, 14 Oct 2024 17:46:40 +0700 Subject: [PATCH] Refactor Apply page component to adjust left margin for company information section and simplify pitchDeckSchema validation --- src/app/business/apply/page.tsx | 182 +++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 64 deletions(-) diff --git a/src/app/business/apply/page.tsx b/src/app/business/apply/page.tsx index 3faf2f2..d39381c 100644 --- a/src/app/business/apply/page.tsx +++ b/src/app/business/apply/page.tsx @@ -19,12 +19,59 @@ import { DualOptionSelector } from "@/components/dualSelector"; import { MultipleOptionSelector } from "@/components/multipleSelector"; export default function Apply() { + const [industry, setIndustry] = useState([]); + const [isInUS, setIsInUS] = useState(""); + const [isForSale, setIsForSale] = useState(""); + const [isGenerating, setIsGenerating] = useState(""); + const [businessPitch, setBusinessPitch] = useState("text"); + const [projectType, setProjectType] = useState([]); + const [projectPitch, setProjectPitch] = useState("text"); + const [applyProject, setApplyProject] = useState(false); + const [selectedImages, setSelectedImages] = useState([]); + const [businessPitchFile, setBusinessPitchFile] = useState(""); const MAX_FILE_SIZE = 5000000; const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png"]; - const pitchDeckSchema = z.union([ - z.string().url("Pitch deck must be a valid URL."), - z.object({}), - ]); + const createPitchDeckSchema = (inputType: string) => { + if (inputType === "text") { + return z + .string() + .url("Pitch deck must be a valid URL.") + .refine((url) => url.endsWith(".md"), { + message: "Pitch deck URL must link to a markdown file (.md).", + }); + } else if (inputType === "file") { + return z + .custom( + (val) => { + // Confirm val is a File object + return val instanceof File; // Ensure it is a File instance + }, + { + message: "Input must be a file.", + } + ) + .refine((file) => file.size < MAX_FILE_SIZE, { + message: "File can't be bigger than 5MB.", + }) + .refine((file) => file.name.endsWith(".md"), { + message: "File must be a markdown file (.md).", + }); + } else { + return z.any(); // avoid undefined + } + }; + const projectLogoSchema = z + .custom( + (val) => val && typeof val === "object" && "size" in val && "type" in val, + { message: "Input must be a file." } + ) + .refine((file) => file.size < MAX_FILE_SIZE, { + message: "File can't be bigger than 5MB.", + }) + .refine((file) => ACCEPTED_IMAGE_TYPES.includes(file.type), { + message: "File format must be either jpg, jpeg, or png.", + }); + const projectFormSchema = z.object({ projectName: z.string().min(5, { message: "Project name must be at least 5 characters.", @@ -39,33 +86,26 @@ export default function Apply() { .min(10, { message: "Short description must be at least 10 characters.", }), - projectPitchDeck: pitchDeckSchema, - projectLogo: z - .instanceof(File) - .refine((file) => ACCEPTED_IMAGE_TYPES.includes(file.type), { - message: "Only .jpg, .jpeg, and .png formats are supported.", - }) - .refine((file) => file.size <= MAX_FILE_SIZE, { - message: "Max image size is 5MB.", - }), + projectPitchDeck: createPitchDeckSchema(projectPitch), + projectLogo: projectLogoSchema, - projectPhotos: z - .array( - z.object({ - file: z - .any() - .refine( - (file) => file?.size <= MAX_FILE_SIZE, - `Max image size is 5MB.` - ) - .refine( - (file) => ACCEPTED_IMAGE_TYPES.includes(file?.type), - "Only .jpg, .jpeg, and .png formats are supported." - ), - }) - ) - .min(1, "You must upload at least one photo.") - .max(10, "You can upload a maximum of 10 photos."), + // projectPhotos: z + // .array( + // z.object({ + // file: z + // .any() + // .refine( + // (file) => file?.size <= MAX_FILE_SIZE, + // `Max image size is 5MB.` + // ) + // .refine( + // (file) => ACCEPTED_IMAGE_TYPES.includes(file?.type), + // "Only .jpg, .jpeg, and .png formats are supported." + // ), + // }) + // ) + // .min(1, "You must upload at least one photo.") + // .max(10, "You can upload a maximum of 10 photos."), minInvest: z .number({ required_error: "Minimum invesment must be a number.", @@ -132,23 +172,12 @@ export default function Apply() { communitySize: z.string({ required_error: "Please select one of the option", }), - businessPitchDeck: pitchDeckSchema, + businessPitchDeck: createPitchDeckSchema(businessPitch), }); let supabase = createSupabaseClient(); - - const [industry, setIndustry] = useState([]); - const [isInUS, setIsInUS] = useState(""); - const [isForSale, setIsForSale] = useState(""); - const [isGenerating, setIsGenerating] = useState(""); - const [businessPitch, setBusinessPitch] = useState(""); - const [projectType, setProjectType] = useState([]); - const [projectPitch, setProjectPitch] = useState(""); - const [applyProject, setApplyProject] = useState(false); - const [selectedImages, setSelectedImages] = useState([]); const { register, handleSubmit, - setValue, setValue: setValueBusiness, formState: { errors: errorsBusiness }, } = useForm({ @@ -243,7 +272,7 @@ export default function Apply() { const fetchIndustry = async () => { let { data: BusinessType, error } = await supabase - .from("BusinessType") + .from("business_type") .select("value"); if (error) { @@ -257,6 +286,9 @@ export default function Apply() { }; const onSubmitSingleForm = (data: any) => { + const pitchDeckSchema = createPitchDeckSchema(businessPitch); // Ensure you create the schema dynamically + pitchDeckSchema.parse(data.businessPitchDeck); // Validate the specific field + console.log("Valid form input:", data); alert(JSON.stringify(data)); }; @@ -278,7 +310,7 @@ export default function Apply() { }; const fetchProjectType = async () => { let { data: ProjectType, error } = await supabase - .from("ProjectType") + .from("project_type") .select("value"); if (error) { @@ -503,9 +535,16 @@ export default function Apply() { : "https:// " } accept={businessPitch === "file" ? ".md" : undefined} - {...register("businessPitchDeck", { required: true })} + {...(businessPitch === "text" + ? register("businessPitchDeck", { required: true }) + : { + onChange: (e) => { + const file = e.target.files?.[0]; + setValueBusiness("businessPitchDeck", file); + setBusinessPitchFile(file?.name || ""); + }, + })} /> - Your pitch deck and other application info will be used for{" "}
@@ -519,10 +558,25 @@ export default function Apply() {

+ {/* box to show file name */} + {businessPitchFile && ( +
+ 1. {businessPitchFile} + +
+ )} - {errorsBusiness.pitchDeck && ( + {errorsBusiness.businessPitchDeck && (

- {errorsBusiness.pitchDeck.message as string} + {errorsBusiness.businessPitchDeck.message as string}

)} - {/* project's name */}