<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wise Capital Rate Watch | Monitor Your Refinance Savings</title>
<!-- Load Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Use Inter font -->
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #f7f9fb;
}
/* Custom styling for the progress bar to look sleek */
.progress-step {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
color: #e5e7eb;
background-color: #cbd5e1;
transition: all 0.3s ease;
}
.progress-step.active {
background-color: #059669; /* Green for active/completed */
color: white;
box-shadow: 0 4px 10px rgba(5, 150, 105, 0.5);
}
.progress-step.completed {
background-color: #10b981; /* Lighter green for completed */
color: white;
}
/* Style for the CTA button - Ensures good touch target size */
.cta-button {
background-color: #059669;
box-shadow: 0 4px 15px rgba(5, 150, 105, 0.4);
transition: all 0.2s ease;
min-height: 48px; /* Mobile touch target standard */
}
.cta-button:hover {
background-color: #047857;
transform: translateY(-1px);
}
/* Ensures inputs are easily tappable */
.form-input {
width: 100%;
padding: 12px;
margin-bottom: 16px;
border: 1px solid #d1d5db;
border-radius: 8px;
transition: border-color 0.2s;
}
.form-input:focus {
border-color: #059669;
outline: none;
box-shadow: 0 0 0 2px rgba(5, 150, 105, 0.2);
}
</style>
</head>
<body class="min-h-screen flex items-center justify-center p-4">
<!-- Main Container -->
<div id="funnel-container" class="bg-white rounded-2xl shadow-2xl p-6 sm:p-10 w-full max-w-lg transition-all duration-500">
<!-- Header -->
<div id="header-content" class="text-center mb-6">
<h1 class="text-3xl sm:text-4xl font-extrabold text-gray-900 leading-tight">
Stop Guessing. <span class="text-green-600">Start Saving.</span>
</h1>
<p class="mt-2 text-gray-600 text-lg">Set Your Perfect Refi Rate Target and Let Wise Capital's AI Monitor the Market 24/7.</p>
</div>
<!-- Progress Bar -->
<div id="progress-bar" class="flex justify-between items-center mb-8">
<div class="flex-1 flex items-center">
<div id="step-1-status" class="progress-step active">1</div>
<div class="flex-grow h-1 bg-gray-200 mx-2 rounded-full"></div>
</div>
<div class="flex-1 flex items-center">
<div id="step-2-status" class="progress-step">2</div>
<div class="flex-grow h-1 bg-gray-200 mx-2 rounded-full"></div>
</div>
<div class="progress-step" id="step-3-status">3</div>
</div>
<!-- Form Content -->
<form id="refi-form" onsubmit="return false;">
<!-- Step 1: Prequalification & Property Details -->
<div id="step-1" class="form-step">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Step 1: Tell us about your home.</h2>
<label for="mortgage-status" class="block text-sm font-medium text-gray-700 mb-2">Current Property Status</label>
<select id="mortgage-status" required class="form-input focus:ring-green-500 focus:border-green-500">
<option value="" disabled selected>Select an option</option>
<option value="Primary Residence">Primary Residence</option>
<option value="Secondary Home">Secondary Home</option>
<option value="Investment Property">Investment Property</option>
</select>
<label class="block text-sm font-medium text-gray-700 mb-2">Your Main Loan Goal</label>
<div class="space-y-2 mb-4">
<label class="flex items-center text-gray-700">
<input type="checkbox" name="loan-goal" value="Lower Payment" class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500">
<span class="ml-2 text-sm">Lower Monthly Payment</span>
</label>
<label class="flex items-center text-gray-700">
<input type="checkbox" name="loan-goal" value="Cash Out/Consolidation" class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500">
<span class="ml-2 text-sm">Cash Out/Consolidation</span>
</label>
<label class="flex items-center text-gray-700">
<input type="checkbox" name="loan-goal" value="Shorten Loan Term" class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500">
<span class="ml-2 text-sm">Shorten Loan Term (e.g., 30yr to 15yr)</span>
</label>
<label class="flex items-center text-gray-700">
<input type="checkbox" name="loan-goal" value="Other" class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500">
<span class="ml-2 text-sm">Other</span>
</label>
</div>
<label for="credit-estimate" class="block text-sm font-medium text-gray-700 mb-2">Estimated Credit Score</label>
<select id="credit-estimate" required class="form-input focus:ring-green-500 focus:border-green-500">
<option value="" disabled selected>Select your range</option>
<option value="Excellent (740+)">Excellent (740+)</option>
<option value="Good (700-739)">Good (700-739)</option>
<option value="Average (660-699)">Average (660-699)</option>
<option value="Fair (600-659)">Fair (600-659)</option>
<option value="Needs Work (< 600)">Needs Work (< 600)</option>
</select>
<!-- Subject Property Address Fields -->
<h3 class="text-base font-semibold text-gray-800 mb-2 mt-4">Property Address (To monitor market rates in your area)</h3>
<label for="street-address" class="block text-sm font-medium text-gray-700 mb-1">Street Address</label>
<input type="text" id="street-address" placeholder="123 Main St" required class="form-input focus:ring-green-500 focus:border-green-500">
<div class="grid grid-cols-2 gap-4">
<div>
<label for="city" class="block text-sm font-medium text-gray-700 mb-1">City</label>
<input type="text" id="city" placeholder="Anytown" required class="form-input focus:ring-green-500 focus:border-green-500">
</div>
<div>
<label for="state" class="block text-sm font-medium text-gray-700 mb-1">State</label>
<input type="text" id="state" placeholder="CA" required class="form-input focus:ring-green-500 focus:border-green-500" maxlength="2" style="text-transform:uppercase;">
</div>
</div>
<div>
<label for="zip-code" class="block text-sm font-medium text-gray-700 mb-1">Zip Code</label>
<input type="text" id="zip-code" placeholder="12345" required class="form-input focus:ring-green-500 focus:border-green-500">
</div>
<!-- Additional Properties Checkbox (Kept simple) -->
<div class="mt-2 mb-6 p-3 bg-gray-50 rounded-lg border border-gray-200">
<label class="flex items-center text-gray-700 cursor-pointer">
<input type="checkbox" id="additional-properties-check" class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500">
<span class="ml-2 text-sm font-medium">I have other properties I might want to refinance.</span>
</label>
</div>
<!-- Dynamic Fields for Additional Properties REMOVED here, moved to post-conversion -->
<button type="button" onclick="handleStepOneCompletion()" class="cta-button w-full text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-green-300">
Next: Enter Mortgage Details
</button>
</div>
<!-- Step 2: Mortgage Specifics (Qualification Data) -->
<div id="step-2" class="form-step hidden">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Step 2: Mortgage Details & Goal Rate</h2>
<label for="current-balance" class="block text-sm font-medium text-gray-700 mb-2">Approximate Current Loan Balance ($)</label>
<input type="number" id="current-balance" placeholder="e.g., 350000" required class="form-input focus:ring-green-500 focus:border-green-500" min="10000">
<label for="current-rate" class="block text-sm font-medium text-gray-700 mb-2">Approximate Current Interest Rate (%)</label>
<input type="number" id="current-rate" step="0.01" placeholder="e.g., 7.50" required class="form-input focus:ring-green-500 focus:border-green-500" min="1" max="20">
<!-- **NEW FIELD** Estimated Property Value -->
<label for="estimated-value" class="block text-sm font-medium text-gray-700 mb-2">Estimated Property Value ($)</label>
<input type="number" id="estimated-value" placeholder="e.g., 500000" required class="form-input focus:ring-green-500 focus:border-green-500" min="50000">
<!-- END NEW FIELD -->
<label for="target-rate" class="block text-sm font-medium text-gray-700 mb-2">Target Refinance Rate (%)</label>
<div class="flex items-center mb-6">
<input type="number" id="target-rate" step="0.01" placeholder="e.g., 6.00" class="flex-grow form-input p-3 border border-gray-300 rounded-l-lg focus:ring-green-500 focus:border-green-500" min="1" max="15">
<button type="button" id="help-rate-button" class="bg-gray-200 text-gray-700 text-sm font-medium py-3 px-4 rounded-r-lg hover:bg-gray-300 transition-colors">
Help me determine my ideal rate
</button>
</div>
<div class="flex space-x-4">
<button type="button" onclick="prevStep(1)" class="w-1/2 bg-gray-500 hover:bg-gray-600 text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-gray-300">
Back
</button>
<button type="button" onclick="nextStep(3)" class="cta-button w-1/2 text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-green-300">
Next: Contact Info
</button>
</div>
</div>
<!-- Step 3: Contact & Opt-In (The Exchange) -->
<div id="step-3" class="form-step hidden">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Step 3: Activate Your Alert</h2>
<label for="full-name" class="block text-sm font-medium text-gray-700 mb-2">Full Name</label>
<input type="text" id="full-name" placeholder="John Doe" required class="form-input focus:ring-green-500 focus:border-green-500">
<label for="email-address" class="block text-sm font-medium text-gray-700 mb-2">Email Address (For Rate Watch Alerts)</label>
<input type="email" id="email-address" placeholder="john@example.com" required class="form-input focus:ring-green-500 focus:border-green-500">
<label for="phone-number" class="block text-sm font-medium text-gray-700 mb-2">Phone Number (For Urgent SMS Alerts)</label>
<input type="tel" id="phone-number" placeholder="(555) 555-5555" required class="form-input focus:ring-green-500 focus:border-green-500">
<!-- **NEW** Error Feedback Div for Step 3 Validation -->
<div id="step-3-error-feedback" class="hidden p-3 mb-4 text-center text-sm font-medium text-red-700 bg-red-100 rounded-lg" role="alert">
⚠️ Please ensure all required fields are filled out above before activating your alert.
</div>
<button type="submit" id="submit-button" class="cta-button w-full text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-green-300">
<span id="submit-text">Activate My Free Rate Watch Alert</span>
<svg id="loading-spinner" class="animate-spin -ml-1 mr-3 h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
<p class="text-xs text-gray-500 mt-2 text-center">By clicking, you agree to receive rate alerts and follow-up communication from Wise Capital Mortgage. We respect your privacy.</p>
</div>
</form>
<!-- Social Proof Area (Visible on all steps) -->
<div id="social-proof" class="mt-8 pt-6 border-t border-gray-100">
<h3 class="text-lg font-semibold text-gray-800 mb-4 text-center">Real Savings, Real Homeowners</h3>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 text-center">
<div class="p-3 bg-green-50 rounded-xl">
<p class="text-green-700 font-bold text-xl">$45,000 Saved</p>
<p class="text-sm text-gray-600">"The alert hit right when I needed it. So easy." - Sarah K.</p>
</div>
<div class="p-3 bg-green-50 rounded-xl">
<p class="text-green-700 font-bold text-xl">1.5% Lower Rate</p>
<p class="text-sm text-gray-600">"Proactive service is key in this market." - John D.</p>
</div>
<div class="p-3 bg-green-50 rounded-xl">
<p class="text-green-700 font-bold text-xl">Perfect Timing</p>
<p class="text-sm text-gray-600">"Alerted me on a Tuesday, locked on Thursday." - Maria L.</p>
</div>
</div>
</div>
</div>
<!-- Final Confirmation / Post-Conversion Step Container -->
<div id="final-step-container" class="hidden bg-white rounded-2xl shadow-2xl p-6 sm:p-10 w-full max-w-lg text-center">
<!-- Standard Thank You Screen (Shown if no additional properties were flagged) -->
<div id="standard-thank-you" class="text-center">
<svg class="mx-auto h-16 w-16 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<h2 class="mt-4 text-3xl font-extrabold text-gray-900">Your Wise Capital Rate Watch is Active!</h2>
<p class="mt-2 text-gray-600 text-lg">We have started monitoring the market for your **[Insert Target Rate]%** goal. Expect an immediate confirmation in your inbox.</p>
<div class="mt-6 p-4 bg-yellow-50 border-l-4 border-yellow-400 text-yellow-800 rounded-lg">
<h3 class="font-semibold mb-2">🎁 Immediate Value Hook:</h3>
<p class="text-sm">Download your **Current Mortgage Market Snapshot** now to understand the factors driving rates this week.</p>
<a href="#" class="inline-block mt-3 px-4 py-2 bg-yellow-500 text-white font-bold rounded-lg hover:bg-yellow-600 transition-colors">Download Market Snapshot (PDF Mock)</a>
</div>
<h3 class="mt-6 text-xl font-semibold text-gray-800">Ready to Fast Track Your Savings?</h3>
<p class="mt-2 text-gray-600">Skip the wait and speak with a Loan Officer today. It only takes 15 minutes.</p>
<a href="#" class="cta-button mt-4 inline-block w-full text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-green-300">
Schedule a Quick 15-Minute 'Refinance Strategy Session' Now (Simulated Link)
</a>
<p class="text-sm text-gray-500 mt-3">Look out for our first communication (SMS and Email) within the next 5 minutes!</p>
</div>
<!-- Post-Conversion Survey (Shown if additional properties were flagged) -->
<div id="post-conversion-survey" class="text-center hidden">
<h2 class="mt-4 text-3xl font-extrabold text-green-700">Almost Done! Maximize Your Savings.</h2>
<p class="mt-2 text-gray-600 text-lg">You indicated you have other properties. Let's add them to your Rate Watch portfolio in just one minute.</p>
<form id="additional-properties-form" onsubmit="return false;" class="text-left mt-6">
<!-- Dynamically populated property forms will go here -->
<div id="property-forms-container">
<!-- Property 1 Form (Initial property) -->
</div>
<div class="flex flex-col space-y-4">
<button type="button" id="add-property-button" class="bg-gray-200 text-gray-700 font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-gray-300 hover:bg-gray-300 transition-colors">
+ Add Another Property
</button>
<button type="button" onclick="saveAdditionalProperties()" class="cta-button w-full text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:ring-4 focus:ring-green-300">
<span id="finish-text">Finish & Activate Full Portfolio Watch</span>
<svg id="finish-spinner" class="animate-spin -ml-1 mr-3 h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
<button type="button" onclick="showStandardThankYou()" class="text-sm text-gray-500 mt-2 hover:text-gray-700">
No thanks, take me to my confirmation.
</button>
</div>
</form>
</div>
</div>
<!-- Error Modal (Replaces alert() for better UX) -->
<div id="error-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white p-6 rounded-xl shadow-2xl max-w-xs text-center transform transition-all duration-300 scale-100">
<svg class="mx-auto h-12 w-12 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.503-1.66 1.732-3.09L13.732 3.51a2 2 0 00-3.464 0L3.51 15.91a2 2 0 001.732 3.09z"></path></svg>
<p id="modal-message" class="text-md font-semibold text-gray-700 mt-3 mb-4"></p>
<button onclick="document.getElementById('error-modal').classList.add('hidden')" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg">
Close
</button>
</div>
</div>
<!-- Firebase/Form Logic -->
<script type="module">
// Data Layer Initialization (MUST be before any other script for tracking)
window.dataLayer = window.dataLayer || [];
// Import necessary Firebase modules
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js";
import { getAuth, signInAnonymously, signInWithCustomToken } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js";
import { getFirestore, collection, addDoc, setDoc, doc, setLogLevel } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js";
// Global Firebase and tracking variables
let db, auth, userId;
let docId = null; // Store Firestore Document ID for subsequent updates
let initialData = {}; // Store initial lead data for conditional routing
const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';
const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : null;
const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null;
const LEADS_COLLECTION_PATH = `artifacts/${appId}/public/data/refi_leads`;
// Form elements
const formSteps = [
document.getElementById('step-1'),
document.getElementById('step-2'),
document.getElementById('step-3')
];
const stepStatus = [
document.getElementById('step-1-status'),
document.getElementById('step-2-status'),
document.getElementById('step-3-status')
];
const funnelContainer = document.getElementById('funnel-container');
const finalStepContainer = document.getElementById('final-step-container');
const standardThankYou = document.getElementById('standard-thank-you');
const postConversionSurvey = document.getElementById('post-conversion-survey');
const submitButton = document.getElementById('submit-button');
const loadingSpinner = document.getElementById('loading-spinner');
const additionalPropertiesCheck = document.getElementById('additional-properties-check');
const propertyFormsContainer = document.getElementById('property-forms-container');
const addPropertyButton = document.getElementById('add-property-button');
const errorModal = document.getElementById('error-modal');
const modalMessage = document.getElementById('modal-message');
const step3ErrorFeedback = document.getElementById('step-3-error-feedback'); // **NEW**
let currentStep = 1;
let propertyCount = 0; // Tracks dynamically added property forms
const MAX_PROPERTIES = 3;
/**
* Utility to display a custom error modal.
* @param {string} message - The message to display.
*/
function displayErrorModal(message) {
modalMessage.textContent = message;
errorModal.classList.remove('hidden');
}
/**
* Initialize Firebase connection and sign in.
*/
async function initFirebase() {
try {
if (!firebaseConfig) {
console.error("Firebase configuration is missing.");
return;
}
setLogLevel('Debug');
const app = initializeApp(firebaseConfig);
db = getFirestore(app);
auth = getAuth(app);
// Sign in using custom token or anonymously
if (initialAuthToken) {
await signInWithCustomToken(auth, initialAuthToken);
} else {
await signInAnonymously(auth);
}
userId = auth.currentUser?.uid || crypto.randomUUID();
console.log("Firebase initialized. User ID:", userId);
} catch (error) {
console.error("Error initializing Firebase:", error);
userId = crypto.randomUUID();
}
}
// Initialize Firebase when the script loads
initFirebase();
/**
* Generates the HTML for a single additional property form.
*/
function createPropertyForm(index) {
const title = index === 1 ? "First Additional Property" : `Property #${index}`;
return `
<div class="p-4 bg-green-50 rounded-lg mb-6 border border-green-200" data-property-index="${index}">
<h4 class="text-base font-bold text-green-800 mb-4">${title}</h4>
<label for="prop-${index}-address" class="block text-sm font-medium text-gray-700 mb-1">Address</label>
<input type="text" id="prop-${index}-address" placeholder="Street, City, Zip" required class="form-input focus:ring-green-500 focus:border-green-500">
<div class="grid grid-cols-2 gap-4">
<div>
<label for="prop-${index}-rate" class="block text-sm font-medium text-gray-700 mb-1">Current Rate (%)</label>
<input type="number" step="0.01" id="prop-${index}-rate" placeholder="5.50" required class="form-input focus:ring-green-500 focus:border-green-500">
</div>
<div>
<label for="prop-${index}-balance" class="block text-sm font-medium text-gray-700 mb-1">Loan Balance ($)</label>
<input type="number" id="prop-${index}-balance" placeholder="250000" required class="form-input focus:ring-green-500 focus:border-green-500">
</div>
</div>
<label for="prop-${index}-value" class="block text-sm font-medium text-gray-700 mb-1">Estimated Value ($)</label>
<input type="number" id="prop-${index}-value" placeholder="400000" required class="form-input focus:ring-green-500 focus:border-green-500">
</div>
`;
}
/**
* Adds a new property form to the post-conversion survey.
*/
addPropertyButton.addEventListener('click', () => {
if (propertyCount < MAX_PROPERTIES) {
propertyCount++;
propertyFormsContainer.insertAdjacentHTML('beforeend', createPropertyForm(propertyCount));
if (propertyCount >= MAX_PROPERTIES) {
addPropertyButton.classList.add('hidden');
}
}
});
/**
* Collects and returns lead data from Step 1.
*/
function collectStepOneData(status) {
const loanGoals = Array.from(document.querySelectorAll('input[name="loan-goal"]:checked')).map(cb => cb.value);
return {
appId: appId,
userId: userId,
timestamp: new Date().toISOString(),
status: status, // 'partial' or 'complete'
// Step 1 Data
mortgageStatus: document.getElementById('mortgage-status').value,
loanGoal: loanGoals,
creditEstimate: document.getElementById('credit-estimate').value,
// Address Fields
propertyAddress: {
street: document.getElementById('street-address').value,
city: document.getElementById('city').value,
state: document.getElementById('state').value.toUpperCase(), // **NEW: Capture State**
zip: document.getElementById('zip-code').value,
},
// Additional Properties Flag (Crucial for post-conversion routing)
hasAdditionalProperties: additionalPropertiesCheck.checked,
};
}
/**
* Saves partial lead data to Firestore (for abandonment tracking).
*/
async function savePartialLead() {
if (!db || !userId) return console.warn("Firestore not ready for saving partial lead.");
try {
const leadData = collectStepOneData('partial');
initialData = leadData; // Store initial data for Step 3 processing
const leadsCollectionRef = collection(db, LEADS_COLLECTION_PATH);
if (!docId) {
// First time saving - create a new document
const newDoc = await addDoc(leadsCollectionRef, leadData);
docId = newDoc.id; // Store ID for future updates
console.log("Partial lead captured (Step 1). Doc ID:", docId);
} else {
// Updating an existing document
await setDoc(doc(db, LEADS_COLLECTION_PATH, docId), leadData, { merge: true });
console.log("Partial lead updated (Step 1). Doc ID:", docId);
}
return true;
} catch (error) {
console.error("Error saving partial lead:", error);
return false;
}
}
/**
* Handles the click event for the Step 1 'Next' button.
*/
window.handleStepOneCompletion = async function() {
const currentStepIndex = 0;
const nextStepIndex = 1;
// Validation Check
const currentStepInputs = formSteps[currentStepIndex].querySelectorAll('[required]');
let isValid = true;
currentStepInputs.forEach(input => {
if (!input.value) {
isValid = false;
input.classList.add('border-red-500');
input.classList.remove('focus:border-green-500');
} else {
input.classList.remove('border-red-500');
input.classList.add('focus:border-green-500');
}
});
if (!isValid) {
const firstInvalid = formSteps[currentStepIndex].querySelector('.border-red-500');
if (firstInvalid) {
firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
return;
}
// 1. SAVE PARTIAL LEAD (Abandonment Capture)
const saveSuccess = await savePartialLead();
if (saveSuccess) {
// 2. DATA LAYER CONVERSION PUSH
window.dataLayer.push({
event: 'funnel_step_1_conversion',
funnel_step: 1,
property_status: document.getElementById('mortgage-status').value,
zip_code: document.getElementById('zip-code').value
});
console.log("Data Layer event pushed: funnel_step_1_conversion");
// 3. UI Transition
stepStatus[currentStepIndex].classList.remove('active');
stepStatus[currentStepIndex].classList.add('completed');
stepStatus[nextStepIndex].classList.add('active');
formSteps[currentStepIndex].classList.add('hidden');
formSteps[nextStepIndex].classList.remove('hidden');
currentStep = 2;
} else {
console.error("Could not proceed to next step due to database error.");
}
}
/**
* Logic to move to the next form step (used for step 2 -> 3).
*/
window.nextStep = function(step) {
const currentStepIndex = currentStep - 1;
const nextStepIndex = step - 1;
// Simple validation check for the current step (Step 2)
const currentStepInputs = formSteps[currentStepIndex].querySelectorAll('[required]');
let isValid = true;
currentStepInputs.forEach(input => {
if (!input.value) {
isValid = false;
input.classList.add('border-red-500');
input.classList.remove('focus:border-green-500');
} else {
input.classList.remove('border-red-500');
input.classList.add('focus:border-green-500');
}
});
if (!isValid) {
const firstInvalid = formSteps[currentStepIndex].querySelector('.border-red-500');
if (firstInvalid) {
firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
return;
}
// Update progress bar
stepStatus[currentStepIndex].classList.remove('active');
stepStatus[currentStepIndex].classList.add('completed');
stepStatus[nextStepIndex].classList.add('active');
// Hide current step, show next step
formSteps[currentStepIndex].classList.add('hidden');
formSteps[nextStepIndex].classList.remove('hidden');
currentStep = step;
}
/**
* Logic to move to the previous form step.
*/
window.prevStep = function(step) {
const currentStepIndex = currentStep - 1;
const prevStepIndex = step - 1;
// Update progress bar
stepStatus[currentStepIndex].classList.remove('active', 'completed');
stepStatus[prevStepIndex].classList.add('active');
stepStatus[prevStepIndex].classList.remove('completed');
// Hide current step, show previous step
formSteps[currentStepIndex].classList.add('hidden');
formSteps[prevStepIndex].classList.remove('hidden');
currentStep = step;
}
/**
* Logic to show the standard thank you screen (used as fallback/skip for survey).
*/
window.showStandardThankYou = function() {
postConversionSurvey.classList.add('hidden');
standardThankYou.classList.remove('hidden');
}
/**
* Handle final form submission (Step 3) and route to post-conversion survey if needed.
*/
document.getElementById('refi-form').addEventListener('submit', async (e) => {
e.preventDefault();
// Reset feedback on attempt
step3ErrorFeedback.classList.add('hidden');
let firstInvalidInput = null;
// Final validation for step 3
const finalInputs = formSteps[2].querySelectorAll('[required]');
let isValid = true;
finalInputs.forEach(input => {
if (!input.value) {
isValid = false;
input.classList.add('border-red-500');
input.classList.remove('focus:border-green-500');
if (!firstInvalidInput) {
firstInvalidInput = input;
}
} else {
input.classList.remove('border-red-500');
input.classList.add('focus:border-green-500');
}
});
// **FIXED LOGIC**: If validation fails, show error and stop.
if (!isValid) {
step3ErrorFeedback.classList.remove('hidden');
if (firstInvalidInput) {
firstInvalidInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
return;
}
submitButton.disabled = true;
loadingSpinner.classList.remove('hidden');
document.getElementById('submit-text').classList.add('hidden');
try {
// Gather all final data for update
const finalLeadData = {
...initialData, // Includes all Step 1 data and hasAdditionalProperties flag
status: 'complete',
// Step 2 Data
currentBalance: parseFloat(document.getElementById('current-balance').value),
currentRate: parseFloat(document.getElementById('current-rate').value),
estimatedValue: parseFloat(document.getElementById('estimated-value').value), // **NEW: Capture Estimated Value**
targetRate: document.getElementById('target-rate').value || 'LO Assisted',
// Step 3 Data (Contact Info)
fullName: document.getElementById('full-name').value,
email: document.getElementById('email-address').value,
phone: document.getElementById('phone-number').value,
timestamp_complete: new Date().toISOString()
};
if (db && docId) {
await setDoc(doc(db, LEADS_COLLECTION_PATH, docId), finalLeadData, { merge: true });
console.log("Step 3 submission updated Firestore record:", docId);
// Update Thank You Screen with the target rate
const targetRateDisplay = document.querySelector('#standard-thank-you p.mt-2');
if (targetRateDisplay) {
targetRateDisplay.innerHTML = targetRateDisplay.innerHTML.replace('[Insert Target Rate]', finalLeadData.targetRate);
}
// Final Data Layer Event (Conversion)
window.dataLayer.push({
event: 'funnel_complete',
lead_doc_id: docId,
target_rate: finalLeadData.targetRate
});
// ROUTING LOGIC: Transition to final step
funnelContainer.classList.add('hidden');
finalStepContainer.classList.remove('hidden');
if (finalLeadData.hasAdditionalProperties) {
// Show post-conversion survey
standardThankYou.classList.add('hidden');
postConversionSurvey.classList.remove('hidden');
// Initialize first property form only if opting in
propertyFormsContainer.innerHTML = createPropertyForm(1);
propertyCount = 1;
if (propertyCount >= MAX_PROPERTIES) {
addPropertyButton.classList.add('hidden');
} else {
addPropertyButton.classList.remove('hidden');
}
} else {
// Show standard thank you
showStandardThankYou();
}
} else {
console.error("Firestore error. Simulating success...");
funnelContainer.classList.add('hidden');
finalStepContainer.classList.remove('hidden');
showStandardThankYou();
}
} catch (error) {
console.error("Error submitting final lead data:", error);
displayErrorModal("A network error occurred while submitting your data. Please check your connection and try again.");
} finally {
loadingSpinner.classList.add('hidden');
document.getElementById('submit-text').classList.remove('hidden');
submitButton.disabled = false;
}
});
/**
* Saves the detailed additional property data to Firestore.
*/
window.saveAdditionalProperties = async function() {
const finishButton = document.querySelector('#post-conversion-survey .cta-button');
const finishSpinner = document.getElementById('finish-spinner');
const finishText = document.getElementById('finish-text');
// Collect all property data
const properties = [];
let formIsValid = true;
for (let i = 1; i <= propertyCount; i++) {
const addressInput = document.getElementById(`prop-${i}-address`);
const rateInput = document.getElementById(`prop-${i}-rate`);
const balanceInput = document.getElementById(`prop-${i}-balance`);
const valueInput = document.getElementById(`prop-${i}-value`);
const propertyContainer = document.querySelector(`[data-property-index="${i}"]`);
// Reset error highlights
const inputs = propertyContainer.querySelectorAll('.form-input');
inputs.forEach(input => input.classList.remove('border-red-500'));
if (addressInput.value && rateInput.value && balanceInput.value && valueInput.value) {
properties.push({
address: addressInput.value,
currentRate: parseFloat(rateInput.value),
loanBalance: parseFloat(balanceInput.value),
estimatedValue: parseFloat(valueInput.value)
});
} else if (addressInput.value || rateInput.value || balanceInput.value || valueInput.value) {
// If any field is partially filled, we require all to be filled
formIsValid = false;
// Highlight all fields in the incomplete set
addressInput.classList.add('border-red-500');
rateInput.classList.add('border-red-500');
balanceInput.classList.add('border-red-500');
valueInput.classList.add('border-red-500');
displayErrorModal("Please fill all fields for Property #" + i + ", or remove the property to continue.");
break;
}
}
if (!formIsValid) return;
finishButton.disabled = true;
finishSpinner.classList.remove('hidden');
finishText.classList.add('hidden');
try {
if (db && docId) {
const updateData = {
additionalPropertiesList: properties,
numAdditionalProperties: properties.length,
// Mark data collection as successful
hasProvidedPortfolio: true
};
await setDoc(doc(db, LEADS_COLLECTION_PATH, docId), updateData, { merge: true });
console.log("Additional properties saved to lead document:", docId);
} else {
console.error("Cannot save properties: Database or Document ID missing.");
}
// Transition to the standard thank you screen after saving properties
showStandardThankYou();
} catch (error) {
console.error("Error saving additional properties:", error);
displayErrorModal("A network error occurred while saving your portfolio details. Please try again.");
} finally {
finishButton.disabled = false;
finishSpinner.classList.add('hidden');
finishText.classList.remove('hidden');
}
}
// Simple utility to manage the 'Help me determine my ideal rate' button
document.getElementById('help-rate-button').addEventListener('click', function() {
const targetRateInput = document.getElementById('target-rate');
targetRateInput.value = 'LO Assisted';
targetRateInput.required = false;
targetRateInput.placeholder = 'We will calculate this for you!';
this.textContent = 'LO Assistance Selected';
this.disabled = true;
targetRateInput.disabled = true;
});
</script>
</body>
</html>