Refactor project structure: update Astro configuration, integrate Tailwind CSS, enhance ContactForm with validation, and improve layout for various pages. Add new Donate and Orphanage pages, and implement responsive design adjustments across components.

This commit is contained in:
2025-06-27 22:49:11 +02:00
parent 81f637b317
commit 9f6fa46227
23 changed files with 2721 additions and 3058 deletions

View File

@@ -1,46 +1,140 @@
import { useState } from "react";
import React, { useState } from 'react';
export default function ContactForm() {
const [status, setStatus] = useState("");
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: '',
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitMessage, setSubmitMessage] = useState(null);
const validate = () => {
let newErrors = {};
if (!formData.name) newErrors.name = 'Name is required';
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(formData.email)) {
newErrors.email = 'Invalid email address';
}
if (!formData.subject) newErrors.subject = 'Subject is required';
if (!formData.message) newErrors.message = 'Message is required';
return newErrors;
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
// Clear error for the field as user types
if (errors[name]) {
setErrors({ ...errors, [name]: null });
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const form = e.target;
// Honeypot check
if (form.honey.value !== "") {
setStatus("Spam detected.");
return;
setIsSubmitting(true);
setSubmitMessage(null);
const validationErrors = validate();
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Form data submitted:', formData);
setSubmitMessage({ type: 'success', text: 'Your message has been sent successfully!' });
setFormData({ name: '', email: '', subject: '', message: '' }); // Clear form
} catch (error) {
setSubmitMessage({ type: 'error', text: 'There was an error sending your message. Please try again later.' });
} finally {
setIsSubmitting(false);
}
} else {
setIsSubmitting(false);
setSubmitMessage({ type: 'error', text: 'Please correct the errors in the form.' });
}
setStatus("Sending...");
// Placeholder: would POST to /api/contact
setTimeout(() => setStatus("Message sent (placeholder, not yet implemented)."), 1000);
};
return (
<form className="max-w-xl mx-auto bg-base-100 p-8 rounded-xl shadow-lg" onSubmit={handleSubmit} autoComplete="off">
<div className="mb-4">
<label htmlFor="name" className="block font-bold mb-1">Name</label>
<input type="text" id="name" name="name" className="input input-bordered w-full" required autoComplete="off" />
<form onSubmit={handleSubmit} className="bg-white p-8 rounded-xl shadow-lg border border-gray-200 max-w-2xl mx-auto">
<h2 className="text-3xl font-bold text-center text-nigerian-green-700 mb-8">Send Us a Message</h2>
{submitMessage && (
<div className={`p-4 mb-4 rounded-lg text-center ${submitMessage.type === 'success' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>
{submitMessage.text}
</div>
)}
<div className="mb-5">
<label htmlFor="name" className="block text-gray-700 text-sm font-bold mb-2">Name</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.name ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Your Name"
/>
{errors.name && <p className="text-red-500 text-xs italic mt-2">{errors.name}</p>}
</div>
<div className="mb-4">
<label htmlFor="email" className="block font-bold mb-1">Email</label>
<input type="email" id="email" name="email" className="input input-bordered w-full" required autoComplete="off" />
<div className="mb-5">
<label htmlFor="email" className="block text-gray-700 text-sm font-bold mb-2">Email</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.email ? 'border-red-500' : 'border-gray-300'}`}
placeholder="your.email@example.com"
/>
{errors.email && <p className="text-red-500 text-xs italic mt-2">{errors.email}</p>}
</div>
<div className="mb-4">
<label htmlFor="subject" className="block font-bold mb-1">Subject</label>
<input type="text" id="subject" name="subject" className="input input-bordered w-full" required autoComplete="off" />
<div className="mb-5">
<label htmlFor="subject" className="block text-gray-700 text-sm font-bold mb-2">Subject</label>
<input
type="text"
id="subject"
name="subject"
value={formData.subject}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.subject ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Subject of your message"
/>
{errors.subject && <p className="text-red-500 text-xs italic mt-2">{errors.subject}</p>}
</div>
<div className="mb-4">
<label htmlFor="message" className="block font-bold mb-1">Message</label>
<textarea id="message" name="message" className="textarea textarea-bordered w-full" rows={5} required></textarea>
<div className="mb-6">
<label htmlFor="message" className="block text-gray-700 text-sm font-bold mb-2">Message</label>
<textarea
id="message"
name="message"
rows="6"
value={formData.message}
onChange={handleChange}
className={`shadow appearance-none border rounded-lg w-full py-3 px-4 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-nigerian-green-500 ${errors.message ? 'border-red-500' : 'border-gray-300'}`}
placeholder="Your message..."
></textarea>
{errors.message && <p className="text-red-500 text-xs italic mt-2">{errors.message}</p>}
</div>
{/* Honeypot field for spam protection */}
<div style={{ display: "none" }}>
<label htmlFor="honey">Do not fill this out</label>
<input type="text" id="honey" name="honey" tabIndex="-1" autoComplete="off" />
<div className="flex items-center justify-center">
<button
type="submit"
className="bg-gradient-to-r from-nigerian-green-500 to-kente-gold-500 hover:from-nigerian-green-600 hover:to-kente-gold-600 text-white font-bold py-3 px-8 rounded-lg focus:outline-none focus:shadow-outline transition-all duration-300 transform hover:scale-105"
disabled={isSubmitting}
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
</div>
<button type="submit" className="btn btn-primary w-full">Send Message</button>
{status && <div className="mt-4 text-center text-sm text-success">{status}</div>}
</form>
);
}
}