implemented contact form using Node.js and Postmark.
This commit is contained in:
+60
-43
@@ -1,5 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
/**
|
||||
* TODO: Add email validation function.
|
||||
@@ -7,10 +6,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
export default function Contact() {
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
emailAddress: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||
|
||||
const handleChange = (event) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
@@ -18,53 +19,69 @@ export default function Contact() {
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
// Handle form submission here, e.g., send data to server
|
||||
console.log(formData);
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault(); // Prevent default form submission behavior
|
||||
setIsSubmitted(true);
|
||||
|
||||
try {
|
||||
const response = await fetch("http://localhost:3001/api/send-email", {
|
||||
method: "POST", // Use POST for sending data
|
||||
headers: { "Content-Type": "application/json" }, // Set the content type
|
||||
body: JSON.stringify(formData), // Convert the JS object to JSON string
|
||||
});
|
||||
const json = await response.json();
|
||||
setData(json);
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div id="contact-section">
|
||||
<h1>Contact Me</h1>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<input
|
||||
className="shadow"
|
||||
placeholder="Name"
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<input
|
||||
className="shadow"
|
||||
placeholder="example@email.com"
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="row">
|
||||
<textarea
|
||||
className="shadow"
|
||||
placeholder="Message"
|
||||
id="message"
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div id="form-container"></div>
|
||||
{isSubmitted ? (
|
||||
<p>Thanks for reaching out! I'll get in touch shortly.</p>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<input
|
||||
className="shadow"
|
||||
placeholder="Name"
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<input
|
||||
className="shadow"
|
||||
placeholder="example@email.com"
|
||||
type="email"
|
||||
id="emailAddress"
|
||||
name="emailAddress"
|
||||
value={formData.emailAddress}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="row">
|
||||
<textarea
|
||||
className="shadow"
|
||||
placeholder="Message"
|
||||
id="message"
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<button type="submit" className="button shadow">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className="row">
|
||||
<button type="submit" className="button shadow">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+6
-10
@@ -63,6 +63,11 @@ h4 {
|
||||
font-size: clamp(1rem, 1.5vw, 1.25rem);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: clamp(1rem, 1.5rem, 2rem);
|
||||
color: #ebd2ff;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-variation-settings:
|
||||
"FILL" 0,
|
||||
@@ -191,23 +196,16 @@ h4 {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--width);
|
||||
aspect-ratio: 1/1;
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#header-image img {
|
||||
display: block;
|
||||
width: calc(var(--width) / 2);
|
||||
filter: drop-shadow(5px 6px 5px rgba(36, 36, 42, 0.5));
|
||||
user-select: none;
|
||||
z-index: 1;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#header-image img {
|
||||
animation: imgMoveDown 0.8s ease-in forwards 0.2s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#skill-cards {
|
||||
@@ -350,8 +348,6 @@ h4 {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: clamp(1rem, 1.5rem, 2rem);
|
||||
color: #ebd2ff;
|
||||
}
|
||||
|
||||
.row {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import postmark from "postmark";
|
||||
const app = express();
|
||||
const port = 3001; // Example port
|
||||
const client = new postmark.ServerClient(
|
||||
"d15a4575-17f1-4ead-8e53-69eb2faea982",
|
||||
);
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json()); // Parse incoming JSON data
|
||||
|
||||
// Example API endpoint
|
||||
app.post("/api/send-email", (req, res) => {
|
||||
const email = {
|
||||
From: "contact@joshashton.dev",
|
||||
To: "me@joshashton.dev",
|
||||
Subject: req.body.name + " - " + req.body.emailAddress,
|
||||
TextBody: req.body.message,
|
||||
MessageStream: "outbound",
|
||||
};
|
||||
|
||||
client.sendEmail(email);
|
||||
res.json({ text: "email sent!" });
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
||||
Reference in New Issue
Block a user