← back to Wallpapercontractor

views/lead.ejs

297 lines

<%- include('partials/head', { title: 'Find Your Wallpaper Installer — ' + site.name, description: 'Tell us about your project. We match you with vetted, bonded, insured wallpaper installers in your area in 24 hours.' }) %>

<link rel="stylesheet" href="/css/funnel.css">

<main class="funnel">
  <div class="funnel-shell" data-step="1">

    <div class="funnel-progress" aria-hidden="true">
      <span class="dot active" data-dot="1"></span>
      <span class="dot" data-dot="2"></span>
      <span class="dot" data-dot="3"></span>
    </div>

    <form id="leadForm" novalidate>

      <!-- ───── STEP 1 — Project type ──────────────────────────────── -->
      <section class="step step-1" data-step="1">
        <div class="step-eyebrow">Step 1 of 3 · Project type</div>
        <h1 class="step-h">What kind of project<br>are we sizing?</h1>
        <p class="step-sub">Pick the closest match. We use this to route to the right specialty crew.</p>

        <div class="choice-grid" role="radiogroup" aria-label="Project type">
          <% const TYPES = [
            { id:'residential', title:'Single home',       sub:'Owner-occupied house, condo, or apartment.', icon:'home' },
            { id:'multifamily', title:'Multifamily',       sub:'Apartments, lofts, condo lobbies, common areas.', icon:'building' },
            { id:'hospitality', title:'Hospitality',       sub:'Hotels, restaurants, bars, spas, resorts.', icon:'wine' },
            { id:'retail',      title:'Retail / showroom', sub:'Stores, boutiques, salons, dealerships.', icon:'shop' },
            { id:'corporate',   title:'Corporate',         sub:'Offices, lobbies, conference rooms.', icon:'briefcase' },
            { id:'healthcare',  title:'Healthcare',        sub:'Hospitals, clinics, dental, senior living.', icon:'cross' },
          ] %>
          <% TYPES.forEach(function(t){ %>
            <label class="choice" data-icon="<%= t.icon %>">
              <input type="radio" name="project_type" value="<%= t.id %>" required>
              <div class="choice-body">
                <div class="choice-title"><%= t.title %></div>
                <div class="choice-sub"><%= t.sub %></div>
              </div>
              <div class="choice-check" aria-hidden="true">✓</div>
            </label>
          <% }) %>
        </div>

        <div class="step-actions">
          <button type="button" class="btn-primary" data-next="2" disabled>Continue →</button>
        </div>
      </section>

      <!-- ───── STEP 2 — Scope + location ──────────────────────────── -->
      <section class="step step-2" data-step="2" hidden>
        <div class="step-eyebrow">Step 2 of 3 · Scope &amp; location</div>
        <h1 class="step-h">Where, when,<br>and how big?</h1>
        <p class="step-sub">Rough numbers are fine. Installers will refine on the walkthrough.</p>

        <div class="form-grid">
          <label class="field">
            <span class="field-label">ZIP code</span>
            <input type="text" inputmode="numeric" pattern="[0-9]{5}" maxlength="5" name="zip" required placeholder="90210">
          </label>

          <label class="field">
            <span class="field-label">Approx. wall area</span>
            <select name="square_footage" required>
              <option value="">Select…</option>
              <option value="<200">Under 200 sq ft (one accent wall)</option>
              <option value="200-500">200–500 sq ft (one room)</option>
              <option value="500-1500">500–1,500 sq ft (multiple rooms)</option>
              <option value="1500-5000">1,500–5,000 sq ft (large home / suite)</option>
              <option value="5000+">5,000+ sq ft (commercial)</option>
            </select>
          </label>

          <label class="field">
            <span class="field-label">Timeline</span>
            <select name="timeline" required>
              <option value="">Select…</option>
              <option value="asap">As soon as possible</option>
              <option value="2-4w">2–4 weeks</option>
              <option value="1-3m">1–3 months</option>
              <option value="3-6m">3–6 months</option>
              <option value="planning">Just planning</option>
            </select>
          </label>

          <label class="field">
            <span class="field-label">Wallpaper status</span>
            <select name="material_status" required>
              <option value="">Select…</option>
              <option value="have">I already have the wallpaper</option>
              <option value="picked">I've picked it, not ordered</option>
              <option value="need_help">I still need to choose</option>
              <option value="commercial_grade">I need commercial-grade</option>
            </select>
          </label>

          <label class="field field-full">
            <span class="field-label">Project notes <span class="field-opt">(optional)</span></span>
            <textarea name="notes" rows="3" placeholder="Brief description, special requirements, mural/grasscloth/silk, prep needed, etc."></textarea>
          </label>
        </div>

        <div class="step-actions">
          <button type="button" class="btn-ghost" data-prev="1">← Back</button>
          <button type="button" class="btn-primary" data-next="3">Continue →</button>
        </div>
      </section>

      <!-- ───── STEP 3 — Contact ───────────────────────────────────── -->
      <section class="step step-3" data-step="3" hidden>
        <div class="step-eyebrow">Step 3 of 3 · Where to send your matches</div>
        <h1 class="step-h">Last bit. Then<br>installers come to you.</h1>
        <p class="step-sub">We send you 2–4 vetted matches in <strong>nationalpaperhangers.com</strong>'s installer marketplace within 24 hours. No spam, no shared lists.</p>

        <div class="form-grid">
          <label class="field">
            <span class="field-label">Your name</span>
            <input type="text" name="name" required autocomplete="name" placeholder="Jane Doe">
          </label>

          <label class="field">
            <span class="field-label">Email</span>
            <input type="email" name="email" required autocomplete="email" placeholder="jane@example.com">
          </label>

          <label class="field">
            <span class="field-label">Phone <span class="field-opt">(optional, faster matching)</span></span>
            <input type="tel" name="phone" autocomplete="tel" placeholder="(555) 123-4567">
          </label>

          <label class="field">
            <span class="field-label">I am a…</span>
            <select name="role" required>
              <option value="">Select…</option>
              <option value="homeowner">Homeowner</option>
              <option value="designer">Interior designer</option>
              <option value="architect">Architect</option>
              <option value="gc">General contractor</option>
              <option value="property_manager">Property manager</option>
              <option value="business_owner">Business owner</option>
              <option value="other">Other</option>
            </select>
          </label>
        </div>

        <label class="consent">
          <input type="checkbox" name="consent" required>
          <span>I agree to be contacted by matched installers about this project. <a href="/privacy" target="_blank" rel="noopener noreferrer">Privacy</a> · I can opt out anytime.</span>
        </label>

        <div class="step-actions">
          <button type="button" class="btn-ghost" data-prev="2">← Back</button>
          <button type="submit" class="btn-primary btn-submit">
            <span class="btn-label">Get my installer matches →</span>
            <span class="btn-spinner" aria-hidden="true"></span>
          </button>
        </div>

        <div id="leadError" class="lead-error" role="alert" hidden></div>
      </section>

      <!-- ───── SUCCESS ────────────────────────────────────────────── -->
      <section class="step step-done" data-step="done" hidden>
        <div class="done-mark" aria-hidden="true">✓</div>
        <h1 class="step-h">You're matched.</h1>
        <p class="step-sub">We're routing you to <strong>National Paper Hangers</strong> — our installer marketplace — where you can browse the vetted installers we've selected for your project.</p>
        <p class="step-meta">Redirecting in <span id="redirCount">3</span>s…</p>
        <p><a id="redirNow" href="https://nationalpaperhangers.com" class="btn-primary">Take me there now →</a></p>
      </section>

    </form>

    <!-- Trust strip — visible all steps -->
    <aside class="trust-strip">
      <div class="trust-item">
        <div class="trust-num">524</div>
        <div class="trust-label">Vetted installers</div>
      </div>
      <div class="trust-item">
        <div class="trust-num">100%</div>
        <div class="trust-label">Bonded &amp; insured</div>
      </div>
      <div class="trust-item">
        <div class="trust-num">24h</div>
        <div class="trust-label">Match turnaround</div>
      </div>
      <div class="trust-item">
        <div class="trust-num">$0</div>
        <div class="trust-label">To get matched</div>
      </div>
    </aside>

  </div>
