feat: update portfolio with new contact form functionality and improved styling

- Removed outdated CV file and replaced with a new image for the profile.
- Implemented a new email service using EmailJS for contact form submissions.
- Enhanced the contact form to handle errors and success messages.
- Updated the About section for grammatical accuracy.
- Modified the Hero component to link to the new CV file and updated GitHub profile link.
- Updated project links to point to the correct GitHub repositories.
- Improved styling for error messages and avatar image with hover effects.
This commit is contained in:
Dayron
2025-11-12 00:47:02 +01:00
parent cdff0c8c5c
commit a4b4423ff4
16 changed files with 1657 additions and 35 deletions

View File

@@ -1,6 +1,8 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import { Mail, Phone, MapPin, Send, Github, Linkedin, MessageCircle, CheckCircle } from 'lucide-react';
import { Mail, Phone, MapPin, Send, Github, Linkedin, MessageCircle, CheckCircle, AlertCircle } from 'lucide-react';
import { sendContactEmail } from '../services/emailService';
import type { ContactFormData } from '../services/emailService';
const Contact = () => {
const [formData, setFormData] = useState({
@@ -11,6 +13,7 @@ const Contact = () => {
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
@@ -23,32 +26,51 @@ const Contact = () => {
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setError(null);
// Simulation d'envoi (remplacez par votre logique d'envoi réelle)
setTimeout(() => {
setIsSubmitting(false);
setIsSubmitted(true);
setFormData({ name: '', email: '', subject: '', message: '' });
try {
const contactData: ContactFormData = {
name: formData.name,
email: formData.email,
subject: formData.subject,
message: formData.message
};
// Reset du message de succès après 5 secondes
setTimeout(() => {
setIsSubmitted(false);
}, 5000);
}, 2000);
const result = await sendContactEmail(contactData);
if (result.success) {
setIsSubmitted(true);
setFormData({ name: '', email: '', subject: '', message: '' });
// Reset du message de succès après 5 secondes
setTimeout(() => {
setIsSubmitted(false);
}, 5000);
} else {
setError(result.message);
}
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Une erreur est survenue lors de l\'envoi du message.';
setError(errorMessage);
console.error('Erreur lors de l\'envoi de l\'email:', err);
} finally {
setIsSubmitting(false);
}
};
const contactInfo = [
{
icon: <Mail size={24} />,
title: "Email",
content: "dayronvanleemput@gmail.com", // Remplacez par votre email
content: "dayronvanleemput@gmail.com",
link: "mailto:dayronvanleemput@gmail.com",
color: "#EA4335"
},
{
icon: <Phone size={24} />,
title: "Téléphone",
content: "+32 455 19 47 62", // Remplacez par votre numéro
content: "+32 455 19 47 62",
link: "tel:+32455194762",
color: "#34A853"
},
@@ -214,6 +236,18 @@ const Contact = () => {
Message envoyé avec succès ! Je vous répondrai bientôt.
</motion.div>
)}
{error && (
<motion.div
className="error-message"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
>
<AlertCircle size={20} />
{error}
</motion.div>
)}
<form onSubmit={handleSubmit} className="contact-form">
<div className="form-row">
@@ -330,7 +364,7 @@ const Contact = () => {
viewport={{ once: true }}
>
<p>
© 2025 Dayron Van Leemput. Développé avec ❤️ en React et TypeScript.
© 2025 Dayron Van Leemput.
</p>
</motion.footer>
</div>