From 053f17610cbf783be7fe8d1509c77a69a15ca7d1 Mon Sep 17 00:00:00 2001 From: thePeras Date: Fri, 24 Jan 2025 15:44:02 +0000 Subject: [PATCH 1/2] fix: request emails improvements --- .env.example | 5 ++ .../requests}/DatePickerComponent.tsx | 0 .../(aefeup)/requests}/MaterialSelector.tsx | 2 +- .../(site)/(aefeup)/requests/RequestTab.tsx | 45 ++++++++++++++---- app/(site)/(aefeup)/requests/calendar.tsx | 47 +++++++++++++++++++ app/(site)/(aefeup)/requests/page.tsx | 25 ++-------- app/(site)/contact/page.tsx | 5 ++ components/Calendar/index.tsx | 44 ----------------- components/Contact/index.tsx | 2 +- lib/sendEmail.ts | 27 +++++++++++ 10 files changed, 126 insertions(+), 76 deletions(-) rename {components/RequestTab => app/(site)/(aefeup)/requests}/DatePickerComponent.tsx (100%) rename {components/RequestTab => app/(site)/(aefeup)/requests}/MaterialSelector.tsx (96%) rename components/RequestTab/index.tsx => app/(site)/(aefeup)/requests/RequestTab.tsx (89%) create mode 100644 app/(site)/(aefeup)/requests/calendar.tsx delete mode 100644 components/Calendar/index.tsx create mode 100644 lib/sendEmail.ts diff --git a/.env.example b/.env.example index 049da18..d41bea5 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,10 @@ PAYLOAD_SECRET=jawliejfilwajefSEANlawefawfewag349jwgo3gj4d POSTGRES_URL=postgresql://postgres:@127.0.0.1:5432/ + GOOGLE_CALENDAR_API_KEY= GOOGLE_CALENDAR_ID= + +RESEND_API_KEY= RESEND_EMAIL= + +#PROD=1 Only if you are running in production diff --git a/components/RequestTab/DatePickerComponent.tsx b/app/(site)/(aefeup)/requests/DatePickerComponent.tsx similarity index 100% rename from components/RequestTab/DatePickerComponent.tsx rename to app/(site)/(aefeup)/requests/DatePickerComponent.tsx diff --git a/components/RequestTab/MaterialSelector.tsx b/app/(site)/(aefeup)/requests/MaterialSelector.tsx similarity index 96% rename from components/RequestTab/MaterialSelector.tsx rename to app/(site)/(aefeup)/requests/MaterialSelector.tsx index 434aef0..1d3ee8c 100644 --- a/components/RequestTab/MaterialSelector.tsx +++ b/app/(site)/(aefeup)/requests/MaterialSelector.tsx @@ -4,7 +4,7 @@ import { Inbox } from "lucide-react"; import { X } from "lucide-react"; import { useState } from "react"; -import MultipleSelector, { Option } from '../ui/multiple-selector'; +import MultipleSelector, { Option } from '../../../../components/ui/multiple-selector'; interface Props { materialData: Material[] diff --git a/components/RequestTab/index.tsx b/app/(site)/(aefeup)/requests/RequestTab.tsx similarity index 89% rename from components/RequestTab/index.tsx rename to app/(site)/(aefeup)/requests/RequestTab.tsx index e55475e..0ed8840 100644 --- a/components/RequestTab/index.tsx +++ b/app/(site)/(aefeup)/requests/RequestTab.tsx @@ -1,21 +1,44 @@ 'use client' -import { useEffect, useRef, useState } from "react" -import SectionHeader from "../Common/SectionHeader"; +import { useEffect, useState } from "react" +import SectionHeader from "../../../../components/Common/SectionHeader"; import { EventRequestInfo } from "@/types/eventRequestInfo"; import { SingleMaterialRequest } from "@/types/singleMaterialRequest"; import { Material } from "@/types/material"; import DatePickerComponent from "./DatePickerComponent"; import MaterialSelector from "./MaterialSelector"; import { Space } from "@/payload-types"; +import EmailTemplate from "@/emails"; +import { sendEmail } from "@/lib/sendEmail"; +import toast, { Toaster } from "react-hot-toast"; +import { render } from "@react-email/render"; interface Props { materialData: Material[], - sendEmail: (eventRequest: EventRequestInfo) => void, availableSpaces: Space[] } -export default function RequestTab({ materialData, sendEmail, availableSpaces }: Props) { +const sendEmailRequest = async (requestInfo: EventRequestInfo) => { + const emailString = await render(EmailTemplate({ requestEventInfo: requestInfo })); + const { data, error } = await sendEmail( + requestInfo.email, + 'gta@aefeup.pt', + `${requestInfo.isEvent ? "Reserva de Espaço" : "Pedido de Material"}`, + emailString, + ) + + if (error) { + console.error(error) + return { error: "Erro ao enviar email" } + } + + if (data) { + return { success: "Email enviado com sucesso" } + } +} + +export default function RequestTab({ materialData, availableSpaces }: Props) { + const [currentTab, setCurrentTab] = useState("tabOne"); const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); @@ -47,7 +70,11 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces }: requestedMaterial: requestedMaterial } - await sendEmail(requestInfo) + if (materialData.length === 0) { + return toast.error("Não há material disponível") + } + + await sendEmailRequest(requestInfo) document.getElementById("material-request-form")?.reset() // TODO: Change this } @@ -70,10 +97,9 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces }: requestedMaterial: requestedMaterial } - await sendEmail(requestInfo) + await sendEmailRequest(requestInfo) document.getElementById("event-request-form")?.reset() // TODO: Change this //TODO: Remove the selected materials - //TODO: Show snack bar } return ( @@ -134,7 +160,7 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces }: @@ -197,6 +223,9 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces }: + ) } diff --git a/app/(site)/(aefeup)/requests/calendar.tsx b/app/(site)/(aefeup)/requests/calendar.tsx new file mode 100644 index 0000000..6d22f3a --- /dev/null +++ b/app/(site)/(aefeup)/requests/calendar.tsx @@ -0,0 +1,47 @@ +'use client' +import FullCalendar from '@fullcalendar/react' +import dayGridPlugin from '@fullcalendar/daygrid' // a plugin! +import googleCalendarPlugin from '@fullcalendar/google-calendar' +import SectionHeader from '../../../../components/Common/SectionHeader' + +const CalendarComponent = ({ calendarID, calendarApiKey }: { calendarID: string | undefined, calendarApiKey: string | undefined }) => { + return ( + <> +
+
+ +
+ { + delete event.url + event.title = event.title ?? "Ocupado" + event.allDay = true + return event + }} + height={700} + /> +
+
+
+ + ) +} + +export default CalendarComponent; \ No newline at end of file diff --git a/app/(site)/(aefeup)/requests/page.tsx b/app/(site)/(aefeup)/requests/page.tsx index 23f2e06..44ff321 100644 --- a/app/(site)/(aefeup)/requests/page.tsx +++ b/app/(site)/(aefeup)/requests/page.tsx @@ -1,12 +1,8 @@ -import CalendarComponent from "@/components/Calendar" +import CalendarComponent from "@/app/(site)/(aefeup)/requests/calendar" import { Metadata } from "next" -import RequestTab from "@/components/RequestTab" +import RequestTab from "@/app/(site)/(aefeup)/requests/RequestTab" import config from "payload.config" import { getPayload } from "payload" -import { Resend } from "resend"; -import { render } from "@react-email/render" -import { EventRequestInfo } from "@/types/eventRequestInfo" -import EmailTemplate from "@/emails" export const metadata: Metadata = { title: "Cedências de Espaço", @@ -26,25 +22,10 @@ export default async function Request() { collection: "space", })).docs - const sendEmail = async (requestInfo: EventRequestInfo) => { - 'use server' - const resend = new Resend(process.env.RESEND_API_KEY) - - if (!requestInfo.isEvent && materialData.length === 0) { - return - } - const { data, error } = await resend.emails.send({ - from: process.env.RESEND_EMAIL ? `AEFEUP <${process.env.RESEND_EMAIL}>` : 'Acme ', - to: [requestInfo.email], - subject: `${requestInfo.isEvent ? "Reserva de Espaço" : "Pedido de Material"}`, - html: await render(EmailTemplate({ requestEventInfo: requestInfo })), - }) - } - return ( <> - + ) } \ No newline at end of file diff --git a/app/(site)/contact/page.tsx b/app/(site)/contact/page.tsx index 174e895..e06ab6d 100644 --- a/app/(site)/contact/page.tsx +++ b/app/(site)/contact/page.tsx @@ -5,6 +5,7 @@ import SuggestionBox from "@/components/Sugestion"; import { getPayload } from "payload"; import config from "payload.config"; import SectionHeader from "@/components/Common/SectionHeader"; +import { Toaster } from "react-hot-toast"; export const metadata: Metadata = { title: "Contacto", @@ -29,6 +30,10 @@ const ContactsPage = () => {
+ + ); } diff --git a/components/Calendar/index.tsx b/components/Calendar/index.tsx deleted file mode 100644 index 2a0f10e..0000000 --- a/components/Calendar/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client' -import FullCalendar from '@fullcalendar/react' -import dayGridPlugin from '@fullcalendar/daygrid' // a plugin! -import googleCalendarPlugin from '@fullcalendar/google-calendar' -import SectionHeader from '../Common/SectionHeader' - -const CalendarComponent = ({calendarID,calendarApiKey} : {calendarID:string | undefined,calendarApiKey:string | undefined}) => { - return ( - <> -
-
- - { - delete event.url - event.allDay=true - return event - }} - height={700} - /> -
-
- - ) -} - -export default CalendarComponent; \ No newline at end of file diff --git a/components/Contact/index.tsx b/components/Contact/index.tsx index c64b1af..d527bf3 100644 --- a/components/Contact/index.tsx +++ b/components/Contact/index.tsx @@ -1,6 +1,6 @@ "use client"; + import { motion } from "framer-motion"; -import Image from "next/image"; import React from "react"; import { Instagram, Facebook, Linkedin } from 'lucide-react'; diff --git a/lib/sendEmail.ts b/lib/sendEmail.ts new file mode 100644 index 0000000..852b397 --- /dev/null +++ b/lib/sendEmail.ts @@ -0,0 +1,27 @@ +'use server' + +import { render } from "@react-email/render" +import { JSX } from "react" +import { Resend } from "resend" + +export const sendEmail = async (from: string, to: string, subject: string, content: string) => { + "use server" + + const resend = new Resend(process.env.RESEND_API_KEY) + + if (!process.env.PROD) { + to = 'projetos.niaefeup@gmail.com' + } + + let serviceAuthor = 'Acme ' + if (process.env.RESEND_EMAIL) serviceAuthor = `AEFEUP <${process.env.RESEND_EMAIL}>` + + return await resend.emails.send({ + from: serviceAuthor, + cc: from, // Sender is notified of the email + replyTo: from, // Sender receives the replies + to: to, + subject: subject, + html: content, + }) +} \ No newline at end of file From 74694a41243f9aa066a5dc80ebf58b5cd9f6e6b8 Mon Sep 17 00:00:00 2001 From: thePeras Date: Fri, 24 Jan 2025 17:11:09 +0000 Subject: [PATCH 2/2] remove contact page --- app/(site)/{contact => _contact}/page.tsx | 0 components/Header/menuData.tsx | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) rename app/(site)/{contact => _contact}/page.tsx (100%) diff --git a/app/(site)/contact/page.tsx b/app/(site)/_contact/page.tsx similarity index 100% rename from app/(site)/contact/page.tsx rename to app/(site)/_contact/page.tsx diff --git a/components/Header/menuData.tsx b/components/Header/menuData.tsx index d6a2bca..7867d6d 100644 --- a/components/Header/menuData.tsx +++ b/components/Header/menuData.tsx @@ -70,7 +70,7 @@ const menuData: Menu[] = [ path: "sport", submenu: [ { - title: "História e Troféus (wip)", + title: "História e Troféus", path: "history" }, { @@ -87,10 +87,10 @@ const menuData: Menu[] = [ title: "Loja (wip)", path: "/store", }, - { - title: "Contactos", - path: "/contact", - }, + //{ + // title: "Contactos", + // path: "/contact", + //}, ]; export default menuData;