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

Newsletter subscription #186

Merged
merged 4 commits into from
Aug 14, 2023
Merged

Newsletter subscription #186

merged 4 commits into from
Aug 14, 2023

Conversation

oleeh-shd
Copy link
Collaborator

@oleeh-shd oleeh-shd commented Aug 14, 2023

Summary by CodeRabbit

New Feature:

  • Enhanced the HomePage component with improved error handling and conditional rendering based on theme.
  • Updated the newsletter subscription form in Newsletter.tsx to display error messages when form submission fails.
  • Added a new function subscribeUser in lib/subscribeUser.ts for GraphQL mutation.

Style:

  • Adjusted the padding values in HomeLayout.tsx for better positioning of child components.
  • Improved visibility and styling of the Modal component in components/Home/Modal.tsx.

🎉 With each line of code, we strive,
To make our user experience come alive.
Errors caught, themes switched with glee,
Our app's journey continues, as smooth as can be. 🚀

@vercel
Copy link

vercel bot commented Aug 14, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
bg-frontend ❌ Failed (Inspect) Aug 14, 2023 11:56am
bhagavad-gita ✅ Ready (Inspect) Visit Preview Aug 14, 2023 11:56am

@github-actions
Copy link
Contributor

github-actions bot commented Aug 14, 2023

Image description CodeRabbit

Walkthrough

This pull request introduces enhancements to the newsletter subscription feature, modifies the modal component's visibility and styling, and adjusts padding in the HomeLayout. It also adds error handling for form submission and a new function to perform GraphQL mutations.

Changes

Files Summary
app/home-page.tsx, components/Home/Newsletter.tsx, lib/subscribeUser.ts The changes enhance the newsletter subscription functionality by adding error handling and conditional rendering based on theme. A new function subscribeUser is introduced to perform GraphQL mutations.
components/Home/Modal.tsx The modal component is updated with a new CSS class to improve its visibility and positioning. The text content of the heading and paragraph elements are also updated.
layouts/HomeLayout.tsx The padding values of a <div> element within the HomeLayout component are adjusted, which may affect the positioning of its children components.

@vercel vercel bot temporarily deployed to Preview – bg-frontend August 14, 2023 11:10 Inactive
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Image description CodeRabbit

Commits Files that changed from the base of the PR and between 9c0a141 and 0a755f2 commits.
Files selected (4)
  • app/home-page.tsx (3)
  • components/Home/Modal.tsx (1)
  • components/Home/Newsletter.tsx (4)
  • lib/subscribeUser.ts (1)
Files skipped from review due to trivial changes (1)
  • components/Home/Modal.tsx
Review comments generated (12)
  • Review: 8
  • LGTM: 4

Tips

Chat with Image description CodeRabbit Bot (@coderabbitai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @coderabbitai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @coderabbitai: ignore anywhere in the PR description to pause further reviews from the bot.

Comment on lines +13 to +14
user_name: "${name}"
user_email: "${email}"
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The GraphQL mutation string is being constructed using template literals which can lead to potential security issues like GraphQL injection attacks. It's better to use variables in the mutation and pass the values separately.

-               user_name: "${name}"
-               user_email: "${email}"
+               user_name: $name
+               user_email: $email

And then in the mutate function, pass the variables like this:

  await apolloClient.mutate({
    mutation: gql`
      mutation MyMutation($name: String!, $email: String!) {
        insert_newsletter_subscriptions_one(
          object: {
              user_name: $name
              user_email: $email
          }
        ) {
          user_name
          user_email
        }
      }
    `,
+   variables: {
+     name,
+     email,
+   },
  });

Comment on lines +3 to +9
import { SubscribeMessage } from "../../app/home-page";

interface Props {
handleSubscribe: (
e: FormEvent<HTMLFormElement>,
formData: NewsletterFormData
) => boolean;
) => Promise<SubscribeMessage>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The change from a boolean return type to a Promise of SubscribeMessage in the handleSubscribe function is a good improvement. It allows for better error handling and more informative responses.

-  ) => boolean;
+  ) => Promise<SubscribeMessage>;

