Skip to content

Commit e4c58e6

Browse files
refactor: streamline request body validation and Slack message formatting
1 parent 229654a commit e4c58e6

File tree

1 file changed

+85
-63
lines changed

1 file changed

+85
-63
lines changed

src/pages/api/apply.ts

Lines changed: 85 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -24,80 +24,102 @@ interface ParsedBody {
2424
preworkRepo?: string;
2525
}
2626

27+
function getRequiredParams(): (keyof ParsedBody)[] {
28+
return [
29+
"firstName",
30+
"lastName",
31+
"email",
32+
"city",
33+
"state",
34+
"zipCode",
35+
"country",
36+
"branchOfService",
37+
"yearJoined",
38+
"yearSeparated",
39+
"hasAttendedPreviousCourse",
40+
"willAttendAnotherCourse",
41+
"linkedInAccountName",
42+
"githubAccountName",
43+
"preworkLink",
44+
"preworkRepo",
45+
];
46+
}
47+
48+
function validateBody(parsedBody: ParsedBody): boolean {
49+
const requiredParams = getRequiredParams();
50+
return checkParams(parsedBody, requiredParams);
51+
}
52+
53+
function formatPreviousCourses(parsedBody: ParsedBody): string | null {
54+
if (parsedBody.hasAttendedPreviousCourse && parsedBody.previousCourses !== "") {
55+
return `\`\`\`${parsedBody.previousCourses}\`\`\``;
56+
}
57+
return null;
58+
}
59+
60+
function formatOtherCourses(parsedBody: ParsedBody): string | null {
61+
if (parsedBody.willAttendAnotherCourse && parsedBody.otherCourses !== "") {
62+
return `\`\`\`${parsedBody.otherCourses}\`\`\``;
63+
}
64+
return null;
65+
}
66+
67+
function formatField(label: string, value: string | number | undefined): string {
68+
return `${label}: \`${value ?? ""}\``;
69+
}
70+
71+
function formatBooleanField(label: string, value: boolean | undefined): string {
72+
return `${label}: \`${value ? "Yes" : "No"}\``;
73+
}
74+
75+
function buildSlackMessage(parsedBody: ParsedBody): string {
76+
const items = [
77+
formatField("First Name", parsedBody.firstName),
78+
formatField("Last Name", parsedBody.lastName),
79+
formatField("Email", parsedBody.email),
80+
formatField("City", parsedBody.city),
81+
formatField("State", parsedBody.state),
82+
formatField("Zip Code", parsedBody.zipCode),
83+
formatField("Country", parsedBody.country),
84+
formatField("Branch of Service", parsedBody.branchOfService),
85+
formatField("Year Joined", parsedBody.yearJoined),
86+
formatField("Year Separated", parsedBody.yearSeparated),
87+
formatBooleanField("Has attended previous bootcamp/programs", parsedBody.hasAttendedPreviousCourse),
88+
formatPreviousCourses(parsedBody),
89+
formatBooleanField("Will do other courses/programs concurrently", parsedBody.willAttendAnotherCourse),
90+
formatOtherCourses(parsedBody),
91+
formatField("LinkedIn Account Name", parsedBody.linkedInAccountName),
92+
formatField("GitHub Account Name", parsedBody.githubAccountName),
93+
formatField("Prework Link", parsedBody.preworkLink),
94+
formatField("Prework Repository", parsedBody.preworkRepo),
95+
].filter(Boolean);
96+
97+
return items.join("\n");
98+
}
99+
100+
async function postToSlack(text: string): Promise<void> {
101+
await axios.post(
102+
`https://hooks.slack.com/services/${process.env.APPLY_WEBHOOK_ID ?? ""}`,
103+
JSON.stringify({ text })
104+
);
105+
}
106+
27107
export default async function handler(req: Request, res: Response) {
28108
try {
29-
const parsedBody = req.body as ParsedBody; // Ensure body matches ParsedBody interface
30-
const requiredParams: (keyof ParsedBody)[] = [
31-
"firstName",
32-
"lastName",
33-
"email",
34-
"city",
35-
"state",
36-
"zipCode",
37-
"country",
38-
"branchOfService",
39-
"yearJoined",
40-
"yearSeparated",
41-
"hasAttendedPreviousCourse",
42-
"willAttendAnotherCourse",
43-
"linkedInAccountName",
44-
"githubAccountName",
45-
"preworkLink",
46-
"preworkRepo",
47-
];
48-
49-
// Validate required fields in the parsed body
50-
const hasErrors = checkParams(parsedBody, requiredParams);
109+
const parsedBody = req.body as ParsedBody;
110+
111+
const hasErrors = validateBody(parsedBody);
51112

52113
if (hasErrors) {
53114
return res.status(422).json({ error: "Missing or incorrect required property" });
54115
}
55116

56-
// Construct the text message to be sent
57-
const items = [
58-
`First Name: \`${parsedBody.firstName ?? ""}\``,
59-
`Last Name: \`${parsedBody.lastName ?? ""}\``,
60-
`Email: \`${parsedBody.email ?? ""}\``,
61-
`City: \`${parsedBody.city ?? ""}\``,
62-
`State: \`${parsedBody.state ?? ""}\``,
63-
`Zip Code: \`${parsedBody.zipCode ?? ""}\``,
64-
`Country: \`${parsedBody.country ?? ""}\``,
65-
`Branch of Service: \`${parsedBody.branchOfService ?? ""}\``,
66-
`Year Joined: \`${parsedBody.yearJoined ?? ""}\``,
67-
`Year Separated: \`${parsedBody.yearSeparated ?? ""}\``,
68-
`Has attended previous bootcamp/programs: \`${
69-
parsedBody.hasAttendedPreviousCourse ? "Yes" : "No"
70-
}\``,
71-
`Will do other courses/programs concurrently: \`${
72-
parsedBody.willAttendAnotherCourse ? "Yes" : "No"
73-
}\``,
74-
`LinkedIn Account Name: \`${parsedBody.linkedInAccountName ?? ""}\``,
75-
`GitHub Account Name: \`${parsedBody.githubAccountName ?? ""}\``,
76-
`Prework Link: \`${parsedBody.preworkLink ?? ""}\``,
77-
`Prework Repository: \`${parsedBody.preworkRepo ?? ""}\``,
78-
];
79-
80-
if (parsedBody.willAttendAnotherCourse && parsedBody.otherCourses !== "") {
81-
items.splice(12, 0, `\`\`\`${parsedBody.otherCourses}\`\`\``);
82-
}
83-
84-
if (parsedBody.hasAttendedPreviousCourse && parsedBody.previousCourses !== "") {
85-
items.splice(11, 0, `\`\`\`${parsedBody.previousCourses}\`\`\``);
86-
}
87-
88-
const text = items.join("\n");
117+
const text = buildSlackMessage(parsedBody);
89118

90-
// Send the payload to the configured Slack webhook URL
91-
await axios.post(
92-
`https://hooks.slack.com/services/${process.env.APPLY_WEBHOOK_ID ?? ""}`,
93-
JSON.stringify({ text })
94-
);
119+
await postToSlack(text);
95120

96-
// Respond with success message
97121
return res.status(200).json({ message: "SUCCESS" });
98122
} catch (err) {
99-
// Log the error for debugging and respond with an error message
100-
// console.error("Failed to post to #mentor channel:", err);
101123
return res.status(500).json({ message: "Failed to post to #apply channel" });
102124
}
103125
}

0 commit comments

Comments
 (0)