From e4f64294a3d638de7534a20a04dbac05ef3247e5 Mon Sep 17 00:00:00 2001 From: mde3 Date: Mon, 23 Dec 2024 10:44:55 +0300 Subject: [PATCH] chore: removed email.js, now entirely using resend --- apps/website/.env.example | 6 +- apps/website/src/app/_action.ts | 45 ++++++++- .../shared/partners/PartnerBusiness.tsx | 39 ++------ .../shared/partners/PartnerCourier.tsx | 43 ++------- .../shared/partners/PartnerSupplier.tsx | 44 ++------- .../src/components/shared/partners/type.ts | 4 +- apps/website/src/emails/partner-message.tsx | 95 +++++++++++++++++++ .../website/src/lib/{schema.tsx => schema.ts} | 19 +--- 8 files changed, 170 insertions(+), 125 deletions(-) create mode 100644 apps/website/src/emails/partner-message.tsx rename apps/website/src/lib/{schema.tsx => schema.ts} (62%) diff --git a/apps/website/.env.example b/apps/website/.env.example index 324aa870..2dfd2fca 100644 --- a/apps/website/.env.example +++ b/apps/website/.env.example @@ -1,4 +1,4 @@ RESEND_API_KEY= -NEXT_PUBLIC_SERVICE_ID= -NEXT_PUBLIC_TEMPLATE_ID_BUSINESS= -NEXT_PUBLIC_PUBLIC_KEY= +RESEND_FROM_DOMAIN_EMAIL= +RESEND_REPLY_TO_EMAIL= +RESEND_TO_EMAIL= \ No newline at end of file diff --git a/apps/website/src/app/_action.ts b/apps/website/src/app/_action.ts index af5fe3c7..65872ef3 100644 --- a/apps/website/src/app/_action.ts +++ b/apps/website/src/app/_action.ts @@ -3,6 +3,7 @@ import { Resend } from "resend"; import { basePartnerSchema } from "@/lib/schema"; import PartnerEmail from "@/emails/partners"; import { FormInputType } from "@/components/shared/partners/type"; +import PartnerMessage from "@/emails/partner-message"; const resend = new Resend(process.env.RESEND_API_KEY) @@ -13,10 +14,9 @@ export async function sendEmail(data: FormInputType) { const { name, email } = result.data try { const data = await resend.emails.send({ - // from: `Sahil <${process.env.RESEND_FROM_EMAIL}>`, - from: 'Sahil ', - // to: [email], - to: ['mabiorduom5@gmail.com'], + from: `Sahil <${process.env.RESEND_FROM_DOMAIN_EMAIL}>`, + to: [email], + replyTo: `${process.env.RESEND_REPLY_TO_EMAIL}`, subject: 'Partnering with Sahil', text: `Name: ${name}\nEmail: ${email}`, react: PartnerEmail({ name }) @@ -31,3 +31,40 @@ export async function sendEmail(data: FormInputType) { return { success: false, error: result.error.format() } } } + +export async function storeUserDetails(data: FormInputType) { + const result = basePartnerSchema.safeParse(data) + + if (result.success) { + const { + name, + email, + phoneNumber, + companyName, + supplyDetails, + vehicleDetails + } = result.data + + try { + const data = await resend.emails.send({ + from: `Sahil <${process.env.RESEND_FROM_DOMAIN_EMAIL}>`, + to: `${process.env.RESEND_TO_EMAIL}`, + subject: `New Partner Submission from ${name}`, + react: PartnerMessage({ + name, + email, + phoneNumber, + companyName, + supplyDetails, + vehicleDetails + }) + }) + return { success: true, data } + } catch (error) { + return { success: false, error } + } + } + if (result.error) { + return { success: false, error: result.error.format() } + } +} diff --git a/apps/website/src/components/shared/partners/PartnerBusiness.tsx b/apps/website/src/components/shared/partners/PartnerBusiness.tsx index 92752aa1..2dfaa253 100644 --- a/apps/website/src/components/shared/partners/PartnerBusiness.tsx +++ b/apps/website/src/components/shared/partners/PartnerBusiness.tsx @@ -2,12 +2,11 @@ import { useState } from "react"; import { useForm, SubmitHandler } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { businessPartnerSchema } from "@/lib/schema"; +import { basePartnerSchema } from "@/lib/schema"; import { Input } from "../Form"; import { HiOutlineArrowUpRight } from "react-icons/hi2"; import { FormInputType } from "./type"; -import { sendEmail } from "@/app/_action"; -import emailjs from '@emailjs/browser'; +import { sendEmail, storeUserDetails } from "@/app/_action"; export const PartnerBusiness = () => { const { @@ -16,7 +15,7 @@ export const PartnerBusiness = () => { reset, formState: {errors, isSubmitting} } = useForm({ - resolver: zodResolver(businessPartnerSchema), + resolver: zodResolver(basePartnerSchema), }) const [submissionStatus, setSubmissionStatus] = useState<{ @@ -34,10 +33,10 @@ export const PartnerBusiness = () => { try { // first, send email via Resend const resendResult = await sendEmail(data); - // then, send email via Email.js - const emailJsResult = await sendEmailViaEmailJs(data); + // store user details + const storeResult = await storeUserDetails(data); - if (resendResult?.success && emailJsResult) { + if (resendResult?.success && storeResult) { setSubmissionStatus({ type: 'success', message: 'Message sent successfully!' @@ -58,30 +57,6 @@ export const PartnerBusiness = () => { } } - // helper function to send email via Email.js - const sendEmailViaEmailJs = async (data: FormInputType): Promise => { - try { - await emailjs.send( - process.env.NEXT_PUBLIC_SERVICE_ID!, - process.env.NEXT_PUBLIC_TEMPLATE_ID_BUSINESS!, - { - // map form data to Email.js template fields - user_name: data.name, - user_email: data.email, - user_phone: data.phoneNumber.toString(), - user_company: data.companyName, - }, - { - publicKey: process.env.NEXT_PUBLIC_PUBLIC_KEY!, - } - ); - return true; - } catch (error) { - console.error('Email.js send error:', error); - return false; - } - } - return (
@@ -137,7 +112,7 @@ export const PartnerBusiness = () => { group inline-flex items-center justify-center gap-2 rounded-full px-6 py-3 text-sm text-white font-semibold transition-colors ${ isSubmitting - ? 'bg-gray-400 cursor-not-allowed' + ? 'bg-gray-400 text-white cursor-not-allowed' : 'bg-primary hover:bg-secondary' } `} diff --git a/apps/website/src/components/shared/partners/PartnerCourier.tsx b/apps/website/src/components/shared/partners/PartnerCourier.tsx index bfb445cb..8feb7cf4 100644 --- a/apps/website/src/components/shared/partners/PartnerCourier.tsx +++ b/apps/website/src/components/shared/partners/PartnerCourier.tsx @@ -2,12 +2,11 @@ import { useState } from "react"; import { useForm, SubmitHandler } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { courierPartnerSchema, mappedVehicleStatuses } from "@/lib/schema"; +import { basePartnerSchema, mappedVehicleStatuses } from "@/lib/schema"; import { Input, Select } from "../Form"; import { HiOutlineArrowUpRight } from "react-icons/hi2"; import { FormInputType } from "./type"; -import { sendEmail } from "@/app/_action"; -import emailjs from '@emailjs/browser'; +import { sendEmail, storeUserDetails } from "@/app/_action"; export const PartnerCourier = () => { const { @@ -16,7 +15,7 @@ export const PartnerCourier = () => { reset, formState: {errors, isSubmitting} } = useForm({ - resolver: zodResolver(courierPartnerSchema), + resolver: zodResolver(basePartnerSchema), }) const [submissionStatus, setSubmissionStatus] = useState<{ @@ -38,10 +37,10 @@ export const PartnerCourier = () => { try { // first, send email via Resend const resendResult = await sendEmail(data); - // then, send email via Email.js - const emailJsResult = await sendEmailViaEmailJs(data); + // store user details + const storeResult = await storeUserDetails(data); - if (resendResult?.success && emailJsResult) { + if (resendResult?.success && storeResult) { setSubmissionStatus({ type: 'success', message: 'Message sent successfully!' @@ -62,30 +61,6 @@ export const PartnerCourier = () => { } } - // helper function to send email via Email.js - const sendEmailViaEmailJs = async (data: FormInputType): Promise => { - try { - await emailjs.send( - process.env.NEXT_PUBLIC_SERVICE_ID!, - process.env.NEXT_PUBLIC_TEMPLATE_ID_BUSINESS!, - { - // map form data to Email.js template fields - user_name: data.name, - user_email: data.email, - user_phone: data.phoneNumber.toString(), - user_vehicle_status: data.vehicleDetails - }, - { - publicKey: process.env.NEXT_PUBLIC_PUBLIC_KEY!, - } - ); - return true; - } catch (error) { - console.error('Email.js send error:', error); - return false; - } - } - return (
@@ -138,11 +113,11 @@ export const PartnerCourier = () => { type="submit" disabled={isSubmitting} className={` - group inline-flex items-center justify-center gap-2 rounded-full px-6 py-3 text-sm font-semibold transition-colors + group inline-flex items-center justify-center gap-2 rounded-full px-6 py-3 text-sm text-white font-semibold transition-colors ${ isSubmitting - ? 'bg-gray-400 text-black cursor-not-allowed' - : 'bg-primary text-white hover:bg-secondary' + ? 'bg-gray-400 text-white cursor-not-allowed' + : 'bg-primary hover:bg-secondary' } `} > diff --git a/apps/website/src/components/shared/partners/PartnerSupplier.tsx b/apps/website/src/components/shared/partners/PartnerSupplier.tsx index 7a8bfe20..48bac11d 100644 --- a/apps/website/src/components/shared/partners/PartnerSupplier.tsx +++ b/apps/website/src/components/shared/partners/PartnerSupplier.tsx @@ -2,12 +2,11 @@ import { useState } from "react"; import { useForm, SubmitHandler } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { supplierPartnerSchema } from "@/lib/schema"; +import { basePartnerSchema } from "@/lib/schema"; import { Input, TextArea } from "../Form"; import { HiOutlineArrowUpRight } from "react-icons/hi2"; import { FormInputType } from "./type"; -import { sendEmail } from "@/app/_action"; -import emailjs from '@emailjs/browser'; +import { sendEmail, storeUserDetails } from "@/app/_action"; export const PartnerSupplier = () => { const { @@ -16,7 +15,7 @@ export const PartnerSupplier = () => { reset, formState: {errors, isSubmitting} } = useForm({ - resolver: zodResolver(supplierPartnerSchema), + resolver: zodResolver(basePartnerSchema), }) const [submissionStatus, setSubmissionStatus] = useState<{ @@ -34,10 +33,10 @@ export const PartnerSupplier = () => { try { // first, send email via Resend const resendResult = await sendEmail(data); - // then, send email via Email.js - const emailJsResult = await sendEmailViaEmailJs(data); + // store user details + const storeResult = await storeUserDetails(data); - if (resendResult?.success && emailJsResult) { + if (resendResult?.success && storeResult) { setSubmissionStatus({ type: 'success', message: 'Message sent successfully!' @@ -58,31 +57,6 @@ export const PartnerSupplier = () => { } } - // helper function to send email via Email.js - const sendEmailViaEmailJs = async (data: FormInputType): Promise => { - try { - await emailjs.send( - process.env.NEXT_PUBLIC_SERVICE_ID!, - process.env.NEXT_PUBLIC_TEMPLATE_ID_BUSINESS!, - { - // map form data to Email.js template fields - user_name: data.name, - user_email: data.email, - user_phone: data.phoneNumber.toString(), - user_company: data.companyName, - user_message: `Supply Details: ${data.supplyDetails}` - }, - { - publicKey: process.env.NEXT_PUBLIC_PUBLIC_KEY!, - } - ); - return true; - } catch (error) { - console.error('Email.js send error:', error); - return false; - } - } - return (
@@ -142,11 +116,11 @@ export const PartnerSupplier = () => { type="submit" disabled={isSubmitting} className={` - group inline-flex items-center justify-center gap-2 rounded-full px-6 py-3 text-sm font-semibold transition-colors + group inline-flex items-center justify-center gap-2 rounded-full px-6 py-3 text-sm text-white font-semibold transition-colors ${ isSubmitting - ? 'bg-gray-400 text-black cursor-not-allowed' - : 'bg-primary text-white hover:bg-secondary' + ? 'bg-gray-400 text-white cursor-not-allowed' + : 'bg-primary hover:bg-secondary' } `} > diff --git a/apps/website/src/components/shared/partners/type.ts b/apps/website/src/components/shared/partners/type.ts index 324c536c..acf020cd 100644 --- a/apps/website/src/components/shared/partners/type.ts +++ b/apps/website/src/components/shared/partners/type.ts @@ -1,5 +1,5 @@ -import { z } from "zod"; -import { businessPartnerSchema, courierPartnerSchema, supplierPartnerSchema } from "@/lib/schema"; +// import { z } from "zod"; +// import { businessPartnerSchema, courierPartnerSchema, supplierPartnerSchema } from "@/lib/schema"; export type FormInputType = { name: string; diff --git a/apps/website/src/emails/partner-message.tsx b/apps/website/src/emails/partner-message.tsx new file mode 100644 index 00000000..08d98145 --- /dev/null +++ b/apps/website/src/emails/partner-message.tsx @@ -0,0 +1,95 @@ +import { + Body, + Container, + Head, + Heading, + Hr, + Html, + Img, + Preview, + Section, + Text, + Tailwind, +} from "@react-email/components"; +import * as React from "react"; + +interface PartnerMessageProps { + name: string; + email: string; + phoneNumber: string; + companyName?: string; + supplyDetails?: string; + vehicleDetails?: string; +} + +export const PartnerMessage = ({ + name, + email, + phoneNumber, + companyName, + supplyDetails, + vehicleDetails, +}: PartnerMessageProps) => ( + + + + Your one-stop logistics platform. + + + + + +
+ Sahil App +
+
+ + Your received a message from {name} + + + Full name: {name} + + + Email address: {email} + + + Phone number: {phoneNumber} + + {companyName && + + Company name: {companyName} + + } + {supplyDetails && + + Supply details: {supplyDetails} + + } + {vehicleDetails && + + Vehicle status: {vehicleDetails} + + } +
+ +
+
+
+ + © 2024 Sahil – Company Ltd. All Rights Reserved. | + Norrsken House Kigali, 1 KN 78 St, Kigali-Rwanda + +
+
+
+ +
+ +); + +export default PartnerMessage; diff --git a/apps/website/src/lib/schema.tsx b/apps/website/src/lib/schema.ts similarity index 62% rename from apps/website/src/lib/schema.tsx rename to apps/website/src/lib/schema.ts index 9bda7445..b4f0022e 100644 --- a/apps/website/src/lib/schema.tsx +++ b/apps/website/src/lib/schema.ts @@ -21,22 +21,11 @@ export const basePartnerSchema = z.object({ name: z.string().min(3, 'Must be at least 3 characters'), email: z.string().email({message: "Email is required"}), phoneNumber: z.string().regex(phoneRegex, 'Phone number is required'), -}); - -export const businessPartnerSchema = basePartnerSchema.extend({ - companyName: z.string().min(3, 'Must be at least 3 characters'), -}); - -export const supplierPartnerSchema = basePartnerSchema.extend({ - companyName: z.string().min(3, 'Must be at least 3 characters'), + companyName: z.string().min(3, 'Must be at least 3 characters').optional(), supplyDetails: z .string() .min(3, {message: 'Must be at least 3 characters'}) - .max(250, {message: 'Must not exceed 250 characters'}), -}); - -export const courierPartnerSchema = basePartnerSchema.extend({ - vehicleDetails: z.enum(vehicleStatuses, { - errorMap: () => ({ message: 'Please select your vehicle status' }), - }), + .max(250, {message: 'Must not exceed 250 characters'}) + .optional(), + vehicleDetails: z.enum(vehicleStatuses).optional(), });