</main>

<script>
(function(){
  var shell = document.querySelector('.funnel-shell');
  var form  = document.getElementById('leadForm');
  var steps = form.querySelectorAll('.step');
  var dots  = document.querySelectorAll('.funnel-progress .dot');

  function go(stepNum){
    steps.forEach(function(s){
      s.hidden = (s.dataset.step !== String(stepNum));
    });
    dots.forEach(function(d){
      var n = Number(d.dataset.dot);
      d.classList.toggle('active', n <= Number(stepNum));
    });
    shell.dataset.step = String(stepNum);
    window.scrollTo({ top: 0, behavior: 'smooth' });
    if (window.gtag) gtag('event','funnel_step',{step: stepNum});
  }

  // Step-1 enable continue when a project type is chosen
  form.querySelectorAll('input[name="project_type"]').forEach(function(r){
    r.addEventListener('change', function(){
      var btn = form.querySelector('button[data-next="2"]');
      btn.disabled = false;
    });
  });

  // next/prev wiring
  form.addEventListener('click', function(ev){
    var t = ev.target.closest('button');
    if (!t) return;
    if (t.dataset.next){
      // validate the current step's required fields before advancing
      var current = form.querySelector('.step:not([hidden])');
      var bad = false;
      current.querySelectorAll('input[required], select[required], textarea[required]').forEach(function(el){
        if (!el.checkValidity()){
          el.reportValidity();
          bad = true;
        }
      });
      if (bad) return;
      go(t.dataset.next);
    } else if (t.dataset.prev){
      go(t.dataset.prev);
    }
  });

  // submit
  form.addEventListener('submit', function(ev){
    ev.preventDefault();
    var btn = form.querySelector('.btn-submit');
    var err = document.getElementById('leadError');
    err.hidden = true;
    btn.classList.add('loading');
    btn.disabled = true;

    var data = {};
    new FormData(form).forEach(function(v,k){ data[k]=v; });

    fetch('/api/lead', {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body: JSON.stringify(data)
    })
    .then(function(r){ return r.json().then(function(j){ return {ok:r.ok, status:r.status, body:j}; }); })
    .then(function(res){
      if (!res.ok){
        err.textContent = (res.body && res.body.error) || 'Something went wrong. Please try again.';
        err.hidden = false;
        btn.classList.remove('loading');
        btn.disabled = false;
        return;
      }
      if (window.gtag) gtag('event','generate_lead',{value:1, currency:'USD'});
      go('done');
      var redirUrl = res.body.redirect || 'https://nationalpaperhangers.com';
      var a = document.getElementById('redirNow');
      a.href = redirUrl;
      var n = 3;
      var counter = setInterval(function(){
        n -= 1;
        document.getElementById('redirCount').textContent = String(Math.max(n,0));
        if (n <= 0){
          clearInterval(counter);
          window.location.href = redirUrl;
        }
      }, 1000);
    })
    .catch(function(){
      err.textContent = 'Network error. Please try again.';
      err.hidden = false;
      btn.classList.remove('loading');
      btn.disabled = false;
    });
  });

  go(1);
})();
</script>

<%- include('partials/foot') %>