diff --git a/src/components/BusinessForm.tsx b/src/components/BusinessForm.tsx index 0610cf0..f4686fb 100644 --- a/src/components/BusinessForm.tsx +++ b/src/components/BusinessForm.tsx @@ -28,8 +28,7 @@ type businessSchema = z.infer; interface BusinessFormProps { industry: string[]; - handleSubmit: SubmitHandler; - onSubmit: () => void; + onSubmit: SubmitHandler; } const BusinessForm = ({ onSubmit, @@ -53,7 +52,12 @@ const BusinessForm = ({ return (
- + + )} + className="space-y-8" + >

About your company

@@ -358,6 +362,12 @@ const BusinessForm = ({ )} /> */} +

diff --git a/src/types/schemas/application.schema.ts b/src/types/schemas/application.schema.ts index 72985a3..2b4529a 100644 --- a/src/types/schemas/application.schema.ts +++ b/src/types/schemas/application.schema.ts @@ -3,140 +3,153 @@ import { z } from "zod"; const MAX_FILE_SIZE = 500000; const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png"]; -const imageSchema = z.custom( +const imageSchema = 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: "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), { + }) + .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.", + projectName: z.string().min(5, { + message: "Project name must be at least 5 characters.", + }), + projectType: z.string({ + required_error: "Please select one of the option", + }), + shortDescription: z + .string({ + required_error: "Please provide a brief description for your project", + }) + .min(10, { + message: "Short description must be at least 10 characters.", }), - projectType: z.string({ - required_error: "Please select one of the option", + projectPitchDeck: z.union([ + 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).", + }), + z + .custom((val) => val instanceof File, { + 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).", + }), + ]), + projectLogo: imageSchema, + projectPhotos: z.custom( + (value) => { + if (value instanceof FileList || Array.isArray(value)) { + if (value.length === 1) { + return false; + } + return Array.from(value).every((item) => item instanceof File); + } + return false; + }, + { + message: + "Must be a FileList or an array of File objects with at least one file.", + } + ), + minInvest: z + .number({ + required_error: "Minimum investment must be a number.", + invalid_type_error: "Minimum investment must be a valid number.", + }) + .positive() + .max(9999999999, "Minimum investment must be a realistic amount."), + targetInvest: z + .number({ + required_error: "Target investment must be a number.", + invalid_type_error: "Target investment must be a valid number.", + }) + .positive() + .max(9999999999, "Target investment must be a realistic amount."), + deadline: z + .string() + .min(1, "Deadline is required.") + .refine((value) => !isNaN(Date.parse(value)), { + message: "Invalid date-time format.", + }) + .transform((value) => new Date(value)) + .refine((date) => date > new Date(), { + message: "Deadline must be in the future.", }), - shortDescription: z.string({ - required_error: "Please provide a brief description for your project", - }).min(10, { - message: "Short description must be at least 10 characters.", - }), - projectPitchDeck: z.union([ - 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).", - }, - ), - z.custom( - (val) => val instanceof File, - { - 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).", - }), - ]), - projectLogo: imageSchema, - projectPhotos: z.custom( - (value) => { - if (value instanceof FileList || Array.isArray(value)) { - if (value.length === 1) { - return false; - } - return Array.from(value).every((item) => item instanceof File); - } - return false; - }, - { - message: - "Must be a FileList or an array of File objects with at least one file.", - }, - ), - minInvest: z.number({ - required_error: "Minimum investment must be a number.", - invalid_type_error: "Minimum investment must be a valid number.", - }).positive().max( - 9999999999, - "Minimum investment must be a realistic amount.", - ), - targetInvest: z.number({ - required_error: "Target investment must be a number.", - invalid_type_error: "Target investment must be a valid number.", - }).positive().max( - 9999999999, - "Target investment must be a realistic amount.", - ), - deadline: z.string().min(1, "Deadline is required.") - .refine((value) => !isNaN(Date.parse(value)), { - message: "Invalid date-time format.", - }) - .transform((value) => new Date(value)) - .refine((date) => date > new Date(), { - message: "Deadline must be in the future.", - }), }); const businessFormSchema = z.object({ - companyName: z.string().min(5, { - message: "Company name must be at least 5 characters.", - }), - industry: z.string({ - required_error: "Please select one of the option", - }), - isInUS: z.string({ - required_error: "Please select either 'Yes' or 'No'.", + companyName: z.string().min(5, { + message: "Company name must be at least 5 characters.", + }), + industry: z.string({ + required_error: "Please select one of the option", + }), + isInUS: z + .string({ + required_error: "Please select either 'Yes' or 'No'.", }) - .transform((val) => val.toLowerCase()) - .refine((val) => val === "yes" || val === "no", { - message: "Please select either 'Yes' or 'No'.", - }), - isForSale: z.string({ - required_error: "Please select either 'Yes' or 'No'.", - }) - .transform((val) => val.toLowerCase()) - .refine((val) => val === "yes" || val === "no", { - message: "Please select either 'Yes' or 'No'.", - }), - isGenerating: z.string({ - required_error: "Please select either 'Yes' or 'No'.", - }) - .transform((val) => val.toLowerCase()) - .refine((val) => val === "yes" || val === "no", { - message: "Please select either 'Yes' or 'No'.", - }), - totalRaised: z.number({ - required_error: "Total raised must be a number.", - invalid_type_error: "Total raised must be a valid number.", - }).positive().max(9999999999, "Total raised must be a realistic amount."), - communitySize: z.string({ - required_error: "Please select one of the option", + .transform((val) => val.toLowerCase()) + .refine((val) => val === "yes" || val === "no", { + message: "Please select either 'Yes' or 'No'.", }), - businessPitchDeck: z.union([ - 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).", - }, - ), - z.custom( - (val) => val instanceof File, - { - 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).", - }), - ]), + isForSale: z + .string({ + required_error: "Please select either 'Yes' or 'No'.", + }) + .transform((val) => val.toLowerCase()) + .refine((val) => val === "yes" || val === "no", { + message: "Please select either 'Yes' or 'No'.", + }), + isGenerating: z + .string({ + required_error: "Please select either 'Yes' or 'No'.", + }) + .transform((val) => val.toLowerCase()) + .refine((val) => val === "yes" || val === "no", { + message: "Please select either 'Yes' or 'No'.", + }), + totalRaised: z + .number({ + required_error: "Total raised must be a number.", + invalid_type_error: "Total raised must be a valid number.", + }) + .positive() + .max(9999999999, "Total raised must be a realistic amount."), + communitySize: z.string({ + required_error: "Please select one of the option", + }), + businessPitchDeck: z.union([ + 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).", + }), + z + .custom((val) => val instanceof File, { + 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).", + }), + ]), }); export { businessFormSchema, projectFormSchema };