2026-04-23 10:15:31 +05:30

282 lines
12 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 slides = [
{
id: 0,
eyebrow: "Based in KWC. Delivering everywhere.",
title: <>Ontario's B2B<br /><em>Fence Supply</em><br />Partner</>,
sub: <>Supplying contractors, builders, and property managers across Ontario with{' '}<strong>chain link, ornamental, composite, glass railing, aluminum railing, Expert Stain &amp; Seal, Fence Armor, and temporary fence rental</strong> — with scheduled job site delivery across a 250km radius from KWC.</>,
productValue: "",
},
{
id: 1,
eyebrow: "Premium Aluminum Railing Systems",
title: <>Durable &amp; Stylish<br /><em>Aluminum</em><br />Railing</>,
sub: <>High-quality, easy-to-install aluminum railing systems for residential and commercial projects. Available in multiple styles and colors with fast job site delivery across our service area.</>,
productValue: "Aluminum railing",
},
{
id: 2,
eyebrow: "Low Maintenance Composite Fencing",
title: <>Modern &amp; Lasting<br /><em>Composite</em><br />Fencing</>,
sub: <>Provide your clients with beautiful, weather-resistant composite fences. Easy installation, long lifespan, and premium aesthetics for any property.</>,
productValue: "Composite fence",
}
];
export default function Hero() {
const [formData, setFormData] = useState({
company: "",
name: "",
phone: "",
email: "",
product: "",
city: "",
quantity: ""
});
const [formErrors, setFormErrors] = useState<any>({});
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
const [currentSlide, setCurrentSlide] = useState(0);
const [userSelectedProduct, setUserSelectedProduct] = useState(false);
useEffect(() => {
const timer = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
}, 6000);
return () => clearInterval(timer);
}, []);
useEffect(() => {
if (!userSelectedProduct) {
setFormData((prev) => ({ ...prev, product: slides[currentSlide].productValue }));
}
}, [currentSlide, userSelectedProduct]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
const { name, value } = e.target;
if (name === "product") {
setUserSelectedProduct(true);
}
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.product.trim()) errors.product = "Please select a product.";
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
setFormErrors(errors);
if (Object.keys(errors).length > 0) return;
const emailData = {
name: formData.name,
email: formData.email,
phone: formData.phone,
message: `
<b>Company:</b> ${formData.company}<br />
<b>Product:</b> ${formData.product}<br />
<b>Job Site City:</b> ${formData.city}<br />
<b>Quantity:</b> ${formData.quantity}
`,
to: "info@vgfenceproducts.com",
senderName: "VG Fence Hero Form",
recaptchaToken: captchaToken,
};
setAlert({ show: true, type: "info", message: "Sending your request..." });
try {
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
headers: { "Content-Type": "application/json" },
});
setAlert({
show: true,
type: "success",
message: "Thank you! Your quote request has been sent successfully.",
});
setFormData({
company: "",
name: "",
phone: "",
email: "",
product: "",
city: "",
quantity: ""
});
setCaptchaToken(null);
setFormErrors({});
} catch (error) {
console.error("❌ Error sending email:", error);
setAlert({
show: true,
type: "danger",
message: "Failed to send request. 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 (
<section className="hero" id="home">
<div className="hero-grid-bg"></div>
<div className="hero-fence-deco" aria-hidden="true">
<div className="hero-fence-rail" style={{ top: '32%' }}></div>
<div className="hero-fence-rail" style={{ top: '67%' }}></div>
<div className="hero-fence-post" style={{ left: '5%' }}></div>
<div className="hero-fence-post" style={{ left: '16%' }}></div>
<div className="hero-fence-post" style={{ left: '27%' }}></div>
<div className="hero-fence-post" style={{ left: '38%' }}></div>
<div className="hero-fence-post" style={{ left: '49%' }}></div>
<div className="hero-fence-post" style={{ left: '60%' }}></div>
<div className="hero-fence-post" style={{ left: '71%' }}></div>
<div className="hero-fence-post" style={{ left: '82%' }}></div>
<div className="hero-fence-post" style={{ left: '93%' }}></div>
</div>
<div className="hero-accent"></div>
<div className="hero-accent2"></div>
<div className="hero-left">
<div key={currentSlide} style={{ animation: "fadeUp 0.6s ease-out forwards" }}>
<div className="hero-eyebrow">{slides[currentSlide].eyebrow}</div>
<h1 className="hero-h1">{slides[currentSlide].title}</h1>
<p className="hero-sub">{slides[currentSlide].sub}</p>
<div className="hero-btns">
<Link href="/contact" className="btn-primary">Request contractor pricing</Link>
<Link href="#products" className="btn-secondary">View all products</Link>
</div>
</div>
<div className="hero-slider-dots" style={{ display: 'flex', gap: '8px', marginTop: '10px' }}>
{slides.map((_, i) => (
<button
type="button"
key={i}
onClick={() => setCurrentSlide(i)}
className={`hero-slider-dot ${currentSlide === i ? 'active' : ''}`}
aria-label={`Go to slide ${i + 1}`}
/>
))}
</div>
</div>
<div className="hero-right" id="quote">
<div className="quote-card">
<div className="qc-title">Request a quote</div>
<div className="qc-sub">Response within 2 business hours · Contractor pricing available</div>
{alert.show && (
<div className={`hero-alert hero-alert-${alert.type === 'danger' ? 'danger' : (alert.type === 'info' ? 'info' : 'success')}`}>
{alert.message}
</div>
)}
<form className="quote-form" onSubmit={handleSubmit}>
<div className="frow">
<div>
<label className="fl">Company name</label>
<input className="fi" type="text" name="company" placeholder="ABC Fence Co." value={formData.company} onChange={handleChange} />
</div>
<div>
<label className="fl">Your name</label>
<input className={`fi ${formErrors.name ? 'border-danger' : ''}`} type="text" name="name" placeholder="John Smith" value={formData.name} onChange={handleChange} />
</div>
</div>
<div className="frow">
<div>
<label className="fl">Phone</label>
<input className={`fi ${formErrors.phone ? 'border-danger' : ''}`} type="tel" name="phone" placeholder="519-xxx-xxxx" value={formData.phone} onChange={handleChange} />
</div>
<div>
<label className="fl">Email</label>
<input className={`fi ${formErrors.email ? 'border-danger' : ''}`} type="email" name="email" placeholder="you@company.com" value={formData.email} onChange={handleChange} />
</div>
</div>
<label className="fl">Product needed</label>
<select className={`fi ${formErrors.product ? 'border-danger' : ''}`} name="product" value={formData.product} onChange={handleChange}>
<option value="">Select a product or service...</option>
<optgroup label="── Products ──">
<option>Aluminum railing</option>
<option>Chain link fence — commercial</option>
<option>Chain link fence — residential</option>
<option>Composite fence</option>
<option>Expert Stain &amp; Seal products</option>
<option>Fence Armor (post caps / guards)</option>
<option>Glass railing</option>
<option>Ornamental / iron fence</option>
</optgroup>
<optgroup label="── Services ──">
<option>Temporary fence rental — construction</option>
<option>Temporary fence rental — event</option>
<option>Wood staining service</option>
<option>2D fence drawing services</option>
<option>Contractor account enquiry</option>
<option>Multiple products</option>
</optgroup>
</select>
<div className="frow">
<div>
<label className="fl">Job site city</label>
<input className="fi" type="text" name="city" placeholder="Kitchener, Guelph..." value={formData.city} onChange={handleChange} />
</div>
<div>
<label className="fl">Approx. quantity</label>
<input className="fi" type="text" name="quantity" placeholder="e.g. 200 linear ft" value={formData.quantity} onChange={handleChange} />
</div>
</div>
<div className="tc-row" id="tc-row-home">
<input type="checkbox" className="tc-check" id="tc-home" required />
<label className="tc-label" htmlFor="tc-home">
I have read and agree to VG Fence Products'
<a href="/legal#t1" target="_blank">Terms &amp; Conditions</a>,
<a href="/legal#t3" target="_blank">Delivery Policy</a>, and
<a href="/legal#t7" target="_blank">Photo Verification (24hr) Policy</a>.
I understand that damage claims require photos submitted within 24 hours of delivery.
</label>
</div>
<div className="form-group" style={{ marginTop: '16px' }}>
<ReCAPTCHA
sitekey="6LekfpwrAAAAAOTwuP1d2gg-Fv9UEsAjE2gjOQJl"
onChange={handleCaptchaChange}
/>
{formErrors.captcha && <small className="text-danger" style={{ fontSize: '11px', marginTop: '4px', display: 'block' }}>{formErrors.captcha}</small>}
</div>
<button type="submit" className="form-submit" disabled={alert.type === "info"}>
{alert.type === "info" ? "Sending..." : "Send quote request →"}
</button>
<div className="form-note">Or email us · info@vgfenceproducts.com</div>
</form>
</div>
</div>
</section>
);
}