From cf23f12075212a9f405525c449678036ac20b903 Mon Sep 17 00:00:00 2001 From: akshat Date: Fri, 2 Feb 2024 15:23:35 +0530 Subject: [PATCH] feat: resend integrated feedback form --- .env.example | 3 +- package.json | 2 + pnpm-lock.yaml | 215 +++++++++++++++++++++++ public/email-x.png | Bin 0 -> 12132 bytes src/app/api/send/route.ts | 38 ++++ src/app/contact-us/page.tsx | 34 ++-- src/components/EmailTemplate.tsx | 171 ++++++++++++++++++ src/components/FeedbackForm.tsx | 133 +++++++------- src/components/StudyMaterial.tsx | 38 ++-- src/components/modals/feedback-modal.tsx | 28 ++- src/components/providers/providers.tsx | 2 + src/components/ui/alert.tsx | 5 +- src/components/ui/sonner.tsx | 30 ++++ src/hooks/use-feedback.ts | 4 - src/lib/schemas.ts | 5 +- 15 files changed, 597 insertions(+), 111 deletions(-) create mode 100644 public/email-x.png create mode 100644 src/app/api/send/route.ts create mode 100644 src/components/EmailTemplate.tsx create mode 100644 src/components/ui/sonner.tsx diff --git a/.env.example b/.env.example index 7f05f9a..ece6080 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ CONTENTFUL_SPACE_ID= -CONTENTFUL_ACCESS_TOKEN= \ No newline at end of file +CONTENTFUL_ACCESS_TOKEN= +RESEND_API_KEY= \ No newline at end of file diff --git a/package.json b/package.json index 12d5006..2f1da77 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", + "@react-email/components": "^0.0.14", "@tailwindcss/typography": "^0.5.10", "@tanstack/query-sync-storage-persister": "^5.8.3", "@tanstack/react-query": "^5.8.4", @@ -65,6 +66,7 @@ "react-hook-form": "^7.49.3", "react-textarea-autosize": "^8.5.3", "resend": "^3.1.0", + "sonner": "^1.4.0", "tailwind-merge": "^2.0.0", "tailwindcss": "3.3.5", "tailwindcss-animate": "^1.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f09f6bf..dd18e1e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ dependencies: '@radix-ui/react-tooltip': specifier: ^1.0.7 version: 1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@react-email/components': + specifier: ^0.0.14 + version: 0.0.14(@types/react@18.2.37)(react@18.2.0) '@tailwindcss/typography': specifier: ^0.5.10 version: 0.5.10(tailwindcss@3.3.5) @@ -149,6 +152,9 @@ dependencies: resend: specifier: ^3.1.0 version: 3.1.0 + sonner: + specifier: ^1.4.0 + version: 1.4.0(react-dom@18.2.0)(react@18.2.0) tailwind-merge: specifier: ^2.0.0 version: 2.2.0 @@ -2170,6 +2176,164 @@ packages: '@babel/runtime': 7.23.8 dev: false + /@react-email/body@0.0.7(react@18.2.0): + resolution: {integrity: sha512-vjJ5P1MUNWV0KNivaEWA6MGj/I3c764qQJMsKjCHlW6mkFJ4SXbm2OlQFtKAb++Bj8LDqBlnE6oW77bWcMc0NA==} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/button@0.0.13(react@18.2.0): + resolution: {integrity: sha512-e/y8u2odJ8fF83B+wvL2FXzVcbQSUh2Cn2JH2Ez4L6AuPELsh8s2JYo081IDsXc16IyFiYpObn0blOt7s/qp8g==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/code-block@0.0.2(react@18.2.0): + resolution: {integrity: sha512-bQApEmpsvIcVYXdPCXhJB9CGCyShhn/c1JdctE/6R1uIosLbWt40evvVfp2X9STdi02Dhsjxw/AcGuQE6zGZqw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + prismjs: 1.29.0 + react: 18.2.0 + dev: false + + /@react-email/code-inline@0.0.1(react@18.2.0): + resolution: {integrity: sha512-SeZKTB9Q4+TUafzeUm/8tGK3dFgywUHb1od/BrAiJCo/im65aT+oJfggJLjK2jCdSsus8odcK2kReeM3/FCNTQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/column@0.0.9(react@18.2.0): + resolution: {integrity: sha512-1ekqNBgmbS6m97/sUFOnVvQtLYljUWamw8Y44VId95v6SjiJ4ca+hMcdOteHWBH67xkRofEOWTvqDRea5SBV8w==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/components@0.0.14(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-t/sNj0R9Mx9Sx5degPQcSBeWotNs7eUwiv72KN8v6fxaf87XlnMo0CPcKI/1by2DHZr5S0258ZQOO7vEFrbcLw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + '@react-email/body': 0.0.7(react@18.2.0) + '@react-email/button': 0.0.13(react@18.2.0) + '@react-email/code-block': 0.0.2(react@18.2.0) + '@react-email/code-inline': 0.0.1(react@18.2.0) + '@react-email/column': 0.0.9(react@18.2.0) + '@react-email/container': 0.0.11(react@18.2.0) + '@react-email/font': 0.0.5(react@18.2.0) + '@react-email/head': 0.0.7(react@18.2.0) + '@react-email/heading': 0.0.11(@types/react@18.2.37)(react@18.2.0) + '@react-email/hr': 0.0.7(react@18.2.0) + '@react-email/html': 0.0.7(react@18.2.0) + '@react-email/img': 0.0.7(react@18.2.0) + '@react-email/link': 0.0.7(react@18.2.0) + '@react-email/preview': 0.0.8(react@18.2.0) + '@react-email/render': 0.0.12 + '@react-email/row': 0.0.7(react@18.2.0) + '@react-email/section': 0.0.11(react@18.2.0) + '@react-email/tailwind': 0.0.14(react@18.2.0) + '@react-email/text': 0.0.7(react@18.2.0) + react: 18.2.0 + transitivePeerDependencies: + - '@types/react' + dev: false + + /@react-email/container@0.0.11(react@18.2.0): + resolution: {integrity: sha512-jzl/EHs0ClXIRFamfH+NR/cqv4GsJJscqRhdYtnWYuRAsWpKBM1muycrrPqIVhWvWi6sFHInWTt07jX+bDc3SQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/font@0.0.5(react@18.2.0): + resolution: {integrity: sha512-if/qKYmH3rJ2egQJoKbV8SfKCPavu+ikUq/naT/UkCr8Q0lkk309tRA0x7fXG/WeIrmcipjMzFRGTm2TxTecDw==} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/head@0.0.7(react@18.2.0): + resolution: {integrity: sha512-IcXL4jc0H1qzAXJCD9ajcRFBQdbUHkjKJyiUeogpaYSVZSq6cVDWQuGaI23TA9k+pI2TFeQimogUFb3Kgeeudw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/heading@0.0.11(@types/react@18.2.37)(react@18.2.0): + resolution: {integrity: sha512-EF5ZtRCxhHPw3m+8iibKKg0RAvAeHj1AP68sjU7s6+J+kvRgllr/E972Wi5Y8UvcIGossCvpX1WrSMDzeB4puA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.37)(react@18.2.0) + react: 18.2.0 + transitivePeerDependencies: + - '@types/react' + dev: false + + /@react-email/hr@0.0.7(react@18.2.0): + resolution: {integrity: sha512-8suK0M/deXHt0DBSeKhSC4bnCBCBm37xk6KJh9M0/FIKlvdltQBem52YUiuqVl1XLB87Y6v6tvspn3SZ9fuxEA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/html@0.0.7(react@18.2.0): + resolution: {integrity: sha512-oy7OoRtoOKApVI/5Lz1OZptMKmMYJu9Xn6+lOmdBQchAuSdQtWJqxhrSj/iI/mm8HZWo6MZEQ6SFpfOuf8/P6Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/img@0.0.7(react@18.2.0): + resolution: {integrity: sha512-up9tM2/dJ24u/CFjcvioKbyGuPw1yeJg605QA7VkrygEhd0CoQEjjgumfugpJ+VJgIt4ZjT9xMVCK5QWTIWoaA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/link@0.0.7(react@18.2.0): + resolution: {integrity: sha512-hXPChT3ZMyKnUSA60BLEMD2maEgyB2A37yg5bASbLMrXmsExHi6/IS1h2XiUPLDK4KqH5KFaFxi2cdNo1JOKwA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/preview@0.0.8(react@18.2.0): + resolution: {integrity: sha512-Jm0KUYBZQd2w0s2QRMQy0zfHdo3Ns+9bYSE1OybjknlvhANirjuZw9E5KfWgdzO7PyrRtB1OBOQD8//Obc4uIQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + /@react-email/render@0.0.12: resolution: {integrity: sha512-S8WRv/PqECEi6x0QJBj0asnAb5GFtJaHlnByxLETLkgJjc76cxMYDH4r9wdbuJ4sjkcbpwP3LPnVzwS+aIjT7g==} engines: {node: '>=18.0.0'} @@ -2180,6 +2344,42 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@react-email/row@0.0.7(react@18.2.0): + resolution: {integrity: sha512-h7pwrLVGk5CIx7Ai/oPxBgCCAGY7BEpCUQ7FCzi4+eThcs5IdjSwDPefLEkwaFS8KZc56UNwTAH92kNq5B7blg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/section@0.0.11(react@18.2.0): + resolution: {integrity: sha512-3bZ/DuvX1julATI7oqYza6pOtWZgLJDBaa62LFFEvYjisyN+k6lrP2KOucPsDKu2DOkUzlQgK0FOm6VQJX+C0w==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/tailwind@0.0.14(react@18.2.0): + resolution: {integrity: sha512-SRRcm08zxrAR5XozaW0X+GAJlTJITakZe0UXBiFZDlSDBLwFMxjaGuQwccqNF0LxDnxmduxYB71mzEAqecgTZg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + + /@react-email/text@0.0.7(react@18.2.0): + resolution: {integrity: sha512-eHCx0mdllGcgK9X7wiLKjNZCBRfxRVNjD3NNYRmOc3Icbl8M9JHriJIfxBuGCmGg2UAORK5P3KmaLQ8b99/pbA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: 18.2.0 + dependencies: + react: 18.2.0 + dev: false + /@rushstack/eslint-patch@1.7.0: resolution: {integrity: sha512-Jh4t/593gxs0lJZ/z3NnasKlplXT2f+4y/LZYuaKZW5KAaiVFL/fThhs+17EbUd53jUVJ0QudYCBGbN/psvaqg==} dev: false @@ -5395,6 +5595,11 @@ packages: hasBin: true dev: true + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -5838,6 +6043,16 @@ packages: yargs: 15.4.1 dev: true + /sonner@1.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nvkTsIuOmi9e5Wz5If8ldasJjZNVfwiXYijBi2dbijvTQnQppvMcXTFNxL/NUFWlI2yJ1JX7TREDsg+gYm9WyA==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} diff --git a/public/email-x.png b/public/email-x.png new file mode 100644 index 0000000000000000000000000000000000000000..d4666047a6c2fd0f9724d5fd27397a1a2c3f298c GIT binary patch literal 12132 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 a@&5q(a`Xh#bI->B0000", + to: ["iboard990@gmail.com"], + subject: "New response has arrived", + react: EmailAdminTemplate( + validatedFormFields + ) as React.ReactElement, + }), + resend.emails.send({ + from: "SyllabusX ", + to: [validatedFormFields.email], + subject: "Thanks for the feedback", + react: EmailTemplate({ + name: validatedFormFields.name, + }) as React.ReactElement, + }), + ]); + return Response.json(data); + } catch (error) { + return Response.json({ error }); + } +} diff --git a/src/app/contact-us/page.tsx b/src/app/contact-us/page.tsx index 0424d74..fd9db81 100644 --- a/src/app/contact-us/page.tsx +++ b/src/app/contact-us/page.tsx @@ -50,25 +50,23 @@ const Page: FC = ({}) => {

