feat: integrate form state and sendMail endpoint fetch

This commit is contained in:
Chneemann 2026-07-25 08:07:04 +02:00
parent 8ac0e8eb08
commit 92812bc70c
2 changed files with 96 additions and 14 deletions

37
sendMail.php Normal file
View file

@ -0,0 +1,37 @@
<?php
switch ($_SERVER['REQUEST_METHOD']) {
case ("OPTIONS"): // Allow preflighting to take place.
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: content-type");
exit;
case ("POST"): // Send the email
header("Access-Control-Allow-Origin: *");
// Payload is sent to php://input as raw JSON text
$json = file_get_contents('php://input');
$params = json_decode($json);
// Extract values
$email = $params->email;
$name = $params->name;
$message = $params->message;
$recipient = 'dev@andre-kempf.com';
$subject = "Contact Form <$email>";
$message = "From: $name<br> Email: $email <br><br>$message";
$headers = array();
$headers[] = 'MIME-Version: 1.0';
$headers[] = 'Content-type: text/html; charset=utf-8';
$headers[] = "From: noreply@andre-kempf.com";
mail($recipient, $subject, $message, implode("\r\n", $headers));
break;
default: // Reject non-POST or OPTIONS requests.
header("Allow: POST", true, 405);
exit;
}

View file

@ -3,13 +3,43 @@
import { useState } from "react"; import { useState } from "react";
export default function Contact() { export default function Contact() {
// Placeholder const [name, setName] = useState("");
const [submitted, setSubmitted] = useState(false); const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const handleSubmit = (e: React.SubmitEvent<HTMLFormElement>) => { const [submitted, setSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const handleSubmit = async (e: React.SubmitEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
// Mailer / Formspree / API Call integration goes here
setLoading(true);
setError(false);
try {
const response = await fetch("https://andre-kempf.com/sendMail.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name, email, message }),
});
if (response.ok) {
setSubmitted(true); setSubmitted(true);
setName("");
setEmail("");
setMessage("");
} else {
setError(true);
}
} catch (err) {
console.error("Mail send error:", err);
setError(true);
} finally {
setLoading(false);
}
}; };
return ( return (
@ -93,44 +123,59 @@ export default function Contact() {
) : ( ) : (
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
<div> <div>
<label className="block text-xs font-bold mb-1.5">Name</label> <label className="block text-xs mb-1.5" htmlFor="name">
Name
</label>
<input <input
type="text" type="text"
required required
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="John Doe" placeholder="John Doe"
className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-white placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm" className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm"
/> />
</div> </div>
<div> <div>
<label className="block text-xs font-bold mb-1.5"> <label className="block text-xs mb-1.5" htmlFor="email">
Email Email
</label> </label>
<input <input
type="email" type="email"
required required
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="john@example.com" placeholder="john@example.com"
className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-white placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm" className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm"
/> />
</div> </div>
<div> <div>
<label className="block text-xs font-bold mb-1.5"> <label className="block text-xs mb-1.5" htmlFor="message">
Message Message
</label> </label>
<textarea <textarea
rows={4} rows={4}
required required
placeholder="Hi André, I would like to discuss a potential project with you..." value={message}
className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-white placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm resize-none" onChange={(e) => setMessage(e.target.value)}
placeholder="Hi André, I would like to discuss a potential project..."
className="w-full px-4 py-2.5 rounded-xl bg-slate-950/60 border border-slate-800 text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-blue-500/80 focus:ring-1 focus:ring-blue-500/80 transition-colors text-sm resize-none"
/> />
</div> </div>
{error && (
<p className="text-red-400 text-xs font-mono">
An error occurred. Please try again later.
</p>
)}
<button <button
type="submit" type="submit"
className="w-full px-6 py-3 bg-slate-900 border border-slate-800 hover:border-slate-700 hover:bg-slate-850 rounded-lg transition-all hover:-translate-y-0.5 duration-200 cursor-pointer" disabled={loading}
className="w-full px-6 py-3 bg-slate-900 border border-slate-800 hover:border-slate-700 hover:bg-slate-850 rounded-lg transition-all hover:-translate-y-0.5 duration-200 cursor-pointer disabled:opacity-50"
> >
Send Message {loading ? "Sending..." : "Send Message"}
</button> </button>
</form> </form>
)} )}