Comment on lines +18 to +30
const [errorMessage, setErrorMessage] = useState("");

const onSubmit = async (e) => {
const { isSuccess, message } = await handleSubscribe(e, formData);
if (isSuccess) {
setFormData({ name: "", email: "" });
setIsValid(true);
setErrorMessage("");
} else {
setIsValid(false);
setErrorMessage(message);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The addition of an errorMessage state variable and its usage in the onSubmit function is a good practice. This allows for dynamic error messages based on the response from the handleSubscribe function, improving user experience.

+ const [errorMessage, setErrorMessage] = useState("");
+
+ const onSubmit = async (e) => {
+   const { isSuccess, message } = await handleSubscribe(e, formData);
+   if (isSuccess) {
+     setFormData({ name: "", email: "" });
+     setIsValid(true);
+     setErrorMessage("");
+   } else {
+     setIsValid(false);
+     setErrorMessage(message);
+   }
+ };

}
}}
>
<form className="flex flex-col md:flex-row" onSubmit={onSubmit}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The refactoring of the form's onSubmit event handler to use the new onSubmit function is a good change. It simplifies the code and makes it easier to understand.

- onSubmit={(e) => {
-   if (handleSubscribe(e, formData)) {
-     setFormData({ name: "", email: "" });
-     setIsValid(true);
-   } else {
-     setIsValid(false);
-   }
- }}
+ onSubmit={onSubmit}

Comment on lines +88 to +89
<div className="text-lg text-red-400 mt-4">
<p className="font-bold mr-20 mt-12">{errorMessage}</p>
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The change to display the errorMessage when the form is not valid is a good improvement. It provides more specific feedback to the user about what went wrong.

- <p className="font-bold mr-20 mt-12">
-   ERROR: Name or Email Cannot be Empty
- </p>
+ <p className="font-bold mr-20 mt-12">{errorMessage}</p>

Comment on lines +38 to +63

async function handleSubscribe(
e: FormEvent<HTMLFormElement>,
formData: NewsletterFormData
): boolean {
{ name, email }: NewsletterFormData
): Promise<SubscribeMessage> {
e.preventDefault();
if (formData.name && formData.email) {
// todo call newsletter subscribe API
setModalVisible(true);
return true;
} else return false;
if (name && email) {
try {
await subscribeUser(name, email);

setModalVisible(true);
return {
isSuccess: true,
message: "",
};
} catch (error) {
return {
isSuccess: false,
message: "ERROR: Email already exists",
};
}
} else
return {
isSuccess: false,
message: "ERROR: Name or Email Cannot be Empty",
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The handleSubscribe function has been updated to use async/await syntax and includes error handling, which is good. However, the error message "ERROR: Email already exists" assumes that any error thrown by subscribeUser is due to a duplicate email. This may not always be the case. It would be better to check the error message returned from the server and display that instead. Also, consider using a try-catch-finally block to ensure setModalVisible(true) is called regardless of whether an error occurs.

-  } catch (error) {
-    return {
-      isSuccess: false,
-      message: "ERROR: Email already exists",
-    };
-  }
+  } catch (error) {
+    return {
+      isSuccess: false,
+      message: error.message || "An error occurred",
+    };
+  } finally {
+    setModalVisible(true);
+  }

@vercel vercel bot temporarily deployed to Preview – bg-frontend August 14, 2023 11:53 Inactive
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Image description CodeRabbit

Commits Files that changed from the base of the PR and between 0a755f2 and 24d86f7 commits.
Files selected (3)
  • app/home-page.tsx (2)
  • components/Home/Modal.tsx (2)
  • layouts/HomeLayout.tsx (1)
Files skipped from review due to trivial changes (1)
  • components/Home/Modal.tsx
Review comments generated (6)
  • Review: 3
  • LGTM: 3

Tips

