Skip to content

Commit

Permalink
Merge pull request #134 from NIAEFEUP/fix/emails
Browse files Browse the repository at this point in the history
fix: emails
  • Loading branch information
vitormpp authored Jan 24, 2025
2 parents 9ada613 + eaff880 commit c3aab9b
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ GOOGLE_CALENDAR_ID=<google-calendar-id>

POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=next-payload-3
POSTGRES_DB=next-payload-3
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
'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 { Docfile, Space } from "@/payload-types";
import { DialogTrigger } from "../ui/dialog";
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";
import { Docfile } from "@/payload-types";
import { DialogTrigger } from "@/components/ui/dialog";

interface Props {
materialData: Material[],
sendEmail: (eventRequest: EventRequestInfo) => void,
availableSpaces: Space[],
regulation?: Docfile,
regulation?: Docfile
}

export default function RequestTab({ materialData, sendEmail, availableSpaces, regulation }: 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, regulation }: Props) {
const [currentTab, setCurrentTab] = useState("tabOne");
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date());
Expand Down Expand Up @@ -49,7 +72,11 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces, r
requestedMaterial: requestedMaterial
}

sendEmail(requestInfo);
if (materialData.length === 0) {
return toast.error("Não há material disponível")
}

await sendEmailRequest(requestInfo);
(document.getElementById("material-request-form") as HTMLFormElement).reset() // TODO: Change this
}

Expand All @@ -72,10 +99,9 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces, r
requestedMaterial: requestedMaterial
}

sendEmail(requestInfo);
await sendEmailRequest(requestInfo);
(document.getElementById("event-request-form") as HTMLFormElement).reset() // TODO: Change this
//TODO: Remove the selected materials
//TODO: Show snack bar
}

