-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
sofiabaezzato
committed
Dec 2, 2023
1 parent
de96659
commit 7494ed2
Showing
21 changed files
with
1,083 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
"use server" | ||
import { error } from "console" | ||
import { Resend } from "resend" | ||
import { validateString } from "@/lib/utils" | ||
|
||
const resend = new Resend(process.env.RESEND_API_KEY) | ||
|
||
export const sendEmail = async (FormData: FormData) => { | ||
const sender = FormData.get("email") | ||
const message = FormData.get("message") | ||
|
||
//server side input validation | ||
if (!validateString(sender, 200)) { | ||
return error('Invalid Email') | ||
} | ||
if (!validateString(message, 5000)) { | ||
return error('Invalid Message') | ||
} | ||
|
||
let data; | ||
try { | ||
await resend.emails.send({ | ||
from: 'Contact Form <[email protected]>', | ||
to: '[email protected]', | ||
subject: 'Portfolio Form: New message', | ||
reply_to: sender as string, | ||
text: message + ' from ' + sender | ||
}) | ||
} catch (error: any) { | ||
return error.message | ||
} | ||
|
||
return { | ||
data | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,6 @@ | |
@tailwind components; | ||
@tailwind utilities; | ||
|
||
html { | ||
--line-color: #e5e7eb; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
"use client" | ||
|
||
import React from 'react' | ||
import SectionHeading from './SectionHeading' | ||
import { useSectionInView } from '@/lib/hooks' | ||
import { motion } from 'framer-motion' | ||
import { sendEmail } from '@/actions/sendEmail' | ||
import SubmitButton from './SubmitButton' | ||
import toast from 'react-hot-toast' | ||
|
||
const Contact = () => { | ||
const { ref } = useSectionInView('Contact', 0.5) | ||
|
||
return ( | ||
<motion.section | ||
id='contact' | ||
className='mb-20 sm:mb-28 w-[min(100%,38rem)] text-center' | ||
ref={ref} | ||
initial={{ | ||
opacity: 0, | ||
}} | ||
whileInView={{ | ||
opacity: 1, | ||
}} | ||
transition={{ | ||
duration: 1, | ||
}} | ||
viewport={{ | ||
once: true, | ||
}} | ||
> | ||
<SectionHeading>Contact me</SectionHeading> | ||
<p className='text-gray-700 -mt-6'>Feel free to contact me through this form.</p> | ||
|
||
<form | ||
className='flex flex-col gap-1 mt-10' | ||
action={async (FormData) => { | ||
const { data, error } = await sendEmail(FormData) | ||
|
||
if (error) { | ||
toast.error(error) | ||
return | ||
} | ||
|
||
toast.success('Email sent!') | ||
}} | ||
> | ||
<input | ||
name='email' | ||
type="email" | ||
className='h-14 rounded-lg border border-black/5 p-4' | ||
placeholder='Your email' | ||
maxLength={200} | ||
required | ||
/> | ||
<textarea | ||
name='message' | ||
className='h-52 my-3 rounded-lg border border-black/5 p-4' | ||
placeholder='Your message' | ||
maxLength={5000} | ||
required | ||
></textarea> | ||
<SubmitButton /> | ||
</form> | ||
</motion.section> | ||
) | ||
} | ||
|
||
export default Contact |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"use client" | ||
|
||
import React from 'react' | ||
import SectionHeading from './SectionHeading' | ||
import { experiencesData } from '@/lib/data'; | ||
|
||
const Experience = () => { | ||
return ( | ||
<section | ||
id='experience' | ||
> | ||
<SectionHeading>My Experience</SectionHeading> | ||
{experiencesData.map((item, index) => ( | ||
|
||
))} | ||
</section> | ||
) | ||
} | ||
|
||
export default Experience |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react' | ||
|
||
const Footer = () => { | ||
return ( | ||
<footer className='mb-10 px-4 text-center text-gray-500'> | ||
<small className='mb-2 text-xs'> | ||
© {new Date().getFullYear()} Sofia - made with ❤️ | ||
</small> | ||
<p className='text-xs'> | ||
<span className='font-semibold'>About this website:</span> built with React (Next.js), Typescript, Framer Motion and Resend. Hosted in Vercel. | ||
</p> | ||
</footer> | ||
) | ||
} | ||
|
||
export default Footer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react' | ||
import { FaPaperPlane } from 'react-icons/fa' | ||
|
||
import { | ||
// @ts-expect-error | ||
experimental_useFormState as useFormState, | ||
// @ts-expect-error | ||
experimental_useFormStatus as useFormStatus, | ||
} from "react-dom"; | ||
|
||
const SubmitButton = () => { | ||
const { pending } = useFormStatus() | ||
|
||
return ( | ||
<button | ||
type='submit' | ||
className='group h-[3rem] w-[8rem] bg-[#ffd500] text-gray-600 px-7 py-3 flex items-center justify-center gap-2 rounded-full outline-none hover:bg-[#ffd500] hover:text-gray-950 hover:scale-105 active:scale-95 transition-transform disabled:scale-100 disabled:bg-opacity-50' | ||
disabled={pending} | ||
> | ||
{pending ? <div className='h-5 w-5 animate-spin rounded-full border-b-2 border-white'></div> : ( | ||
<> | ||
Submit <FaPaperPlane className="opacity-70 group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform" /> | ||
</> | ||
)} | ||
</button> | ||
) | ||
} | ||
|
||
export default SubmitButton |
Oops, something went wrong.