Chat with Image description CodeRabbit Bot (@coderabbitai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @coderabbitai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @coderabbitai: ignore anywhere in the PR description to pause further reviews from the bot.

@@ -6,7 +6,7 @@ const HomeLayout = ({ children }: { children: ReactNode }) => {
return (
<div className="dark:bg-dark-bg min-h-screen flex flex-col">
<IndexHeader />
<div className="pt-24 lg:pt-[90px] flex-1">{children}</div>
<div className="pt-[84px] lg:pt-[90px] flex-1">{children}</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The change from pt-24 to pt-[84px] seems to be a significant increase in padding-top. Ensure that this change doesn't disrupt the layout of the page or make it inconsistent with other pages. If the intention is to provide more space, consider if there's a more responsive way to do so.

- <div className="pt-[84px] lg:pt-[90px] flex-1">{children}</div>
+ <div className="pt-24 lg:pt-[90px] flex-1">{children}</div>

Comment on lines +39 to 64
async function handleSubscribe(
e: FormEvent<HTMLFormElement>,
formData: NewsletterFormData
): boolean {
{ name, email }: NewsletterFormData
): Promise<SubscribeMessage> {
e.preventDefault();
if (formData.name && formData.email) {
// todo call newsletter subscribe API
setModalVisible(true);
return true;
} else return false;
if (name && email) {
try {
await subscribeUser(name, email);

setModalVisible(true);
return {
isSuccess: true,
message: "",
};
} catch (error) {
return {
isSuccess: false,
message: "ERROR: Email already exists",
};
}
} else
return {
isSuccess: false,
message: "ERROR: Name or Email Cannot be Empty",
};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The handleSubscribe function has been modified to be asynchronous and now returns a promise that resolves to a SubscribeMessage. The error handling introduced here is a good practice, but it's not ideal to hardcode error messages like "ERROR: Email already exists" or "ERROR: Name or Email Cannot be Empty". It would be better to handle these errors at a higher level or use an error handling utility. Here's a suggestion:

  try {
    await subscribeUser(name, email);
    setModalVisible(true);
    return {
      isSuccess: true,
      message: "",
    };
  } catch (error) {
+   let errorMessage = '';
+   if (error.message.includes('duplicate key value')) {
+     errorMessage = 'ERROR: Email already exists';
+   } else {
+     errorMessage = error.message;
+   }
    return {
      isSuccess: false,
-     message: "ERROR: Email already exists",
+     message: errorMessage,
    };
  }

This way, you can handle different types of errors more effectively.

Comment on lines 66 to 93
return (
<div className="font-inter min-h-screen dark:bg-dark-bg">
<main>
<HomeLayout>
<Modal
modalVisible={modalVisible}
modalVisible={!modalVisible}
setModalVisible={setModalVisible}
/>
<div className="relative">
<Banner />
<div className="absolute top-[204px] z-0 w-full h-[460px]">
<Image src="/main-background.png" alt="background image" fill />
</div>
<Image
src="/flower.svg"
alt="flower"
width={365}
height={150}
className="absolute top-[54%] left-[50%] -translate-x-2/4"
/>
{theme === "light" && (
<>
<div className="absolute top-[204px] z-0 w-full h-[460px]">
<Image
src="/main-background.png"
alt="background image"
fill
/>
</div>
<Image
src="/flower.svg"
alt="flower"
width={365}
height={150}
className="absolute top-[54%] left-[50%] -translate-x-2/4"
/>
</>
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The rendering of certain elements is now conditional based on the theme value. This is a good approach for theming. However, the modal visibility condition seems to be inverted in line 71. If modalVisible is true, then !modalVisible will be false, which means the modal won't be visible when it should be. Here's a suggested fix:

- <Modal modalVisible={!modalVisible} setModalVisible={setModalVisible} />
+ <Modal modalVisible={modalVisible} setModalVisible={setModalVisible} />

@vercel vercel bot temporarily deployed to Preview – bg-frontend August 14, 2023 11:56 Inactive
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Image description CodeRabbit

Commits Files that changed from the base of the PR and between 24d86f7 and ad573b1 commits.
Files selected (1)
  • app/home-page.tsx (3)
Review comments generated (4)
  • Review: 3
  • LGTM: 1

Tips

Chat with Image description CodeRabbit Bot (@coderabbitai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @coderabbitai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @coderabbitai: ignore anywhere in the PR description to pause further reviews from the bot.

import { useTheme } from "next-themes";
import { subscribeUser } from "../lib/subscribeUser";

export type SubscribeMessage = { isSuccess: boolean; message: string };
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The SubscribeMessage type is defined but it's not clear if the message field is used in any meaningful way. It seems to be set to an empty string on success and a hardcoded error message on failure. Consider using this field to pass more detailed error messages from the subscribeUser function, or remove it if it's not needed.

- export type SubscribeMessage = { isSuccess: boolean; message: string };
+ export type SubscribeMessage = { isSuccess: boolean; message?: string };

Comment on lines +39 to +63
async function handleSubscribe(
e: FormEvent<HTMLFormElement>,
formData: NewsletterFormData
): boolean {
{ name, email }: NewsletterFormData
): Promise<SubscribeMessage> {
e.preventDefault();
if (formData.name && formData.email) {
// todo call newsletter subscribe API
setModalVisible(true);
return true;
} else return false;
if (name && email) {
try {
await subscribeUser(name, email);

setModalVisible(true);
return {
isSuccess: true,
message: "",
};
} catch (error) {
return {
isSuccess: false,
message: "ERROR: Email already exists",
};
}
} else
return {
isSuccess: false,
message: "ERROR: Name or Email Cannot be Empty",
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The handleSubscribe function has been modified to handle errors and return a SubscribeMessage. However, it only catches errors at a high level and assumes any error means that the email already exists. This could lead to misleading error messages if the error was due to something else (like a network error). Consider catching specific error types within the subscribeUser function and throwing custom Error objects with appropriate messages that can be caught and handled here.

Also, the function returns a SubscribeMessage object when the name or email fields are empty. This is not an asynchronous operation and doesn't need to be part of an async function. Consider moving this validation outside of handleSubscribe and before calling it.

-  async function handleSubscribe(
-     e: FormEvent<HTMLFormElement>,
-    { name, email }: NewsletterFormData
-  ): Promise<SubscribeMessage> {
-     e.preventDefault();
-    if (name && email) {
-      try {
-        await subscribeUser(name, email);
-
-        setModalVisible(true);
-        return {
-          isSuccess: true,
-          message: "",
-        };
-      } catch (error) {
-        return {
-          isSuccess: false,
-          message: "ERROR: Email already exists",
-        };
-      }
-    } else
-      return {
-        isSuccess: false,
-        message: "ERROR: Name or Email Cannot be Empty",
-      };
-  }

+  function validateNewsletterFormData({ name, email }: NewsletterFormData): boolean {
+    if (!name || !email) {
+      // Show error message about empty fields
+      return false;
+    }
+    return true;
+  }
+
+  async function handleSubscribe(
+    e: FormEvent<HTMLFormElement>,
+    formData: NewsletterFormData
+  ): Promise<SubscribeMessage> {
+    e.preventDefault();
+
+    try {
+      await subscribeUser(formData.name, formData.email);
+      setModalVisible(true);
+      return {
+        isSuccess: true,
+      };
+    } catch (error) {
+      // Assume error.message is set appropriately in subscribeUser
+      return {
+        isSuccess: false,
+        message: error.message,
+      };
+    }
+  }

Comment on lines +76 to +93
{theme === "light" && (
<>
<div className="absolute top-[204px] z-0 w-full h-[460px]">
<Image
src="/main-background.png"
alt="background image"
fill
/>
</div>
<Image
src="/flower.svg"
alt="flower"
width={365}
height={150}
className="absolute top-[54%] left-[50%] -translate-x-2/4"
/>
</>
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Image description CodeRabbit

The conditional rendering based on the theme value is a good practice for theme-based UI changes. However, it's not clear why the Image components are only rendered for the light theme. If they should also be rendered for other themes, consider moving them outside of the conditional block. If they're specific to the light theme, this is fine as is.

@samanyougarg samanyougarg merged commit 385ed99 into main Aug 14, 2023
9 checks passed
@samanyougarg samanyougarg deleted the newsletter-subscription branch August 14, 2023 12:04
@Gupta-Anubhav12 Gupta-Anubhav12 restored the newsletter-subscription branch September 3, 2023 13:00
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.

2 participants