mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-19 05:54:06 +01:00
Refactor application schema to add validation for project and business forms
This commit is contained in:
parent
428f42383d
commit
01afc6c6fb
142
src/types/schemas/application.schema.ts
Normal file
142
src/types/schemas/application.schema.ts
Normal file
@ -0,0 +1,142 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const MAX_FILE_SIZE = 500000;
|
||||
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/jpg", "image/png"];
|
||||
|
||||
const imageSchema = z.custom<File>(
|
||||
(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.",
|
||||
}),
|
||||
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.",
|
||||
}),
|
||||
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<File>(
|
||||
(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'.",
|
||||
})
|
||||
.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",
|
||||
}),
|
||||
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<File>(
|
||||
(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 };
|
||||
Loading…
Reference in New Issue
Block a user