Skip to content

Commit

Permalink
updating contact form with notification toast
Browse files Browse the repository at this point in the history
  • Loading branch information
BigSamu committed Oct 31, 2023
1 parent bcd50da commit dfd08f7
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 72 deletions.
32 changes: 17 additions & 15 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { Routes, Route } from "react-router-dom";
import { Element } from "react-scroll";
import { ToastProvider } from "./contexts/ToastContext";

import Layout from "./components/Layout";
import HomePage from "./pages/HomePage";
Expand All @@ -16,21 +17,22 @@ function App() {

// </Route>
// </Routes>

<Layout>
<Element name="home">
<HomePage />
</Element>
<Element name="about">
<AboutPage />
</Element>
<Element name="portfolio">
<PortfolioPage />
</Element>
<Element name="contact">
<ContactPage />
</Element>
</Layout>
<ToastProvider>
<Layout>
<Element name="home">
<HomePage />
</Element>
<Element name="about">
<AboutPage />
</Element>
<Element name="portfolio">
<PortfolioPage />
</Element>
<Element name="contact">
<ContactPage />
</Element>
</Layout>
</ToastProvider>
);
}

Expand Down
108 changes: 108 additions & 0 deletions src/components/ContactForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useContext } from "react";
import ToastContext from "../contexts/ToastContext";

import axios from "axios";

const ContactForm = () => {
const { showToast } = useContext(ToastContext);

const handleSubmitMessage = async (e) => {
e.preventDefault(); // Prevent the default form submission behavior

const form = e.target;
const formData = new FormData(form);

try {
const response = await axios.post(form.action, formData, {
headers: {
Accept: "application/json",
},
});

if (response.status === 200) {
showToast("Message sent successfully!", "success");
// Reset the form if needed
form.reset();
} else {
showToast("Error submitting Message. Please try again.", "error");
}
} catch (error) {
showToast("Error submitting Message. Please try again.", "error");
}
};

return (
<div>
<form
action="https://getform.io/f/b0d67c57-9226-4c38-be8c-76357605bb9c"
method="POST"
onSubmit={handleSubmitMessage}
className="w-full"
>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label
htmlFor="name"
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
>
Name
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="name"
name="name"
type="text"
placeholder="Name"
/>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label
htmlFor="email"
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
>
E-mail
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="email"
name="email"
type="email"
placeholder="Email"
/>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label
htmlFor="message"
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
>
Message
</label>
<textarea
className="no-resize appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500 h-48 resize-none"
id="message"
name="message"
placeholder="Message"
></textarea>
</div>
</div>
<div className="md:flex md:items-center">
<div className="md:w-1/3">
<button
className="shadow bg-black hover:bg-gray-500 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded"
type="submit"
>
Send
</button>
</div>
<div className="md:w-2/3"></div>
</div>
</form>
</div>
);
};

export default ContactForm;
33 changes: 33 additions & 0 deletions src/components/ContactToast.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { useContext } from 'react';
import { Toast } from 'flowbite-react';
import { FaTelegramPlane, FaTimesCircle } from 'react-icons/fa';
import ToastContext from '../contexts/ToastContext';

const ContactToast = () => {
const { toastInfo, setToastInfo } = useContext(ToastContext);
console.log(toastInfo)

const backgroundColor = toastInfo.type === 'success' ? '!bg-green-200 dark:!bg-green-700' : '!bg-red-200 dark:!bg-red-700';
const textColor = toastInfo.type === 'success' ? 'text-green-500 dark:text-green-200' : 'text-red-500 dark:text-red-200';

return (
<div className="fixed top-5 right-5 z-50">
<Toast onClose={() => setToastInfo(null)} className={backgroundColor}>
<div className={`inline-flex h-8 w-8 items-center justify-center rounded-lg ${textColor}`}>
{toastInfo.type === 'success' ? (
<FaTelegramPlane className={`h-5 w-5 ${textColor}`} />
) : (
<FaTimesCircle className={`h-5 w-5 ${textColor}`} />
)}
</div>
<div className={`mx-3 text-sm font-normal ${textColor}`}>{toastInfo.message}</div>
<Toast.Toggle />
</Toast>
</div>
);
};

export default ContactToast;



1 change: 0 additions & 1 deletion src/components/PortfolioMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const PortfolioMenu = ({ selectedAlbum, setSelectedAlbum }) => {
);

useEffect(() => {
console.log(menuItems)
let activeAlbum = menuItems.find((item) => item.active === true)
let albumToUpdate = imagesData.find((item) =>
item.album === activeAlbum.label.toLowerCase().replace(/\s+/g, '-')
Expand Down
2 changes: 1 addition & 1 deletion src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { FiHome, FiUser, FiBriefcase, FiMail } from "react-icons/fi";
import { Link as ScrollLink } from "react-scroll";

import { FiHome, FiUser, FiBriefcase, FiMail } from "react-icons/fi";
import userDetails from "../data/userDetails";

const Sidebar = () => {
Expand Down
25 changes: 25 additions & 0 deletions src/contexts/ToastContext.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createContext, useState } from 'react';
import ContactToast from '../components/ContactToast';

const ToastContext = createContext();

export const ToastProvider = ({ children }) => {
const [toastInfo, setToastInfo] = useState({ message:"", type:"", visible: false });

const showToast = (message, type, duration = 5000) => {
setToastInfo({ message, type, visible: true });

setTimeout(() => {
setToastInfo({ message:"", type:"", visible: false });
}, duration);
};

return (
<ToastContext.Provider value={{ toastInfo, setToastInfo, showToast }}>
{children}
{toastInfo.visible && <ContactToast />}
</ToastContext.Provider>
);
};

export default ToastContext;
53 changes: 2 additions & 51 deletions src/pages/ContactPage.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import ContactForm from "../components/ContactForm";

const ContactPage = () => {
return (
Expand All @@ -11,57 +12,7 @@ const ContactPage = () => {
</div>

<div className="m-4">
<form className="w-full">
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
Name
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="name"
type="text"
placeholder="Name"
/>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
E-mail
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="email"
type="email"
placeholder="Email"
/>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<label className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
Message
</label>
<textarea
className="no-resize appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500 h-48 resize-none"
id="message"
placeholder="Message"
></textarea>
</div>
</div>
<div className="md:flex md:items-center">
<div className="md:w-1/3">
<button
className="shadow bg-black hover:bg-gray-500 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded"
type="button"
>
Send
</button>
</div>
<div className="md:w-2/3"></div>
</div>
</form>
<ContactForm/>
</div>
</div>
</div>
Expand Down
12 changes: 8 additions & 4 deletions src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from "react";
import { Link as ScrollLink } from "react-scroll";

import { FiInstagram, FiMail } from "react-icons/fi";
import avatar_1 from "/assets/avatar_1.jpeg";
Expand Down Expand Up @@ -57,13 +58,16 @@ const HomePage = () => {
</p>
<div>
<span className="inline-flex justify-center space-x-2 sm:ml-auto sm:mt-0 sm:justify-start">
<a
href={`mailto:${userDetails.email}`}
className="hover:text-gray-500"
<ScrollLink
to="contact"
containerId="content-container"
spy={true}
smooth={true}
className="hover:text-gray-500"
>
<span className="sr-only">Email</span>
<FiMail className="w-7 h-7" />
</a>
</ScrollLink>

<a
href={userDetails.instagram}
Expand Down

0 comments on commit dfd08f7

Please sign in to comment.