Some checks are pending
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Waiting to run
276 lines
8.3 KiB
TypeScript
276 lines
8.3 KiB
TypeScript
export const inquiryIntents = [
|
|
"general",
|
|
"exhibitor",
|
|
"sponsor",
|
|
"partnership",
|
|
"startup_referral",
|
|
"sales",
|
|
"press",
|
|
"newsletter",
|
|
] as const;
|
|
|
|
export type InquiryIntent = (typeof inquiryIntents)[number];
|
|
|
|
export type InquiryPayload = {
|
|
intent: InquiryIntent;
|
|
name: string;
|
|
email: string;
|
|
company?: string;
|
|
message: string;
|
|
phone?: string;
|
|
firstName?: string;
|
|
lastName?: string;
|
|
consent: boolean;
|
|
startupName?: string;
|
|
startupWebsite?: string;
|
|
startupSector?: string;
|
|
whyRecommend?: string;
|
|
jobTitle?: string;
|
|
companyWebsite?: string;
|
|
companyDescription?: string;
|
|
sector?: string;
|
|
productsToAdvertise?: string;
|
|
boothSize?: string;
|
|
powerRequired?: boolean;
|
|
internetRequired?: boolean;
|
|
staffCount?: string;
|
|
marketingMaterials?: string;
|
|
specialRequirements?: string;
|
|
};
|
|
|
|
function parseEmail(email: unknown) {
|
|
return typeof email === "string" ? email.trim() : "";
|
|
}
|
|
|
|
function requireConsent(consent: unknown): boolean {
|
|
return consent === true;
|
|
}
|
|
|
|
export function validateInquiry(
|
|
body: unknown
|
|
): { ok: true; data: InquiryPayload } | { ok: false; error: string } {
|
|
if (!body || typeof body !== "object") {
|
|
return { ok: false, error: "Invalid request body" };
|
|
}
|
|
|
|
const b = body as Record<string, unknown>;
|
|
const intent = b.intent as InquiryIntent;
|
|
|
|
if (!inquiryIntents.includes(intent)) {
|
|
return { ok: false, error: "Invalid intent" };
|
|
}
|
|
|
|
const email = parseEmail(b.email);
|
|
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
return { ok: false, error: "Valid email is required" };
|
|
}
|
|
|
|
if (intent === "partnership") {
|
|
const firstName = typeof b.firstName === "string" ? b.firstName.trim() : "";
|
|
const lastName = typeof b.lastName === "string" ? b.lastName.trim() : "";
|
|
const company = typeof b.company === "string" ? b.company.trim() : "";
|
|
|
|
if (!firstName || firstName.length < 2) {
|
|
return { ok: false, error: "First name is required" };
|
|
}
|
|
if (!lastName || lastName.length < 2) {
|
|
return { ok: false, error: "Last name is required" };
|
|
}
|
|
if (!company) {
|
|
return { ok: false, error: "Company name is required" };
|
|
}
|
|
if (!requireConsent(b.consent)) {
|
|
return { ok: false, error: "You must agree to data collection to submit" };
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
data: {
|
|
intent,
|
|
firstName,
|
|
lastName,
|
|
name: `${firstName} ${lastName}`,
|
|
email,
|
|
company,
|
|
message:
|
|
typeof b.message === "string" && b.message.trim()
|
|
? b.message.trim()
|
|
: "Partnership information request",
|
|
consent: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
if (intent === "exhibitor") {
|
|
const firstName = typeof b.firstName === "string" ? b.firstName.trim() : "";
|
|
const lastName = typeof b.lastName === "string" ? b.lastName.trim() : "";
|
|
const company = typeof b.company === "string" ? b.company.trim() : "";
|
|
const phone = typeof b.phone === "string" ? b.phone.trim() : "";
|
|
const jobTitle = typeof b.jobTitle === "string" ? b.jobTitle.trim() : "";
|
|
const companyDescription =
|
|
typeof b.companyDescription === "string" ? b.companyDescription.trim() : "";
|
|
const productsToAdvertise =
|
|
typeof b.productsToAdvertise === "string" ? b.productsToAdvertise.trim() : "";
|
|
const boothSize = typeof b.boothSize === "string" ? b.boothSize.trim() : "";
|
|
const sector = typeof b.sector === "string" ? b.sector.trim() : "";
|
|
const message = typeof b.message === "string" ? b.message.trim() : "";
|
|
|
|
if (!firstName || firstName.length < 2) {
|
|
return { ok: false, error: "First name is required" };
|
|
}
|
|
if (!lastName || lastName.length < 2) {
|
|
return { ok: false, error: "Last name is required" };
|
|
}
|
|
if (!company) {
|
|
return { ok: false, error: "Company name is required" };
|
|
}
|
|
if (!phone) {
|
|
return { ok: false, error: "Phone number is required" };
|
|
}
|
|
if (!jobTitle) {
|
|
return { ok: false, error: "Job title is required" };
|
|
}
|
|
if (!sector) {
|
|
return { ok: false, error: "Industry / sector is required" };
|
|
}
|
|
if (!companyDescription || companyDescription.length < 20) {
|
|
return { ok: false, error: "Please describe your company (at least 20 characters)" };
|
|
}
|
|
if (!productsToAdvertise || productsToAdvertise.length < 20) {
|
|
return {
|
|
ok: false,
|
|
error: "Please describe the products you plan to advertise (at least 20 characters)",
|
|
};
|
|
}
|
|
if (!boothSize) {
|
|
return { ok: false, error: "Preferred booth size is required" };
|
|
}
|
|
if (!message || message.length < 10) {
|
|
return { ok: false, error: "Please describe your booth goals (at least 10 characters)" };
|
|
}
|
|
if (!requireConsent(b.consent)) {
|
|
return { ok: false, error: "You must agree to data collection to submit" };
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
data: {
|
|
intent,
|
|
firstName,
|
|
lastName,
|
|
name: `${firstName} ${lastName}`,
|
|
email,
|
|
phone,
|
|
jobTitle,
|
|
company,
|
|
companyWebsite:
|
|
typeof b.companyWebsite === "string" ? b.companyWebsite.trim() : undefined,
|
|
companyDescription,
|
|
sector,
|
|
productsToAdvertise,
|
|
boothSize,
|
|
powerRequired: b.powerRequired === true,
|
|
internetRequired: b.internetRequired === true,
|
|
staffCount: typeof b.staffCount === "string" ? b.staffCount.trim() : undefined,
|
|
marketingMaterials:
|
|
typeof b.marketingMaterials === "string" ? b.marketingMaterials.trim() : undefined,
|
|
specialRequirements:
|
|
typeof b.specialRequirements === "string" ? b.specialRequirements.trim() : undefined,
|
|
message,
|
|
consent: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
if (intent === "startup_referral") {
|
|
const name = typeof b.name === "string" ? b.name.trim() : "";
|
|
const startupName = typeof b.startupName === "string" ? b.startupName.trim() : "";
|
|
const whyRecommend = typeof b.whyRecommend === "string" ? b.whyRecommend.trim() : "";
|
|
|
|
if (!name || name.length < 2) {
|
|
return { ok: false, error: "Your name is required" };
|
|
}
|
|
if (!startupName) {
|
|
return { ok: false, error: "Startup name is required" };
|
|
}
|
|
if (!whyRecommend || whyRecommend.length < 20) {
|
|
return { ok: false, error: "Please tell us why you recommend this startup (at least 20 characters)" };
|
|
}
|
|
if (!requireConsent(b.consent)) {
|
|
return { ok: false, error: "You must agree to data collection to submit" };
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
data: {
|
|
intent,
|
|
name,
|
|
email,
|
|
startupName,
|
|
startupWebsite:
|
|
typeof b.startupWebsite === "string" ? b.startupWebsite.trim() : undefined,
|
|
startupSector:
|
|
typeof b.startupSector === "string" ? b.startupSector.trim() : undefined,
|
|
whyRecommend,
|
|
message: whyRecommend,
|
|
consent: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
if (!requireConsent(b.consent)) {
|
|
return { ok: false, error: "You must agree to data collection to submit" };
|
|
}
|
|
|
|
if (intent === "newsletter") {
|
|
const firstName = typeof b.firstName === "string" ? b.firstName.trim() : "";
|
|
const lastName = typeof b.lastName === "string" ? b.lastName.trim() : "";
|
|
const nameFromFields = `${firstName} ${lastName}`.trim();
|
|
const name = nameFromFields || (typeof b.name === "string" ? b.name.trim() : "");
|
|
|
|
if (!firstName || firstName.length < 2) {
|
|
return { ok: false, error: "First name is required" };
|
|
}
|
|
if (!lastName || lastName.length < 2) {
|
|
return { ok: false, error: "Last name is required" };
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
data: {
|
|
intent,
|
|
firstName,
|
|
lastName,
|
|
name,
|
|
email,
|
|
message: "Newsletter signup",
|
|
consent: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
const name = typeof b.name === "string" ? b.name.trim() : "";
|
|
const message = typeof b.message === "string" ? b.message.trim() : "";
|
|
|
|
if (!name || name.length < 2) {
|
|
return { ok: false, error: "Name is required" };
|
|
}
|
|
|
|
if (!message || message.length < 10) {
|
|
return { ok: false, error: "Message must be at least 10 characters" };
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
data: {
|
|
intent,
|
|
name,
|
|
email,
|
|
message,
|
|
company: typeof b.company === "string" ? b.company.trim() : undefined,
|
|
phone: typeof b.phone === "string" ? b.phone.trim() : undefined,
|
|
consent: true,
|
|
},
|
|
};
|
|
}
|