contact integration updated
This commit is contained in:
parent
3240bdaf4c
commit
4a9948c6e0
@ -19,6 +19,8 @@ const ContactClient = () => {
|
|||||||
|
|
||||||
const [formStatus, setFormStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
const [formStatus, setFormStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||||
const [tcError, setTcError] = useState(false);
|
const [tcError, setTcError] = useState(false);
|
||||||
|
const [nlEmail, setNlEmail] = useState("");
|
||||||
|
const [nlStatus, setNlStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||||
const [openFaq, setOpenFaq] = useState<number | null>(null);
|
const [openFaq, setOpenFaq] = useState<number | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -104,6 +106,34 @@ const ContactClient = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitNewsletterForm = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!nlEmail || !nlEmail.includes("@")) return;
|
||||||
|
|
||||||
|
setNlStatus("submitting");
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
name: "Newsletter Subscriber",
|
||||||
|
email: nlEmail,
|
||||||
|
phone: "N/A",
|
||||||
|
service: "Newsletter Subscription",
|
||||||
|
message: `A new user has subscribed to the newsletter: <b>${nlEmail}</b>`,
|
||||||
|
to: "info@vgfenceproducts.com",
|
||||||
|
senderName: "VG Fence Contact Page Newsletter",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
setNlStatus("success");
|
||||||
|
setNlEmail("");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error subscribing to newsletter:", error);
|
||||||
|
setNlStatus("error");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="contact-page">
|
<div className="contact-page">
|
||||||
|
|
||||||
@ -658,18 +688,27 @@ const ContactClient = () => {
|
|||||||
<div className="nl-eye">Stay in the loop</div>
|
<div className="nl-eye">Stay in the loop</div>
|
||||||
<h2 className="nl-h2">Product updates &<br /><span>contractor deals.</span></h2>
|
<h2 className="nl-h2">Product updates &<br /><span>contractor deals.</span></h2>
|
||||||
<p className="nl-sub">New products, seasonal promotions, and industry tips — delivered to your inbox. No spam, unsubscribe anytime.</p>
|
<p className="nl-sub">New products, seasonal promotions, and industry tips — delivered to your inbox. No spam, unsubscribe anytime.</p>
|
||||||
<div className="nl-form">
|
<div className="nl-form-wrap">
|
||||||
<input className="nl-input" type="email" placeholder="Enter your email address" id="nl-input" />
|
{nlStatus === "success" ? (
|
||||||
<button className="nl-btn" onClick={() => {
|
<div className="nl-success-msg" style={{ padding: '12px 20px', background: '#16A34A', color: 'white', borderRadius: '4px', fontWeight: 600, textAlign: 'center' }}>
|
||||||
const input = document.getElementById('nl-input') as HTMLInputElement;
|
Thank you! You've been subscribed successfully. ✓
|
||||||
if (input && input.value.includes('@')) {
|
</div>
|
||||||
const btn = document.querySelector('.nl-btn') as HTMLElement;
|
) : (
|
||||||
btn.textContent = 'Subscribed ✓';
|
<form className="nl-form" onSubmit={submitNewsletterForm}>
|
||||||
btn.style.background = '#16A34A';
|
<input
|
||||||
input.value = '';
|
className="nl-input"
|
||||||
input.placeholder = 'Thank you — you\'re subscribed!';
|
type="email"
|
||||||
}
|
placeholder={nlStatus === "error" ? "Error occurred. Try again?" : "Enter your email address"}
|
||||||
}}>Subscribe →</button>
|
value={nlEmail}
|
||||||
|
onChange={(e) => setNlEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
disabled={nlStatus === "submitting"}
|
||||||
|
/>
|
||||||
|
<button type="submit" className="nl-btn" disabled={nlStatus === "submitting"}>
|
||||||
|
{nlStatus === "submitting" ? "..." : "Subscribe →"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="nl-note">Join contractors and builders across Ontario · 1–6 emails per month</p>
|
<p className="nl-note">Join contractors and builders across Ontario · 1–6 emails per month</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -378,6 +378,7 @@
|
|||||||
.model-image-col {
|
.model-image-col {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-area {
|
.photo-area {
|
||||||
@ -428,17 +429,16 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 48px;
|
gap: 48px;
|
||||||
align-items: stretch; /* Key for matching height */
|
align-items: start;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-area-large {
|
.photo-area-large {
|
||||||
flex: 1;
|
height: 500px;
|
||||||
min-height: 300px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-area-small {
|
.photo-area-small {
|
||||||
min-height: 180px;
|
height: 340px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-area img {
|
.photo-area img {
|
||||||
|
|||||||
@ -1,8 +1,65 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
const ChainLinkQuote = () => {
|
const ChainLinkQuote = () => {
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
company: '',
|
||||||
|
name: '',
|
||||||
|
phone: '',
|
||||||
|
email: '',
|
||||||
|
material: '',
|
||||||
|
city: '',
|
||||||
|
footage: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFormData(prev => ({ ...prev, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setStatus("submitting");
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
name: formData.name,
|
||||||
|
email: formData.email,
|
||||||
|
phone: formData.phone,
|
||||||
|
service: formData.material || "Chain Link Quote",
|
||||||
|
message: `
|
||||||
|
<b>Company:</b> ${formData.company}<br />
|
||||||
|
<b>Material Needed:</b> ${formData.material}<br />
|
||||||
|
<b>Job Site City:</b> ${formData.city}<br />
|
||||||
|
<b>Linear Footage:</b> ${formData.footage}
|
||||||
|
`,
|
||||||
|
to: "info@vgfenceproducts.com",
|
||||||
|
senderName: "VG Fence Chain Link Page",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
setStatus("success");
|
||||||
|
setFormData({
|
||||||
|
company: '',
|
||||||
|
name: '',
|
||||||
|
phone: '',
|
||||||
|
email: '',
|
||||||
|
material: '',
|
||||||
|
city: '',
|
||||||
|
footage: ''
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error sending chain link quote request:", error);
|
||||||
|
setStatus("error");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="quote-cta">
|
<section className="quote-cta">
|
||||||
<div className="quote-inner">
|
<div className="quote-inner">
|
||||||
@ -11,56 +68,71 @@ const ChainLinkQuote = () => {
|
|||||||
<p>Fill in the quick form and we'll come back to you with contractor pricing within 2 business hours. Bulk orders welcome — we supply fence contractors, builders, and property managers across Ontario.</p>
|
<p>Fill in the quick form and we'll come back to you with contractor pricing within 2 business hours. Bulk orders welcome — we supply fence contractors, builders, and property managers across Ontario.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="quote-form-card">
|
<div className="quote-form-card">
|
||||||
<div className="q-form-title">Request a quote</div>
|
{status === "success" ? (
|
||||||
<div className="q-form-sub">Response within 2 business hours</div>
|
<div className="q-success-msg" style={{ padding: '40px 20px', textAlign: 'center' }}>
|
||||||
<div className="qrow">
|
<div style={{ fontSize: '48px', marginBottom: '20px' }}>✅</div>
|
||||||
<div>
|
<h3 style={{ color: '#fff', marginBottom: '10px' }}>Quote Request Sent!</h3>
|
||||||
<label className="ql">Company name</label>
|
<p style={{ color: '#fff' }}>Thank you. We'll respond within 2 business hours.</p>
|
||||||
<input className="qi" type="text" placeholder="ABC Fence Co." />
|
<button className="qbtn" style={{ marginTop: '20px' }} onClick={() => setStatus("idle")}>Send another request</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
) : (
|
||||||
<label className="ql">Your name</label>
|
<form onSubmit={handleSubmit}>
|
||||||
<input className="qi" type="text" placeholder="John Smith" />
|
<div className="q-form-title">Request a quote</div>
|
||||||
</div>
|
<div className="q-form-sub">Response within 2 business hours</div>
|
||||||
</div>
|
<div className="qrow">
|
||||||
<div className="qrow">
|
<div>
|
||||||
<div>
|
<label className="ql">Company name</label>
|
||||||
<label className="ql">Phone</label>
|
<input className="qi" type="text" name="company" placeholder="ABC Fence Co." value={formData.company} onChange={handleChange} />
|
||||||
<input className="qi" type="tel" placeholder="519-xxx-xxxx" />
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<label className="ql">Your name</label>
|
||||||
<label className="ql">Email</label>
|
<input className="qi" type="text" name="name" placeholder="John Smith" value={formData.name} onChange={handleChange} required />
|
||||||
<input className="qi" type="email" placeholder="you@company.com" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="qrow">
|
||||||
<label className="ql">Material needed</label>
|
<div>
|
||||||
<select className="qi">
|
<label className="ql">Phone</label>
|
||||||
<option value="">Select material type...</option>
|
<input className="qi" type="tel" name="phone" placeholder="519-xxx-xxxx" value={formData.phone} onChange={handleChange} required />
|
||||||
<option>Chain link mesh — galvanized</option>
|
</div>
|
||||||
<option>Chain link mesh — vinyl coated black</option>
|
<div>
|
||||||
<option>Posts (terminal & line)</option>
|
<label className="ql">Email</label>
|
||||||
<option>Top rail</option>
|
<input className="qi" type="email" name="email" placeholder="you@company.com" value={formData.email} onChange={handleChange} required />
|
||||||
<option>Gates & gate hardware</option>
|
</div>
|
||||||
<option>Hardware & fittings pack</option>
|
</div>
|
||||||
<option>Privacy slats</option>
|
<label className="ql">Material needed</label>
|
||||||
<option>Barbed wire</option>
|
<select className="qi" name="material" value={formData.material} onChange={handleChange} required>
|
||||||
<option>Complete material package</option>
|
<option value="">Select material type...</option>
|
||||||
</select>
|
<option>Chain link mesh — galvanized</option>
|
||||||
<div className="qrow">
|
<option>Chain link mesh — vinyl coated black</option>
|
||||||
<div>
|
<option>Posts (terminal & line)</option>
|
||||||
<label className="ql">Job site city</label>
|
<option>Top rail</option>
|
||||||
<input className="qi" type="text" placeholder="Kitchener, Guelph..." />
|
<option>Gates & gate hardware</option>
|
||||||
</div>
|
<option>Hardware & fittings pack</option>
|
||||||
<div>
|
<option>Privacy slats</option>
|
||||||
<label className="ql">Linear footage</label>
|
<option>Barbed wire</option>
|
||||||
<input className="qi" type="text" placeholder="e.g. 300 linear ft" />
|
<option>Complete material package</option>
|
||||||
</div>
|
</select>
|
||||||
</div>
|
<div className="qrow">
|
||||||
<button className="qbtn">Send quote request →</button>
|
<div>
|
||||||
|
<label className="ql">Job site city</label>
|
||||||
|
<input className="qi" type="text" name="city" placeholder="Kitchener, Guelph..." value={formData.city} onChange={handleChange} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="ql">Linear footage</label>
|
||||||
|
<input className="qi" type="text" name="footage" placeholder="e.g. 300 linear ft" value={formData.footage} onChange={handleChange} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{status === "error" && <p style={{ color: 'red', fontSize: '14px', marginBottom: '10px' }}>⚠️ Error sending request. Please try again.</p>}
|
||||||
|
<button className="qbtn" disabled={status === "submitting"}>
|
||||||
|
{status === "submitting" ? "Sending..." : "Send quote request →"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default ChainLinkQuote;
|
export default ChainLinkQuote;
|
||||||
|
|||||||
@ -1,4 +1,40 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
export default function Newsletter() {
|
export default function Newsletter() {
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!email || !email.includes("@")) return;
|
||||||
|
|
||||||
|
setStatus("submitting");
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
name: "Newsletter Subscriber",
|
||||||
|
email: email,
|
||||||
|
phone: "N/A",
|
||||||
|
service: "Newsletter Subscription",
|
||||||
|
message: `A new user has subscribed to the newsletter: <b>${email}</b>`,
|
||||||
|
to: "info@vgfenceproducts.com",
|
||||||
|
senderName: "VG Fence Newsletter",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
setStatus("success");
|
||||||
|
setEmail("");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error subscribing to newsletter:", error);
|
||||||
|
setStatus("error");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="newsletter-section">
|
<section className="newsletter-section">
|
||||||
<div className="newsletter-inner reveal">
|
<div className="newsletter-inner reveal">
|
||||||
@ -8,12 +44,37 @@ export default function Newsletter() {
|
|||||||
New product arrivals, seasonal promotions, and industry tips — delivered to your inbox.<br />
|
New product arrivals, seasonal promotions, and industry tips — delivered to your inbox.<br />
|
||||||
No spam, unsubscribe anytime.
|
No spam, unsubscribe anytime.
|
||||||
</p>
|
</p>
|
||||||
<form className="newsletter-form" action="#" method="POST">
|
|
||||||
<input type="email" className="newsletter-input" placeholder="Enter your email address" required />
|
{status === "success" ? (
|
||||||
<button type="submit" className="newsletter-btn">Subscribe →</button>
|
<div className="newsletter-success" style={{ textAlign: 'center', padding: '20px', background: 'rgba(22, 163, 74, 0.1)', borderRadius: '8px', border: '1px solid #16A34A', color: '#16A34A', fontWeight: 600 }}>
|
||||||
</form>
|
Thank you! You've been subscribed successfully. ✓
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<form className="newsletter-form" onSubmit={handleSubmit}>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
className="newsletter-input"
|
||||||
|
placeholder="Enter your email address"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
disabled={status === "submitting"}
|
||||||
|
/>
|
||||||
|
<button type="submit" className="newsletter-btn" disabled={status === "submitting"}>
|
||||||
|
{status === "submitting" ? "Subscribing..." : "Subscribe →"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{status === "error" && (
|
||||||
|
<p style={{ color: '#ef4444', fontSize: '14px', marginTop: '10px', textAlign: 'center' }}>
|
||||||
|
Failed to subscribe. Please try again later.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="newsletter-note">Join contractors and builders across Ontario · 1–6 emails per month</div>
|
<div className="newsletter-note">Join contractors and builders across Ontario · 1–6 emails per month</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
export default function StainingQuote() {
|
export default function StainingQuote() {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
@ -8,19 +9,58 @@ export default function StainingQuote() {
|
|||||||
email: '',
|
email: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
projectType: 'fence',
|
projectType: 'fence',
|
||||||
|
location: '',
|
||||||
|
size: '',
|
||||||
message: ''
|
message: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
||||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log('Form submitted:', formData);
|
|
||||||
alert('Thank you for your request! We will contact you shortly.');
|
setStatus("submitting");
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
name: formData.name,
|
||||||
|
email: formData.email,
|
||||||
|
phone: formData.phone,
|
||||||
|
service: formData.projectType || "Wood Staining",
|
||||||
|
message: `
|
||||||
|
<b>Service:</b> ${formData.projectType}<br />
|
||||||
|
<b>Location:</b> ${formData.location}<br />
|
||||||
|
<b>Approx Size:</b> ${formData.size}<br /><br />
|
||||||
|
<b>Additional Notes:</b> ${formData.message || "N/A"}
|
||||||
|
`,
|
||||||
|
to: "info@vgfenceproducts.com",
|
||||||
|
senderName: "VG Fence Staining Page",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
setStatus("success");
|
||||||
|
setFormData({
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
phone: '',
|
||||||
|
projectType: 'fence',
|
||||||
|
location: '',
|
||||||
|
size: '',
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Error sending staining quote request:", error);
|
||||||
|
setStatus("error");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="quote-cta quote-cta-orange" id="quote-section">
|
<section className="quote-cta quote-cta-orange" id="quote-section">
|
||||||
<div className="quote-inner">
|
<div className="quote-inner">
|
||||||
@ -31,92 +71,112 @@ export default function StainingQuote() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="quote-form-card">
|
<div className="quote-form-card">
|
||||||
<form onSubmit={handleSubmit}>
|
{status === "success" ? (
|
||||||
<div className="q-form-title">REQUEST A STAINING QUOTE</div>
|
<div className="q-form-success" style={{ padding: '30px', background: 'rgba(255,255,255,0.1)', borderRadius: '8px', border: '1px solid white', color: 'white', textAlign: 'center' }}>
|
||||||
<div className="q-form-sub text-white-70">Response within 2 business hours</div>
|
<div style={{ fontSize: '40px', marginBottom: '15px' }}>✅</div>
|
||||||
|
<h3 style={{ margin: '0 0 10px 0' }}>Request Sent!</h3>
|
||||||
<div className="qrow">
|
<p style={{ margin: 0, opacity: 0.9 }}>Thank you. We'll be in touch within 2 business hours.</p>
|
||||||
<div>
|
<button type="button" className="qbtn btn-white-orange" style={{ marginTop: '20px' }} onClick={() => setStatus("idle")}>Send another request</button>
|
||||||
<label className="ql text-white">YOUR NAME</label>
|
</div>
|
||||||
|
) : (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="q-form-title">REQUEST A STAINING QUOTE</div>
|
||||||
|
<div className="q-form-sub text-white-70">Response within 2 business hours</div>
|
||||||
|
|
||||||
|
<div className="qrow">
|
||||||
|
<div>
|
||||||
|
<label className="ql text-white">YOUR NAME</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
className="qi"
|
||||||
|
placeholder="John Smith"
|
||||||
|
required
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="ql text-white">PHONE</label>
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
name="phone"
|
||||||
|
className="qi"
|
||||||
|
placeholder="519-xxx-xxxx"
|
||||||
|
required
|
||||||
|
value={formData.phone}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label className="ql text-white">EMAIL</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="email"
|
||||||
name="name"
|
name="email"
|
||||||
className="qi"
|
className="qi"
|
||||||
placeholder="John Smith"
|
placeholder="you@email.com"
|
||||||
required
|
required
|
||||||
value={formData.name}
|
value={formData.email}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div>
|
<label className="ql text-white">SERVICE NEEDED</label>
|
||||||
<label className="ql text-white">PHONE</label>
|
<select
|
||||||
<input
|
name="projectType"
|
||||||
type="tel"
|
|
||||||
name="phone"
|
|
||||||
className="qi"
|
className="qi"
|
||||||
placeholder="519-xxx-xxxx"
|
value={formData.projectType}
|
||||||
required
|
|
||||||
value={formData.phone}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
>
|
||||||
</div>
|
<option value="">Select service...</option>
|
||||||
</div>
|
<option>Fence staining — new wood</option>
|
||||||
|
<option>Fence staining — existing / restoration</option>
|
||||||
|
<option>Deck staining — new wood</option>
|
||||||
|
<option>Deck staining — restoration</option>
|
||||||
|
<option>Pergola / structure staining</option>
|
||||||
|
<option>Log cabin / cedar siding</option>
|
||||||
|
<option>Pre-staining — fence boards before install</option>
|
||||||
|
<option>Expert Stain & Seal product only — contractor purchase</option>
|
||||||
|
<option>Multiple services — describe below</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
<label className="ql text-white">EMAIL</label>
|
<div className="qrow">
|
||||||
<input
|
<div>
|
||||||
type="email"
|
<label className="ql text-white">CITY / LOCATION</label>
|
||||||
name="email"
|
<input
|
||||||
className="qi"
|
type="text"
|
||||||
placeholder="you@email.com"
|
name="location"
|
||||||
required
|
className="qi"
|
||||||
value={formData.email}
|
placeholder="Kitchener, Guelph..."
|
||||||
onChange={handleChange}
|
value={formData.location}
|
||||||
/>
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="ql text-white">APPROXIMATE SIZE</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="size"
|
||||||
|
className="qi"
|
||||||
|
placeholder="e.g. 150 ft fence / 400 sq ft deck"
|
||||||
|
value={formData.size}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label className="ql text-white">SERVICE NEEDED</label>
|
{status === "error" && (
|
||||||
<select
|
<p style={{ color: '#fee2e2', fontSize: '14px', marginBottom: '15px' }}>
|
||||||
name="projectType"
|
⚠️ Failed to send request. Please try again or email us directly.
|
||||||
className="qi"
|
</p>
|
||||||
value={formData.projectType}
|
)}
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
<option value="">Select service...</option>
|
|
||||||
<option>Fence staining — new wood</option>
|
|
||||||
<option>Fence staining — existing / restoration</option>
|
|
||||||
<option>Deck staining — new wood</option>
|
|
||||||
<option>Deck staining — restoration</option>
|
|
||||||
<option>Pergola / structure staining</option>
|
|
||||||
<option>Log cabin / cedar siding</option>
|
|
||||||
<option>Pre-staining — fence boards before install</option>
|
|
||||||
<option>Expert Stain & Seal product only — contractor purchase</option>
|
|
||||||
<option>Multiple services — describe below</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div className="qrow">
|
<button type="submit" className="qbtn btn-white-orange" disabled={status === "submitting"}>
|
||||||
<div>
|
{status === "submitting" ? "SENDING..." : "SEND QUOTE REQUEST →"}
|
||||||
<label className="ql text-white">CITY / LOCATION</label>
|
</button>
|
||||||
<input
|
</form>
|
||||||
type="text"
|
)}
|
||||||
name="location"
|
|
||||||
className="qi"
|
|
||||||
placeholder="Kitchener, Guelph..."
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="ql text-white">APPROXIMATE SIZE</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="size"
|
|
||||||
className="qi"
|
|
||||||
placeholder="e.g. 150 ft fence / 400 sq ft deck"
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" className="qbtn btn-white-orange">SEND QUOTE REQUEST →</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user