return (
Expand Down Expand Up @@ -129,7 +155,7 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces, r
<label htmlFor="space">Espaço <span className="text-primary">*</span></label>
<select name="space" id="space" className="p-3 border bg-white rounded" required>
<option value="" selected hidden>Escolha um lugar</option>
{availableSpaces.map((space: Space) => (
{availableSpaces.map((space) => (
<option value={space.name}>{space.name}</option>
))}
</select>
Expand Down Expand Up @@ -248,6 +274,9 @@ export default function RequestTab({ materialData, sendEmail, availableSpaces, r
</div>
</div>
</section>
<Toaster
position="bottom-right"
/>
</>
)
}
47 changes: 47 additions & 0 deletions app/(site)/(aefeup)/requests/calendar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<section id="calendar" className="py-20 md:px-10 lg:py-25 xl:py-30">
<div className="mx-auto max-w-c-1315 px-4 md:px-8 xl:px-0">
<SectionHeader
headerInfo={{
title: "Calendar",
subtitle: "Available Dates",
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. In
convallis tortor eros. Donec vitae tortor lacus. Phasellus aliquam
ante in maximus.`,
}}
/>
<div className="bg-white mt-8">
<FullCalendar
plugins={[dayGridPlugin, googleCalendarPlugin]}
initialView='dayGridMonth'
headerToolbar={{
right: "today,prev,next"
}}
googleCalendarApiKey={calendarApiKey}
events={{
googleCalendarId: calendarID
}}
eventDataTransform={(event) => {
delete event.url
event.title = event.title ?? "Ocupado"
event.allDay = true
return event
}}
height={700}
/>
</div>
</div>
</section>
</>
)
}

export default CalendarComponent;
27 changes: 4 additions & 23 deletions app/(site)/(aefeup)/requests/client.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
"use client"

import CalendarComponent from "@/components/Calendar";
import RequestTab from "@/components/RequestTab";
import EmailTemplate from "@/emails";
import { EventRequestInfo } from "@/types/eventRequestInfo";
import { render } from "@react-email/render";
import { Resend } from "resend";
import { Dialog, DialogContent, DialogDescription } from "@/components/ui/dialog"
import { Docfile, Material, Space } from "@/payload-types";
import RequestTab from "./RequestTab";

interface Props {
calendarID?: string;
Expand All @@ -15,28 +13,11 @@ interface Props {
regulation?: Docfile;
}


const RequestPageContent = ({ calendarID, calendarApiKey, materialData, availableSpaces, regulation }: Props) => {

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 <onboarding@resend.dev>',
to: [requestInfo.email],
subject: `${requestInfo.isEvent ? "Reserva de Espaço" : "Pedido de Material"}`,
html: await render(EmailTemplate({ requestEventInfo: requestInfo })),
})
}

return (
<Dialog>
<CalendarComponent calendarID={calendarID} calendarApiKey={calendarApiKey} />
<RequestTab materialData={materialData} sendEmail={sendEmail} availableSpaces={availableSpaces} regulation={regulation} />
<RequestTab materialData={materialData} availableSpaces={availableSpaces} regulation={regulation} />
<DialogContent>
<DialogDescription>
<iframe
Expand Down
46 changes: 16 additions & 30 deletions app/(site)/(aefeup)/requests/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import CalendarComponent from "@/components/Calendar"
import { Metadata } from "next"
import config from "payload.config"
import { getPayload } from "payload"
import RequestPageContent from "./client"
import config from "payload.config"

export const dynamic = 'force-dynamic'

Expand All @@ -12,9 +11,9 @@ export const metadata: Metadata = {
}

async function getMaterialData() {
if(process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
if (process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
}

const payload = await getPayload({ config });
Expand All @@ -27,26 +26,28 @@ async function getMaterialData() {
}

async function getRegulation() {
if(process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
if (process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
}


const payload = await getPayload({ config });

const regulation = (await payload.find({
collection: "docfile",
limit: 1,
where: {
type: { equals: "regulation" },
},
})).docs;
return regulation;

return regulation;
}

async function getAvailableSpaces() {
if(process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
if (process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
}

const payload = await getPayload({ config });
Expand All @@ -63,22 +64,7 @@ export default async function Request() {

const materialData = await getMaterialData()
const availableSpaces = await getAvailableSpaces()
const regulation = await getRegulation()

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 <onboarding@resend.dev>',
to: [requestInfo.email],
subject: `${requestInfo.isEvent ? "Reserva de Espaço" : "Pedido de Material"}`,
html: await render(EmailTemplate({ requestEventInfo: requestInfo })),
})
}
const regulation = await getRegulation()

return (
<RequestPageContent
Expand Down
31 changes: 17 additions & 14 deletions app/(site)/contact/page.tsx → app/(site)/_contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,44 @@ import Contact from "@/components/Contact";
import SuggestionBox from "@/components/Sugestion";
import { getPayload } from "payload";
import config from "payload.config";
import { Toaster } from "react-hot-toast";

export const metadata: Metadata = {
title: "Contacto",
description: "Contacta-nos para qualquer dúvida ou sugestão. Estamos aqui para ajudar!",
description: "Contacta-nos para qualquer dúvida ou sugestão. Estamos aqui para ajudar!",
};



async function getFaqData() {
if(process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
if (process.env.IS_BUILD) {
console.log('skipping getProjects DB call during build')
return []
}

const payload = await getPayload({config});
const payload = await getPayload({ config });
const faqData = (await payload.find({
collection: 'faq'
})).docs;

return faqData
}

const ContactsPage = async () => {
const ContactsPage = async () => {
const faqData = await getFaqData()
return (
<main>
<div className="pt-20 lg:pt-25 xl:pt-30">
<Contact />
<div className="pt-20 lg:pt-25 xl:pt-30">
<Contact />
</div>
<div className="pt-20 lg:pt-25 xl:pt-30">
<FAQ faqData={faqData}/>
<div className="pt-20 lg:pt-25 xl:pt-30">
<FAQ faqData={faqData} />
</div>
<div className=" pt-20 lg:pt-25 xl:pt-30 pb-20 lg:pb-25 xl:pb-30">
<SuggestionBox />
<div className=" pt-20 lg:pt-25 xl:pt-30 pb-20 lg:pb-25 xl:pb-30">
<SuggestionBox />
</div>

<Toaster
position="bottom-right"
/>
</main>
);
}
Expand Down
2 changes: 1 addition & 1 deletion components/Contact/index.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down
10 changes: 5 additions & 5 deletions components/Header/menuData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
{
Expand All @@ -87,10 +87,10 @@ const menuData: Menu[] = [
title: "Loja (wip)",
path: "/store",
},
{
title: "Contactos",
path: "/contact",
},
//{
// title: "Contactos",
// path: "/contact",
//},
];

export default menuData;
Loading

0 comments on commit c3aab9b

Please sign in to comment.