277 lines
18 KiB
TypeScript
277 lines
18 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import ReCAPTCHA from "react-google-recaptcha";
|
|
import axios from "axios";
|
|
import Link from 'next/link';
|
|
|
|
const ContactClient = () => {
|
|
const [formData, setFormData] = useState({
|
|
name: "",
|
|
phone: "",
|
|
email: "",
|
|
service: "Commercial",
|
|
message: "",
|
|
});
|
|
|
|
const [formErrors, setFormErrors] = useState<any>({});
|
|
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
|
|
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
|
const { name, value } = e.target;
|
|
setFormData((prev) => ({ ...prev, [name]: value }));
|
|
};
|
|
|
|
const handleCaptchaChange = (token: string | null) => {
|
|
setCaptchaToken(token);
|
|
};
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
const errors: any = {};
|
|
if (!formData.name.trim()) errors.name = "Name is required.";
|
|
if (!formData.phone.trim()) errors.phone = "Phone is required.";
|
|
if (!formData.email.trim()) errors.email = "Email is required.";
|
|
if (!formData.service.trim()) errors.service = "Please select a service.";
|
|
if (!formData.message.trim()) errors.message = "Message is required.";
|
|
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
|
|
|
|
setFormErrors(errors);
|
|
if (Object.keys(errors).length > 0) return;
|
|
|
|
const emailData = {
|
|
...formData,
|
|
message: `<b>Project Type:</b> ${formData.service}<br /><br /><b>Message:</b> ${formData.message}`,
|
|
to: "info@vgfenceproducts.com",
|
|
senderName: "VG Fence Contact Page",
|
|
recaptchaToken: captchaToken,
|
|
};
|
|
|
|
setAlert({ show: true, type: "info", message: "Sending your message..." });
|
|
|
|
try {
|
|
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
|
|
setAlert({
|
|
show: true,
|
|
type: "success",
|
|
message: "Thank you! Your message has been sent successfully.",
|
|
});
|
|
|
|
setFormData({
|
|
name: "",
|
|
phone: "",
|
|
email: "",
|
|
service: "Commercial",
|
|
message: "",
|
|
});
|
|
setCaptchaToken(null);
|
|
setFormErrors({});
|
|
} catch (error) {
|
|
console.error("❌ Error sending email:", error);
|
|
setAlert({
|
|
show: true,
|
|
type: "danger",
|
|
message: "Failed to send message. Please try again later.",
|
|
});
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (alert.show && alert.type !== "info") {
|
|
const timer = setTimeout(() => {
|
|
setAlert((prev) => ({ ...prev, show: false }));
|
|
}, 5000);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [alert.show, alert.type]);
|
|
|
|
return (
|
|
<div style={{ background: 'var(--cream)' }}>
|
|
{/* Inner Banner */}
|
|
<section className="inner-banner fade-up">
|
|
<div className="inner-banner-content">
|
|
<h1 className="section-h2">How to <span>Contact</span> Us</h1>
|
|
<div className="banner-breadcrumb" style={{ marginTop: '30px', marginBottom: '0' }}>
|
|
<Link href="/">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
|
Home
|
|
</Link>
|
|
<span className="separator">/</span>
|
|
<span>Contact</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Contact Content */}
|
|
<section className="section">
|
|
<div className="container" style={{ maxWidth: '1200px', margin: '0 auto' }}>
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1.2fr', gap: '80px' }} className="contact-layout">
|
|
|
|
{/* Left Col: Info & Map */}
|
|
<div>
|
|
<div style={{ marginBottom: '48px' }}>
|
|
<h3 className="section-h2" style={{ fontSize: '32px', marginBottom: '32px' }}>Office <span>Details.</span></h3>
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
|
|
<div style={{ display: 'flex', gap: '16px' }}>
|
|
<div style={{ width: '40px', height: '40px', background: 'var(--orange)', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: '4px', fontFamily: 'var(--font-display)', textTransform: 'uppercase', fontSize: '14px', letterSpacing: '.05em' }}>Our Location</div>
|
|
<div style={{ fontSize: '15px', color: 'var(--gray-600)', lineHeight: 1.5 }}>125 Earl Thompson Rd, Ayr, ON N0B 1E0, Canada</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', gap: '16px' }}>
|
|
<div style={{ width: '40px', height: '40px', background: 'var(--orange)', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: '4px', fontFamily: 'var(--font-display)', textTransform: 'uppercase', fontSize: '14px', letterSpacing: '.05em' }}>Direct Line Numbers</div>
|
|
<div style={{ fontSize: '15px', color: 'var(--gray-600)', lineHeight: 1.5 }}>+1 226-888-7999</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', gap: '16px' }}>
|
|
<div style={{ width: '40px', height: '40px', background: 'var(--orange)', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
|
|
</div>
|
|
<div>
|
|
<div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: '4px', fontFamily: 'var(--font-display)', textTransform: 'uppercase', fontSize: '14px', letterSpacing: '.05em' }}>Our Email</div>
|
|
<div style={{ fontSize: '15px', color: 'var(--gray-600)', lineHeight: 1.5 }}>info@vgfenceproducts.com</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Map Placeholder */}
|
|
<div style={{ borderRadius: '12px', overflow: 'hidden', border: '1px solid var(--gray-200)', height: '440px', background: 'var(--white)', position: 'relative' }}>
|
|
<iframe
|
|
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2903.9575459392213!2d-80.447551023419!3d43.29854497112028!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x882c7f0f0f0f0f0f%3A0x0!2zMTI1IEVhcmwgVGhvbXBzb24gUmQsIEF5ciwgT04gTjBCIDFFMCwgQ2FuYWRh!5e0!3m2!1sen!2sca!4v1713350000000!5m2!1sen!2sca"
|
|
width="100%"
|
|
height="100%"
|
|
style={{ border: 0 }}
|
|
allowFullScreen
|
|
loading="lazy"
|
|
></iframe>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="quote-card" style={{ height: 'fit-content', background: 'var(--white)', borderRadius: '16px', padding: '30px', boxShadow: '0 20px 40px rgba(15, 36, 68, .08)', border: '1px solid var(--gray-200)' }}>
|
|
<div style={{ marginBottom: '32px' }}>
|
|
<h3 style={{ fontFamily: 'var(--font-display)', fontSize: '28px', fontWeight: 800, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Send us a <span>Message.</span></h3>
|
|
<p style={{ fontSize: '14px', color: 'var(--gray-600)' }}>Fill out the form below and our team will get back to you within 24 hours.</p>
|
|
</div>
|
|
|
|
<form className="contact-form" onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
{alert.show && (
|
|
<div className={`alert alert-${alert.type === 'danger' ? 'danger' : (alert.type === 'info' ? 'info' : 'success')} mb-4`} style={{
|
|
padding: '12px 16px',
|
|
borderRadius: '8px',
|
|
fontSize: '14px',
|
|
background: alert.type === 'danger' ? '#fee2e2' : (alert.type === 'info' ? '#e0f2fe' : '#f0fdf4'),
|
|
color: alert.type === 'danger' ? '#991b1b' : (alert.type === 'info' ? '#075985' : '#166534'),
|
|
border: `1px solid ${alert.type === 'danger' ? '#fecaca' : (alert.type === 'info' ? '#bae6fd' : '#bbf7d0')}`
|
|
}}>
|
|
{alert.message}
|
|
</div>
|
|
)}
|
|
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }} className="form-row">
|
|
<div className="form-group">
|
|
<label style={{ display: 'block', fontSize: '12px', fontWeight: 700, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Name</label>
|
|
<input
|
|
type="text"
|
|
name="name"
|
|
placeholder="John Doe"
|
|
value={formData.name}
|
|
onChange={handleChange}
|
|
style={{ width: '100%', padding: '12px 16px', borderRadius: '4px', border: formErrors.name ? '1px solid #ef4444' : '1px solid var(--gray-200)', fontSize: '14px', background: 'var(--white)' }}
|
|
/>
|
|
{formErrors.name && <small style={{ color: '#ef4444', fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.name}</small>}
|
|
</div>
|
|
<div className="form-group">
|
|
<label style={{ display: 'block', fontSize: '12px', fontWeight: 700, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Email</label>
|
|
<input
|
|
type="email"
|
|
name="email"
|
|
placeholder="john@example.com"
|
|
value={formData.email}
|
|
onChange={handleChange}
|
|
style={{ width: '100%', padding: '12px 16px', borderRadius: '4px', border: formErrors.email ? '1px solid #ef4444' : '1px solid var(--gray-200)', fontSize: '14px', background: 'var(--white)' }}
|
|
/>
|
|
{formErrors.email && <small style={{ color: '#ef4444', fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.email}</small>}
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }} className="form-row">
|
|
<div className="form-group">
|
|
<label style={{ display: 'block', fontSize: '12px', fontWeight: 700, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Phone Number</label>
|
|
<input
|
|
type="tel"
|
|
name="phone"
|
|
placeholder="(555) 123-4567"
|
|
value={formData.phone}
|
|
onChange={handleChange}
|
|
style={{ width: '100%', padding: '12px 16px', borderRadius: '4px', border: formErrors.phone ? '1px solid #ef4444' : '1px solid var(--gray-200)', fontSize: '14px', background: 'var(--white)' }}
|
|
/>
|
|
{formErrors.phone && <small style={{ color: '#ef4444', fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.phone}</small>}
|
|
</div>
|
|
<div className="form-group">
|
|
<label style={{ display: 'block', fontSize: '12px', fontWeight: 700, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Project Type</label>
|
|
<select
|
|
name="service"
|
|
value={formData.service}
|
|
onChange={handleChange}
|
|
style={{ width: '100%', padding: '12px 16px', borderRadius: '4px', border: '1px solid var(--gray-200)', fontSize: '14px', background: 'var(--white)', appearance: 'none' }}
|
|
>
|
|
<option value="Commercial">Commercial</option>
|
|
<option value="Residential">Residential</option>
|
|
<option value="Event">Event</option>
|
|
<option value="Other">Other</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label style={{ display: 'block', fontSize: '12px', fontWeight: 700, textTransform: 'uppercase', color: 'var(--navy)', marginBottom: '8px' }}>Message</label>
|
|
<textarea
|
|
name="message"
|
|
placeholder="How can we help you?"
|
|
value={formData.message}
|
|
onChange={handleChange}
|
|
style={{ width: '100%', padding: '12px 16px', borderRadius: '4px', border: formErrors.message ? '1px solid #ef4444' : '1px solid var(--gray-200)', fontSize: '14px', minHeight: '150px', resize: 'vertical', background: 'var(--white)' }}
|
|
></textarea>
|
|
{formErrors.message && <small style={{ color: '#ef4444', fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.message}</small>}
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<ReCAPTCHA
|
|
sitekey="6LekfpwrAAAAAOTwuP1d2gg-Fv9UEsAjE2gjOQJl"
|
|
onChange={handleCaptchaChange}
|
|
/>
|
|
{formErrors.captcha && <small style={{ color: '#ef4444', fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.captcha}</small>}
|
|
</div>
|
|
|
|
<button type="submit" className="btn-primary" style={{ width: '100%', marginTop: '10px' }} disabled={alert.type === "info"}>
|
|
{alert.type === "info" ? "Sending..." : "Send Message →"}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ContactClient;
|