Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"react-dom": "18.2.0",
"react-gtm-module": "^2.0.11",
"react-loader-spinner": "^5.3.4",
"swiper": "^8.3.2"
"swiper": "^8.3.2",
"zod": "^3.19.1"
},
"devDependencies": {
"@types/google-spreadsheet": "^3.3.0",
Expand Down
190 changes: 93 additions & 97 deletions src/pages/api/mail/contact.ts
Original file line number Diff line number Diff line change
@@ -1,112 +1,108 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import { mailingClient } from '@/api/mailingClient'
import { appendSpreadsheet } from '@/api/gSheets'

interface ContactFormNextApiRequest extends NextApiRequest {
body: {
firstName: string
email: string
projectName: string
projectDescription: string
services: string[]
budget: string
deadline: string
discord: string | undefined
telegram: string | undefined
github: string | undefined
projectLink: string | undefined
aditionalInformation: string | undefined
}
}
import { Submit, SubmitSchema } from '@/types/submit'

export default async function serverSideCall(
req: ContactFormNextApiRequest,
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
res.status(405)
} else {
const {
firstName,
email,
projectName,
projectDescription,
services,
budget,
deadline,
discord,
telegram,
github,
projectLink,
aditionalInformation,
} = req.body
const aditionalInformationHeader =
discord || telegram || github || projectLink || aditionalInformation
? 'Aditional information'
: ''
const discordHandle = discord ? `Discord handle: ${discord}` : ''
const telegramHandle = telegram ? `Telegram handle: ${telegram}` : ''
const githubHandle = github ? `Github Profile: ${github}` : ''
const projectLinkText = projectLink ? `Project Link: ${projectLink}` : ''
const aditionalInformationText = aditionalInformation
? `Additional Information given by the client: ${aditionalInformation}`
: ''
const mailData = {
from: process.env.GMAIL_ACCOUNT as string,
to: process.env.EMAIL_RECIPIENT as string,
subject: `Project Request from: ${firstName} | ${projectName}`,
text: `Who requested:
First Name: ${firstName}
E-mail: ${email}
Project Name: ${projectName}
Project Description: ${projectDescription}
Type of services: ${services}
Budget Range: ${budget}
Deadline(yyyy-mm-dd): ${deadline}
const submitData: Submit = req.body
const { success } = SubmitSchema.safeParse(submitData)
if (success) {
const {
firstName,
email,
projectName,
projectDescription,
services,
budget,
deadline,
discord,
telegram,
github,
projectLink,
aditionalInformation,
} = submitData

${aditionalInformationHeader}
${discordHandle}
${telegramHandle}
${githubHandle}
${projectLinkText}
${aditionalInformationText}
`,
}
const date = new Date()
const sheetsData = {
timeStamp: date.toUTCString(),
whoRequested: firstName,
emailContact: email,
projectName: projectName,
projectDescription: projectDescription,
typeOfServices: services.toString(),
budgetRange: budget,
deadline: deadline,
discordHandle: discord ? discord : '',
githubHandle: github ? github : '',
telegramHandle: telegram ? telegram : '',
projectLink: projectLink ? projectLink : '',
aditionalInformationText: aditionalInformation ? aditionalInformation : ''
}
try {
mailingClient.sendMail(mailData, (err) => {
if (err) {
console.log(err)
res.status(500).json({
success: false,
body: err,
})
} else {
res.status(200).json({
success: true,
})
}
})
appendSpreadsheet(sheetsData)
} catch (err) {
console.log(err)
res.status(400).json({
const aditionalInformationHeader =
discord || telegram || github || projectLink || aditionalInformation
? 'Aditional information'
: ''
const discordHandle = discord ? `Discord handle: ${discord}` : ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep it DRY, I recommend creating a helper function that takes the optional data variable and its message and returns an empty string, and replaces all of these ternary operators.

something like that

// Helper function that returns an empty string if the optional data is falsy
    const handleOptionalData = (optionalData: string, message: string) => optionalData ? message : ''

// instead of 
const discordHandle = discord ? `Discord handle: ${discord}` : ''

// replacing for
const discordHandle = handleOptionalData(discord, `Discord handle: ${discord}`)

const telegramHandle = telegram ? `Telegram handle: ${telegram}` : ''
const githubHandle = github ? `Github Profile: ${github}` : ''
const projectLinkText = projectLink ? `Project Link: ${projectLink}` : ''
const aditionalInformationText = aditionalInformation
? `Additional Information given by the client: ${aditionalInformation}`
: ''
const mailData = {
from: process.env.GMAIL_ACCOUNT as string,
to: process.env.EMAIL_RECIPIENT as string,
subject: `Project Request from: ${firstName} | ${projectName}`,
text: `Who requested:
First Name: ${firstName}
E-mail: ${email}
Project Name: ${projectName}
Project Description: ${projectDescription}
Type of services: ${services}
Budget Range: ${budget}
Deadline(yyyy-mm-dd): ${deadline}
${aditionalInformationHeader}
${discordHandle}
${telegramHandle}
${githubHandle}
${projectLinkText}
${aditionalInformationText}
`,
}
const date = new Date()
const sheetsData = {
timeStamp: date.toUTCString(),
whoRequested: firstName,
emailContact: email,
projectName: projectName,
projectDescription: projectDescription,
typeOfServices: services.toString(),
budgetRange: budget,
deadline: deadline,
discordHandle: discord ? discord : '',
githubHandle: github ? github : '',
telegramHandle: telegram ? telegram : '',
projectLink: projectLink ? projectLink : '',
aditionalInformationText: aditionalInformation
? aditionalInformation
: '',
}
try {
mailingClient.sendMail(mailData, (err) => {
if (err) {
console.log(err)
res.status(500).json({
success: false,
body: err,
})
} else {
res.status(200).json({
success: true,
})
}
})
appendSpreadsheet(sheetsData)
} catch (err) {
console.log(err)
res.status(400).json({
success: false,
})
}
Comment on lines +96 to +101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of an error in the execution of the endpoint is always good to also send the error message. Getting the message with the correct typing from an error response is a bit tricky, but here's a solution:

Suggested change
} catch (err) {
console.log(err)
res.status(400).json({
success: false,
})
}
} catch (err) {
console.log(err)
let message
if (err instanceof Error) message = err.message
else message = String(err)
res.status(400).json({
success: false,
message
})
}

} else {
res.status(422).json({
success: false,
message: 'Invalid body format',
})
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/types/submit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { z } from 'zod'

const nonEmptyStringContraint = z.string().min(1)
const EmptyStringContraint = z.string()

export const SubmitSchema = z.object({
firstName: nonEmptyStringContraint,
email: nonEmptyStringContraint,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zod string objects has a built-in method for checking the email syntax:

Suggested change
email: nonEmptyStringContraint,
email: nonEmptyStringContraint.email(),

projectName: nonEmptyStringContraint,
projectDescription: nonEmptyStringContraint,
services: z.array(nonEmptyStringContraint),
budget: nonEmptyStringContraint,
deadline: nonEmptyStringContraint,
discord: EmptyStringContraint,
telegram: EmptyStringContraint,
github: EmptyStringContraint,
projectLink: EmptyStringContraint,
aditionalInformation: EmptyStringContraint,
})

export type Submit = z.infer<typeof SubmitSchema>
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3246,3 +3246,8 @@ yoga-wasm-web@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yoga-wasm-web/-/yoga-wasm-web-0.1.2.tgz#05d3fc9cbdfd57ac9682debb5001aca075489a39"
integrity sha512-8SkgawHcA0RUbMrnhxbaQkZDBi8rMed8pQHixkFF9w32zGhAwZ9/cOHWlpYfr6RCx42Yp3siV45/jPEkJxsk6w==

zod@^3.19.1:
version "3.19.1"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.19.1.tgz#112f074a97b50bfc4772d4ad1576814bd8ac4473"
integrity sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==