Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/EPMGCIP-168/implement contacts form #29

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

usavkov-epam
Copy link
Collaborator

@usavkov-epam usavkov-epam commented Nov 19, 2024

Purpose

JIRA

UI Form: https://jira.epam.com/jira/browse/EPMGCIP-168
Server action: https://jira.epam.com/jira/browse/EPMGCIP-174

Approach

Utilize the Mantine library as the UI kit to create the form component. Additionally, leverage Mantine's plugin for implementing a UI notification system. For form handling, adopt Next.js's approach using Server Actions. Use the nodemailer library to handle email sending. Include a CAPTCHA to verify that the user is human.

Screenshot

EPM-PR.mp4

@usavkov-epam usavkov-epam self-assigned this Nov 19, 2024
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [isCaptchaLoaded, setIsCaptchaLoaded] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const reCaptchaRef: any = useRef();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it possible to avoid 'any'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, updated

'postcss-preset-mantine': {},
'postcss-simple-vars': {
variables: {
'mantine-breakpoint-xs': '36em',
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have some breakpoints in src\variables.scss. So, we have to make a single source of truth for them. I guess, we can:

  • at least remove breakpoints in src\variables.scss and update a few related .scss files
  • OR, honestly, I am a not big fan of the idea to be to so tighly connected to mantine's provider, so maybe you know other options

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated, use SCSS as a source of truth

}

.reCaptcha {
min-height: 5.25rem;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you convert 'gap' and 'min-height' to 'px'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated

import { MessageKeys, NestedKeyOf, useTranslations } from "next-intl";
import { useCallback } from "react";

type NotificationType = "success" | "error";
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about creating global enum and using it for calling 'showNotification'? I noticed that you pass 'type' as string, maybe enum will be more appropriate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated. Types extracted to enum

token: string;
}

export async function sendContactForm({ name, email, subject, message, token }: SendEmailProps) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suppose, we need runtime validation here. Maybe Zod or something like that. In addition, we can reuse validation schema on frontend

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated. Used zod for validation on UI and BE via sharing the schema

@@ -0,0 +1 @@
export { default } from "./ContactForm";
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you don't mind, could you remove barrel 'index' files?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

removed

Copy link
Collaborator

@Dzmitry-Yaniuk Dzmitry-Yaniuk left a comment

Choose a reason for hiding this comment

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

Well done!
Please, address to some notes

label={t("contactForm.fields.name.label")}
placeholder={t("contactForm.fields.name.placeholder")}
key={form.key("name")}
{...form.getInputProps("name")}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just to confirm: is it safe to put spread operator for form.getInputProps("name")? Won't it accidentally override some props you declared earlier? Perhaps for safety it is better to put it in the beginning

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

All the props, specified above ...form.get... will be safely passed to components. I don't think it should be in the beginning, since devs are who can accidentally erase the necessary props for the form :)

src/hooks/useShowNotification.ts Outdated Show resolved Hide resolved
src/hooks/useShowNotification.ts Show resolved Hide resolved
src/hooks/useShowNotification.ts Outdated Show resolved Hide resolved
src/actions/sendContactForm.ts Outdated Show resolved Hide resolved
src/actions/sendContactForm.ts Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
Copy link
Collaborator

@Dzmitry-Yaniuk Dzmitry-Yaniuk left a comment

Choose a reason for hiding this comment

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

Great work!

md: 992px,
lg: 1200px,
xl: 1400px,
tablet: 834px,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I propose to remove 'tablet' and use 'sm' instead of that. I even don't remember why we chose 834px for tablets

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated

@@ -1 +1 @@
export { default as ContactForm } from "./ContactForm";
export { default as ContactForm } from "./ContactForm/ContactForm";
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about removing this index.tsx as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think using index files simplifies imports, hides folder structure details, and centralizes exports, making the codebase cleaner, easier to manage, and more scalable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants