163 lines
5.7 KiB
TypeScript
163 lines
5.7 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Input } from './ui/input';
|
|
import { Textarea } from './ui/textarea';
|
|
import { Label } from './ui/label';
|
|
import { Select } from './ui/select';
|
|
import { Button } from './ui/button';
|
|
|
|
export function ContactForm() {
|
|
const [formState, setFormState] = useState({
|
|
name: '',
|
|
email: '',
|
|
company: '',
|
|
service: '',
|
|
message: '',
|
|
});
|
|
|
|
const [formStatus, setFormStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
|
const { name, value } = e.target;
|
|
setFormState(prev => ({ ...prev, [name]: value }));
|
|
};
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setFormStatus('submitting');
|
|
|
|
// Simulate form submission with a timeout
|
|
setTimeout(() => {
|
|
// In a real app, you would send the data to a server here
|
|
console.log('Form submitted:', formState);
|
|
setFormStatus('success');
|
|
|
|
// Reset form after successful submission
|
|
setFormState({
|
|
name: '',
|
|
email: '',
|
|
company: '',
|
|
service: '',
|
|
message: '',
|
|
});
|
|
|
|
// Reset status after showing success message for a while
|
|
setTimeout(() => {
|
|
setFormStatus('idle');
|
|
}, 3000);
|
|
}, 1500);
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className="space-y-4 sm:space-y-6">
|
|
<div className="space-y-3 sm:space-y-4">
|
|
{/* Name and Email - Stack on mobile, side-by-side on tablet+ */}
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4">
|
|
<div className="space-y-1 sm:space-y-2">
|
|
<Label htmlFor="name" className="text-sm sm:text-base">Name</Label>
|
|
<Input
|
|
id="name"
|
|
name="name"
|
|
placeholder="Your name"
|
|
value={formState.name}
|
|
onChange={handleChange}
|
|
required
|
|
className="text-sm sm:text-base"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1 sm:space-y-2">
|
|
<Label htmlFor="email" className="text-sm sm:text-base">Email</Label>
|
|
<Input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
placeholder="your.email@example.com"
|
|
value={formState.email}
|
|
onChange={handleChange}
|
|
required
|
|
className="text-sm sm:text-base"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Company and Service Interest - Stack on mobile, side-by-side on tablet+ */}
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4">
|
|
<div className="space-y-1 sm:space-y-2">
|
|
<Label htmlFor="company" className="text-sm sm:text-base">Company</Label>
|
|
<Input
|
|
id="company"
|
|
name="company"
|
|
placeholder="Your company name"
|
|
value={formState.company}
|
|
onChange={handleChange}
|
|
className="text-sm sm:text-base"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1 sm:space-y-2">
|
|
<Label htmlFor="service" className="text-sm sm:text-base">Service Interest</Label>
|
|
<Select
|
|
id="service"
|
|
name="service"
|
|
value={formState.service}
|
|
onChange={handleChange}
|
|
required
|
|
className="text-sm sm:text-base"
|
|
>
|
|
<option value="" disabled>Select a service</option>
|
|
<option value="php">PHP Hosting</option>
|
|
<option value="nodejs">Node.js Hosting</option>
|
|
<option value="python">Python Hosting</option>
|
|
<option value="kubernetes">Kubernetes (K8s)</option>
|
|
<option value="k3s">K3s Lightweight Kubernetes</option>
|
|
<option value="custom">Custom Solution</option>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-1 sm:space-y-2">
|
|
<Label htmlFor="message" className="text-sm sm:text-base">Message</Label>
|
|
<Textarea
|
|
id="message"
|
|
name="message"
|
|
placeholder="Tell us about your project requirements..."
|
|
value={formState.message}
|
|
onChange={handleChange}
|
|
required
|
|
className="min-h-[100px] sm:min-h-[150px] text-sm sm:text-base"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Button
|
|
type="submit"
|
|
size="lg"
|
|
className="w-full mt-2 text-sm sm:text-base py-2 sm:py-3"
|
|
disabled={formStatus === 'submitting'}
|
|
>
|
|
{formStatus === 'submitting' ? (
|
|
<>
|
|
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
Sending...
|
|
</>
|
|
) : 'Send Message'}
|
|
</Button>
|
|
|
|
{formStatus === 'success' && (
|
|
<div className="p-3 sm:p-4 bg-green-900/30 border border-green-800 rounded-md text-green-400 text-center text-sm sm:text-base">
|
|
Thank you for your message! We'll get back to you soon.
|
|
</div>
|
|
)}
|
|
|
|
{formStatus === 'error' && (
|
|
<div className="p-3 sm:p-4 bg-red-900/30 border border-red-800 rounded-md text-red-400 text-center text-sm sm:text-base">
|
|
There was an error sending your message. Please try again.
|
|
</div>
|
|
)}
|
|
</form>
|
|
);
|
|
}
|