auto-claude: subtask-3-1 - Update ContactForm to call API route instead of simulating

Changes:
- Replaced simulated API call with real fetch() to /api/contact
- Added errorMessage state for custom error messages
- Implemented proper response handling for different status codes:
  * 200: Success message and form reset
  * 429: Rate limit error with time until retry
  * 400/500: Display API error messages
- Enhanced rate limit error display with human-readable time formatting
- Added VERIFICATION_STEPS.md for manual testing guidance

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 12:06:43 +01:00
co-authored by Claude Sonnet 4.5
parent e875a1e480
commit 24dbadf5d6
2 changed files with 95 additions and 5 deletions
+40 -5
View File
@@ -17,6 +17,7 @@ export function ContactForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
const [errorMessage, setErrorMessage] = useState<string>('');
const [formData, setFormData] = useState<FormData>({
name: '',
email: '',
@@ -62,14 +63,48 @@ export function ContactForm() {
setIsSubmitting(true);
setSubmitStatus('idle');
setErrorMessage('');
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500));
setSubmitStatus('success');
setFormData({ name: '', email: '', message: '' });
const response = await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
const data = await response.json();
if (response.ok) {
setSubmitStatus('success');
setFormData({ name: '', email: '', message: '' });
} else if (response.status === 429) {
// Rate limit exceeded
setSubmitStatus('error');
const retryAfter = data.retryAfter || 0;
const minutes = Math.ceil(retryAfter / 60);
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
let timeMessage = '';
if (hours > 0) {
timeMessage = `${hours} hour${hours > 1 ? 's' : ''}${remainingMinutes > 0 ? ` and ${remainingMinutes} minute${remainingMinutes > 1 ? 's' : ''}` : ''}`;
} else {
timeMessage = `${minutes} minute${minutes > 1 ? 's' : ''}`;
}
setErrorMessage(
`Too many requests. Please try again in ${timeMessage}.`
);
} else {
// Other errors (400, 500, etc.)
setSubmitStatus('error');
setErrorMessage(data.error || t('contactForm.errorMessage'));
}
} catch {
setSubmitStatus('error');
setErrorMessage(t('contactForm.errorMessage'));
} finally {
setIsSubmitting(false);
}
@@ -299,7 +334,7 @@ export function ContactForm() {
className="p-3 bg-red-900/20 border border-red-900/50 rounded-lg"
>
<p className="text-red-400 text-sm">
{t('contactForm.errorMessage')}
{errorMessage || t('contactForm.errorMessage')}
</p>
</motion.div>
)}