Jade-Infra-test / src /components /ContactForm.jsx
rushiljain's picture
Upload 29 files
691cdd0 verified
import React, { useState } from 'react';
import axios from 'axios';
const DEFAULT_ENDPOINT = 'https://formsubmit.co/ajax/jadeinfrapune@gmail.com';
export default function ContactForm() {
const [status, setStatus] = useState({ state: 'idle', message: '' });
async function onSubmit(e) {
e.preventDefault();
const form = new FormData(e.currentTarget);
const payload = {
name: String(form.get('name') || '').trim(),
email: String(form.get('email') || '').trim(),
phone: String(form.get('phone') || '').trim(),
message: String(form.get('message') || '').trim()
};
if (!payload.name || !payload.email || !payload.phone || !payload.message) {
setStatus({
state: 'error',
message: 'All fields are required. Please complete the form.'
});
return;
}
const namePattern = /^[A-Za-z\s]{2,60}$/;
if (!namePattern.test(payload.name)) {
setStatus({
state: 'error',
message: 'Please enter a valid name using alphabets only.'
});
return;
}
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(payload.email)) {
setStatus({
state: 'error',
message: 'Please enter a valid email address.'
});
return;
}
const phonePattern = /^[0-9]{10}$/;
if (!phonePattern.test(payload.phone)) {
setStatus({
state: 'error',
message: 'Please enter a valid 10-digit phone number.'
});
return;
}
setStatus({ state: 'loading', message: '' });
try {
const endpoint = import.meta.env.VITE_CONTACT_ENDPOINT || DEFAULT_ENDPOINT;
const structuredMessage = [
'New enquiry received via jadeinfra.in contact form:',
'',
`Name : ${payload.name}`,
`Email : ${payload.email}`,
`Phone : ${payload.phone}`,
'',
'Message:',
payload.message
].join('\n');
await axios.post(
endpoint,
{
name: payload.name,
email: payload.email,
phone: payload.phone,
message: payload.message,
_subject: 'New enquiry via jadeinfra.in contact form',
_template: 'box',
_replyto: payload.email,
_captcha: 'false',
content: structuredMessage
},
{
headers: { 'Content-Type': 'application/json' }
}
);
setStatus({ state: 'success', message: 'Thanks! We will get back to you shortly.' });
e.currentTarget.reset();
} catch (err) {
setStatus({
state: 'error',
message:
'Sorry, there was an issue sending your message. Please try again or email us directly.'
});
}
}
return (
<form className="space-y-4" onSubmit={onSubmit} noValidate aria-labelledby="contact-heading">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<div>
<label htmlFor="name" className="block text-sm font-medium text-slate-700">Name</label>
<input
id="name"
name="name"
required
pattern="[A-Za-z\s]{2,60}"
autoComplete="name"
className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2
focus:outline-none focus:ring-2 focus:ring-brand-600"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-slate-700">Email</label>
<input
id="email"
name="email"
type="email"
required
pattern="^[^\s@]+@[^\s@]+\.[^\s@]+$"
autoComplete="email"
className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2
focus:outline-none focus:ring-2 focus:ring-brand-600"
/>
</div>
<div className="md:col-span-2">
<label htmlFor="phone" className="block text-sm font-medium text-slate-700">Phone</label>
<input
id="phone"
name="phone"
type="tel"
required
pattern="[0-9]{10}"
inputMode="numeric"
autoComplete="tel"
className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2
focus:outline-none focus:ring-2 focus:ring-brand-600"
/>
</div>
<div className="md:col-span-2">
<label htmlFor="message" className="block text-sm font-medium text-slate-700">Message</label>
<textarea
id="message"
name="message"
required
rows="5"
className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2
focus:outline-none focus:ring-2 focus:ring-brand-600"
></textarea>
</div>
</div>
<div className="flex items-center gap-3">
<button type="submit" className="btn btn-primary" aria-live="polite">
Send Message
</button>
{status.state === 'loading' && (
<span role="status" className="text-sm text-slate-600">Sending…</span>
)}
{status.state === 'success' && (
<span className="text-sm text-green-700">{status.message}</span>
)}
{status.state === 'error' && (
<span className="text-sm text-red-700">{status.message}</span>
)}
</div>
</form>
);
}