React 19 + TypeScript SPA with Vite, mobile responsive fixes, GitHub Actions CI/CD pipeline for automated deployment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
135 lines
No EOL
4.2 KiB
TypeScript
135 lines
No EOL
4.2 KiB
TypeScript
import React, { useState, ChangeEvent, FormEvent } from 'react';
|
|
|
|
interface FormData {
|
|
fullName: string;
|
|
workEmail: string;
|
|
companyName: string;
|
|
jobTitle: string;
|
|
automationNeed: string;
|
|
phoneNumber: string;
|
|
}
|
|
|
|
const ContactForm: React.FC = () => {
|
|
const [formData, setFormData] = useState<FormData>({
|
|
fullName: '',
|
|
workEmail: '',
|
|
companyName: '',
|
|
jobTitle: '',
|
|
automationNeed: '',
|
|
phoneNumber: '',
|
|
});
|
|
|
|
const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
const { name, value } = e.target;
|
|
setFormData((prev) => ({ ...prev, [name]: value }));
|
|
};
|
|
|
|
const handleSubmit = (e: FormEvent) => {
|
|
e.preventDefault();
|
|
console.log('Submitted Data:', formData);
|
|
// Тут можна додати логіку відправки на API
|
|
};
|
|
|
|
const inputStyles = "w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:outline-none transition-all";
|
|
const labelStyles = "block text-sm font-medium text-gray-700 mb-1";
|
|
|
|
return (
|
|
<div className="max-w-4xl mx-auto p-6 bg-white shadow-lg rounded-xl">
|
|
<h2 className="text-2xl font-bold mb-6 text-gray-800">Contact Us</h2>
|
|
<form onSubmit={handleSubmit} className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
{/* Ліва колонка */}
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className={labelStyles}>Full Name*</label>
|
|
<input
|
|
type="text"
|
|
name="fullName"
|
|
required
|
|
value={formData.fullName}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="John Doe"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={labelStyles}>Work Email*</label>
|
|
<input
|
|
type="email"
|
|
name="workEmail"
|
|
required
|
|
value={formData.workEmail}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="john@company.com"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={labelStyles}>Company Name*</label>
|
|
<input
|
|
type="text"
|
|
name="companyName"
|
|
required
|
|
value={formData.companyName}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="Tech Solutions Inc."
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Права колонка */}
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label className={labelStyles}>Job Title / Role*</label>
|
|
<input
|
|
type="text"
|
|
name="jobTitle"
|
|
required
|
|
value={formData.jobTitle}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="Project Manager"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={labelStyles}>Automation Need*</label>
|
|
<input
|
|
type="text"
|
|
name="automationNeed"
|
|
required
|
|
value={formData.automationNeed}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="Workflow optimization"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={labelStyles}>Phone Number*</label>
|
|
<input
|
|
type="tel"
|
|
name="phoneNumber"
|
|
required
|
|
value={formData.phoneNumber}
|
|
onChange={handleChange}
|
|
className={inputStyles}
|
|
placeholder="+380..."
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Кнопка відправки */}
|
|
<div className="md:col-span-2 mt-4">
|
|
<button
|
|
type="submit"
|
|
className="w-full md:w-max px-8 py-3 bg-blue-600 text-white font-semibold rounded-md hover:bg-blue-700 transition-colors cursor-pointer"
|
|
>
|
|
Submit Request
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ContactForm; |