Refactor form submission logic in BusinessForm component

This commit is contained in:
THIS ONE IS A LITTLE BIT TRICKY KRUB 2024-10-17 09:39:07 +07:00
parent 3a9f3faa48
commit dca9af5e3b
2 changed files with 147 additions and 124 deletions

View File

@ -28,8 +28,7 @@ type businessSchema = z.infer<typeof businessFormSchema>;
interface BusinessFormProps { interface BusinessFormProps {
industry: string[]; industry: string[];
handleSubmit: SubmitHandler<businessSchema>; onSubmit: SubmitHandler<businessSchema>;
onSubmit: () => void;
} }
const BusinessForm = ({ const BusinessForm = ({
onSubmit, onSubmit,
@ -53,7 +52,12 @@ const BusinessForm = ({
return ( return (
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> <form
onSubmit={form.handleSubmit(
onSubmit as unknown as SubmitHandler<businessSchema>
)}
className="space-y-8"
>
<div className="grid grid-flow-row auto-rows-max w-3/4 ml-1/2 lg:ml-[10%]"> <div className="grid grid-flow-row auto-rows-max w-3/4 ml-1/2 lg:ml-[10%]">
<h1 className="text-3xl font-bold mt-10 ml-96">About your company</h1> <h1 className="text-3xl font-bold mt-10 ml-96">About your company</h1>
<p className="ml-96 mt-5 text-neutral-500"> <p className="ml-96 mt-5 text-neutral-500">
@ -358,6 +362,12 @@ const BusinessForm = ({
</FormItem> </FormItem>
)} )}
/> */} /> */}
<Button
className="mt-12 mb-20 h-10 text-base font-bold py-6 px-5"
type="submit"
>
Submit application
</Button>
</div> </div>
</form> </form>
</Form> </Form>

View File

@ -3,16 +3,19 @@ import { z } from "zod";
const MAX_FILE_SIZE = 500000; const MAX_FILE_SIZE = 500000;
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png"]; const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png"];
const imageSchema = z.custom<File>( const imageSchema = z
.custom<File>(
(val) => val && typeof val === "object" && "size" in val && "type" in val, (val) => val && typeof val === "object" && "size" in val && "type" in val,
{ {
message: "Input must be a file.", message: "Input must be a file.",
}, }
).refine((file) => file.size < MAX_FILE_SIZE, { )
.refine((file) => file.size < MAX_FILE_SIZE, {
message: "File can't be bigger than 5MB.", 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.", message: "File format must be either jpg, jpeg, or png.",
}); });
const projectFormSchema = z.object({ const projectFormSchema = z.object({
projectName: z.string().min(5, { projectName: z.string().min(5, {
@ -21,26 +24,28 @@ const projectFormSchema = z.object({
projectType: z.string({ projectType: z.string({
required_error: "Please select one of the option", required_error: "Please select one of the option",
}), }),
shortDescription: z.string({ shortDescription: z
.string({
required_error: "Please provide a brief description for your project", required_error: "Please provide a brief description for your project",
}).min(10, { })
.min(10, {
message: "Short description must be at least 10 characters.", message: "Short description must be at least 10 characters.",
}), }),
projectPitchDeck: z.union([ projectPitchDeck: z.union([
z.string().url("Pitch deck must be a valid URL.").refine( z
(url) => url.endsWith(".md"), .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).", message: "Pitch deck URL must link to a markdown file (.md).",
}, }),
), z
z.custom<File>( .custom<File>((val) => val instanceof File, {
(val) => val instanceof File,
{
message: "Input must be a file.", message: "Input must be a file.",
}, })
).refine((file) => file.size < MAX_FILE_SIZE, { .refine((file) => file.size < MAX_FILE_SIZE, {
message: "File can't be bigger than 5MB.", message: "File can't be bigger than 5MB.",
}).refine((file) => file.name.endsWith(".md"), { })
.refine((file) => file.name.endsWith(".md"), {
message: "File must be a markdown file (.md).", message: "File must be a markdown file (.md).",
}), }),
]), ]),
@ -58,23 +63,25 @@ const projectFormSchema = z.object({
{ {
message: message:
"Must be a FileList or an array of File objects with at least one file.", "Must be a FileList or an array of File objects with at least one file.",
}, }
), ),
minInvest: z.number({ minInvest: z
.number({
required_error: "Minimum investment must be a number.", required_error: "Minimum investment must be a number.",
invalid_type_error: "Minimum investment must be a valid number.", invalid_type_error: "Minimum investment must be a valid number.",
}).positive().max( })
9999999999, .positive()
"Minimum investment must be a realistic amount.", .max(9999999999, "Minimum investment must be a realistic amount."),
), targetInvest: z
targetInvest: z.number({ .number({
required_error: "Target investment must be a number.", required_error: "Target investment must be a number.",
invalid_type_error: "Target investment must be a valid number.", invalid_type_error: "Target investment must be a valid number.",
}).positive().max( })
9999999999, .positive()
"Target investment must be a realistic amount.", .max(9999999999, "Target investment must be a realistic amount."),
), deadline: z
deadline: z.string().min(1, "Deadline is required.") .string()
.min(1, "Deadline is required.")
.refine((value) => !isNaN(Date.parse(value)), { .refine((value) => !isNaN(Date.parse(value)), {
message: "Invalid date-time format.", message: "Invalid date-time format.",
}) })
@ -91,49 +98,55 @@ const businessFormSchema = z.object({
industry: z.string({ industry: z.string({
required_error: "Please select one of the option", required_error: "Please select one of the option",
}), }),
isInUS: z.string({ isInUS: z
.string({
required_error: "Please select either 'Yes' or 'No'.", required_error: "Please select either 'Yes' or 'No'.",
}) })
.transform((val) => val.toLowerCase()) .transform((val) => val.toLowerCase())
.refine((val) => val === "yes" || val === "no", { .refine((val) => val === "yes" || val === "no", {
message: "Please select either 'Yes' or 'No'.", message: "Please select either 'Yes' or 'No'.",
}), }),
isForSale: z.string({ isForSale: z
.string({
required_error: "Please select either 'Yes' or 'No'.", required_error: "Please select either 'Yes' or 'No'.",
}) })
.transform((val) => val.toLowerCase()) .transform((val) => val.toLowerCase())
.refine((val) => val === "yes" || val === "no", { .refine((val) => val === "yes" || val === "no", {
message: "Please select either 'Yes' or 'No'.", message: "Please select either 'Yes' or 'No'.",
}), }),
isGenerating: z.string({ isGenerating: z
.string({
required_error: "Please select either 'Yes' or 'No'.", required_error: "Please select either 'Yes' or 'No'.",
}) })
.transform((val) => val.toLowerCase()) .transform((val) => val.toLowerCase())
.refine((val) => val === "yes" || val === "no", { .refine((val) => val === "yes" || val === "no", {
message: "Please select either 'Yes' or 'No'.", message: "Please select either 'Yes' or 'No'.",
}), }),
totalRaised: z.number({ totalRaised: z
.number({
required_error: "Total raised must be a number.", required_error: "Total raised must be a number.",
invalid_type_error: "Total raised must be a valid number.", invalid_type_error: "Total raised must be a valid number.",
}).positive().max(9999999999, "Total raised must be a realistic amount."), })
.positive()
.max(9999999999, "Total raised must be a realistic amount."),
communitySize: z.string({ communitySize: z.string({
required_error: "Please select one of the option", required_error: "Please select one of the option",
}), }),
businessPitchDeck: z.union([ businessPitchDeck: z.union([
z.string().url("Pitch deck must be a valid URL.").refine( z
(url) => url.endsWith(".md"), .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).", message: "Pitch deck URL must link to a markdown file (.md).",
}, }),
), z
z.custom<File>( .custom<File>((val) => val instanceof File, {
(val) => val instanceof File,
{
message: "Input must be a file.", message: "Input must be a file.",
}, })
).refine((file) => file.size < MAX_FILE_SIZE, { .refine((file) => file.size < MAX_FILE_SIZE, {
message: "File can't be bigger than 5MB.", message: "File can't be bigger than 5MB.",
}).refine((file) => file.name.endsWith(".md"), { })
.refine((file) => file.name.endsWith(".md"), {
message: "File must be a markdown file (.md).", message: "File must be a markdown file (.md).",
}), }),
]), ]),