// ============================================================
// Happy Fence Quote Quiz — React 18 + Babel Standalone
// Loaded as an external script so WordPress doesn't mangle
// the && operators in this file.
//
// Update log:
// 2026-05-08 - Promoted A2P 10DLC SMS consent to its own dedicated
// final screen, but kept the user-facing step counter at 5 (not 6)
// so the consent reads as a final-confirmation continuation of
// Step 5 rather than a new piece of information being collected.
// Implementation: TOTAL = 6 internally for state navigation, but
// TOTAL_DISPLAY = 5 drives the progress bar fill, "Step X of Y"
// label, and time estimate. The consent screen's StepHeading
// kicker shows "Final step" (no number). Step 6 renders a yellow
// "One last thing" card with custom 26px brand checkbox, a
// state-aware helper line ("↑ Check the box to unlock submit"
// -> "✓ All set - click submit below"), and a full-width submit
// button whose disabled vs active treatment is unmistakable.
// Step 5 (contact form) needs a manual "Next ->" button since it
// no longer holds submit. Auto-advance still applies to steps
// 1-4. Modal disclosure + Zapier consent payload (sms_consent,
// sms_consent_text, sms_consent_at) carry forward unchanged.
// ============================================================
// ZAPIER WEBHOOK
// 1. In Zapier: Create Zap -> "Webhooks by Zapier" -> "Catch Hook"
// 2. Copy the webhook URL
// 3. Paste it below, replacing PASTE_YOUR_ZAPIER_WEBHOOK_URL_HERE
const ZAPIER_WEBHOOK_URL = "PASTE_YOUR_ZAPIER_WEBHOOK_URL_HERE";
// Internal step count includes the consent screen as step 6.
// TOTAL_DISPLAY is what the user sees in the progress bar / counter
// — we keep it at 5 so the consent screen reads as a continuation
// of step 5, not a new step.
const TOTAL = 6;
const TOTAL_DISPLAY = 5;
// A2P 10DLC required disclosure shown in the consent popup.
// Must match what the visible UI tells the user they're agreeing to.
const SMS_CONSENT_TEXT = "By submitting, you authorize Happy Fence Company LLC to text/call the number above for informational/transactional messages, possibly using automated means. Msg/data rates apply, msg frequency varies. Consent is not a condition of purchase. See terms (https://www.leadconnectorhq.com/terms2) and privacy policy (https://www.leadconnectorhq.com/privacy-policy). Text HELP for help and STOP to unsubscribe.";
const MATERIALS = [
{ key:'wood', name:'Wood', price:'$', life:'Lasts 10\u201315 years',
blurb:'Pressure-treated pine or cedar. Classic look, warm character.',
color:'#a0785a' },
{ key:'durafence', name:'Durafence', price:'$$', life:'Lasts 40+ years',
blurb:'Galvanized steel. Hurricane-tough. Bulletproof.',
color:'var(--yellow-dk)' },
{ key:'vinyl', name:'Vinyl', price:'$$$', life:'Lasts 20\u201330 years',
blurb:'Zero maintenance, fade-resistant. HOA favorite.',
color:'var(--blue-dk)' },
{ key:'aluminum', name:'Custom Aluminum', price:'$$$$', life:'Lasts 30+ years',
blurb:'Decorative, pool-code compliant. Built to last.',
color:'#8a8f99' },
{ key:'unsure', name:'Not sure \u2014 help me decide', price:'\u2014', life:'Expert recommends on the call',
blurb:"Tell us the goal \u2014 we'll match the right material.",
color:'#ccd5de' },
];
const FEET = [
{ key:'u80', name:'Under 80 ft', sub:'Small yard / partial section' },
{ key:'80_150', name:'80 \u2013 150 ft', sub:'Typical backyard' },
{ key:'150_250',name:'150 \u2013 250 ft', sub:'Full property perimeter' },
{ key:'250p', name:'250+ ft', sub:'Large lot / double lot' },
{ key:'unsure', name:'Not sure', sub:"We'll measure on the walkthrough" },
];
const TIMELINE = [
{ key:'asap', name:'ASAP', sub:'Within 2 weeks', tag:'Priority' },
{ key:'2_6', name:'2 \u2013 6 weeks', sub:'Standard booking' },
{ key:'1_3m', name:'1 \u2013 3 months', sub:'Planning ahead' },
{ key:'browse', name:'Just exploring', sub:'Gathering info' },
];
const PERMITS = [
{ key:'yes', name:'Yes, please', sub:'Pull permits for me' },
{ key:'no', name:'No thanks', sub:"I've got it handled" },
{ key:'unsure', name:'Not sure', sub:"We'll walk you through it" },
];
function ProgressBar({ step, compact }) {
// Clamp the displayed step to TOTAL_DISPLAY so the consent screen
// (internal step 6) reads as "Step 5 of 5" with the bar at 100%.
const displayStep = Math.min(step, TOTAL_DISPLAY);
const pct = (displayStep / TOTAL_DISPLAY) * 100;
return (
Step {displayStep} of {TOTAL_DISPLAY}
~{Math.max(0, (TOTAL_DISPLAY - displayStep + 1) * 15)} sec left
{"By submitting, you authorize Happy Fence Company LLC to text/call the number above for informational/transactional messages, possibly using automated means. Msg/data rates apply, msg frequency varies. Consent is not a condition of purchase. "}
See terms
{" and "}
privacy policy
{". Text HELP for help and STOP to unsubscribe."}
{[
'A rep calls you to grab the basics',
'You send us a short backyard video',
'We book a Zoom walkthrough (often within 48 hrs)',
'You get your full quote on the Zoom',
].map((t,i) => (
{"I agree to receive "}SMS & calls{" from Happy Fence Company at the number above. "}
{consent ? (
{'All set — click submit below'}
) : '↑ Check the box to unlock submit'}
);
}
function SuccessScreen({ compact }) {
return (
You're in good hands.
{"A rep will reach out shortly to grab your basics and request a short video of your backyard. Once we have it, we'll book a Zoom walkthrough \u2014 usually within 48 hours \u2014 and you'll get your full quote live on that call."}