-
- + ); diff --git a/src/components/EmailTemplate.tsx b/src/components/EmailTemplate.tsx new file mode 100644 index 0000000..213a87c --- /dev/null +++ b/src/components/EmailTemplate.tsx @@ -0,0 +1,171 @@ +import { cn } from "@/lib/utils"; +import { + Body, + Container, + Head, + Heading, + Hr, + Html, + Img, + Link, + Preview, + Row, + Section, + Tailwind, + Text, +} from "@react-email/components"; +import { GeistSans } from "geist/font/sans"; +import { FC } from "react"; + +const baseUrl = process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : ""; + +interface EmailTemplateProps { + name: string; +} + +const EmailTemplate: FC = ({ name }) => { + return ( + + + Acknowledgment of Your Feedback on SyllabusX + + + We've received your feedback! Our team is on it. + + + + +
+ SyllabusX +
+ + Thanks for the feedback + + + Hello {name}, + + + Thank you for taking the time to provide valuable + feedback to SyllabusX! Your input is important to + us, and we appreciate your effort in helping us + enhance our platform. + + + Please rest assured that your concerns or + suggestions will be carefully considered. We aim to + address and respond to your feedback promptly. + + + If you have any additional thoughts or questions, + please feel free to reach out to us at{" "} + + iboard990@gmail.com + + . We're here to assist you and ensure that + SyllabusX continues to meet your expectations. + +
+
+ +
+ + ); +}; + +export function EmailAdminTemplate({ + name, + email, + college, + course, + semester, + branch, + query, +}: { + name: string; + email: string; + college: string; + course: string; + semester: string; + branch: string; + query: string; +}) { + return ( + + + New form response + + {name} submitted the feedback form + + + +
+ SyllabusX +
+ + A new response has arrived. + + + Form submitted by {name} + + + Here's what {name} wrote + + + {query} + +
+
+ + + Email: {email} + + + College: {college} + + + Course: {course} + + + Semester: {semester} + + + Branch: {branch} + + +
+
+
+ +
+ + ); +} + +export default EmailTemplate; diff --git a/src/components/FeedbackForm.tsx b/src/components/FeedbackForm.tsx index d22a49f..5d67133 100644 --- a/src/components/FeedbackForm.tsx +++ b/src/components/FeedbackForm.tsx @@ -4,8 +4,10 @@ import { useFeedback } from "@/hooks/use-feedback"; import { FeedbackSchema, TFeedbackSchema } from "@/lib/schemas"; import { cn } from "@/lib/utils"; import { zodResolver } from "@hookform/resolvers/zod"; -import { CornerRightUp, UploadCloud } from "lucide-react"; +import axios from "axios"; +import { CornerRightUp, MessageSquare, UploadCloud } from "lucide-react"; import { useForm } from "react-hook-form"; +import { toast } from "sonner"; import { Alert, AlertDescription, AlertTitle } from "./ui/alert"; import { Button, buttonVariants } from "./ui/button"; import { @@ -27,24 +29,26 @@ const FeedbackForm = ({}) => { const form = useForm({ resolver: zodResolver(FeedbackSchema), - defaultValues: { - name: "", - email: "", - branch: "", - semester: 1, - college: "", - course: "", - query: feedback.query, - }, }); - const onSubmit = (values: TFeedbackSchema) => {}; + const onSubmit = async (values: TFeedbackSchema) => { + toast.promise(axios.post("/api/send", { values }), { + loading: "Submitting...", + success: () => { + return "Form submitted!"; + }, + error: "Something went wrong! Try again later", + }); + }; return ( -
- - -
+ <> + + + { Name - + - Your good name. + The title of your autobiography. @@ -65,13 +72,16 @@ const FeedbackForm = ({}) => { control={form.control} name="email" render={({ field }) => ( - + Email - + - Your email so we can spam you. + Your mail so we can spam. @@ -81,13 +91,13 @@ const FeedbackForm = ({}) => { control={form.control} name="college" render={({ field }) => ( - + College / Institution - + - Your college / institution name. + The academic HQ you call home. @@ -97,13 +107,17 @@ const FeedbackForm = ({}) => { control={form.control} name="course" render={({ field }) => ( - + Course - + - Really? You chose this? + Your academic journey's chosen + path. @@ -114,12 +128,12 @@ const FeedbackForm = ({}) => { name="semester" render={({ field }) => ( - Semester + Course - + - Your current semester. + Your academic chapter number. @@ -132,10 +146,10 @@ const FeedbackForm = ({}) => { Branch - + - Your current branch. + Your academic superhero identity. @@ -145,20 +159,25 @@ const FeedbackForm = ({}) => { control={form.control} name="query" render={({ field }) => ( - - Query + + Branch -