Add calculator UX enhancements and submission tracking
- Button loading spinner + disable on submit to prevent duplicate AI calls - Email field and opt-in consent checkbox on calculator form (checked by default) - Privacy assurance blurb below opt-in - Refinement blurb on results screen explaining live cash-flow optimization - calc_submissions SQLite table stores form inputs, computed results, AI text, email, opt-in - GET /api/calc-submissions endpoint (x-admin-key protected) to retrieve submissions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
20
app.js
20
app.js
@@ -52,6 +52,16 @@
|
||||
close();
|
||||
});
|
||||
|
||||
const calcBtnText = submitBtn?.querySelector('.calc-btn-text');
|
||||
const calcBtnLoading = submitBtn?.querySelector('.calc-btn-loading');
|
||||
|
||||
function setCalcLoading(on) {
|
||||
if (!submitBtn) return;
|
||||
submitBtn.disabled = on;
|
||||
calcBtnText?.classList.toggle('hidden', on);
|
||||
calcBtnLoading?.classList.toggle('hidden', !on);
|
||||
}
|
||||
|
||||
submitBtn?.addEventListener('click', async () => {
|
||||
const homesites = parseFloat(document.getElementById('calcHomesites').value) || 0;
|
||||
const propertyType = document.getElementById('calcPropertyType').value;
|
||||
@@ -59,12 +69,15 @@
|
||||
const paymentFreq = document.getElementById('calcPaymentFreq').value;
|
||||
const reserveFunds = parseFloat(document.getElementById('calcReserveFunds').value) || 0;
|
||||
const interest2025 = parseFloat(document.getElementById('calcInterest2025').value) || 0;
|
||||
const calcEmail = document.getElementById('calcEmail')?.value.trim() || '';
|
||||
const calcOptIn = document.getElementById('calcOptIn')?.checked ?? true;
|
||||
|
||||
if (!homesites || !annualIncome) {
|
||||
calcErr.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
calcErr.classList.add('hidden');
|
||||
setCalcLoading(true);
|
||||
|
||||
// ── Conservative investment assumptions ──
|
||||
// Operating cash: depending on payment frequency, portion investable in high-yield savings
|
||||
@@ -121,7 +134,11 @@
|
||||
const aiRes = await fetch('/api/calculate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ homesites, propertyType, annualIncome, paymentFreq, reserveFunds, interest2025 }),
|
||||
body: JSON.stringify({
|
||||
homesites, propertyType, annualIncome, paymentFreq, reserveFunds, interest2025,
|
||||
email: calcEmail, optIn: calcOptIn,
|
||||
totalPotential, opInterest, resInterest,
|
||||
}),
|
||||
});
|
||||
if (aiRes.ok) {
|
||||
const { recommendation } = await aiRes.json();
|
||||
@@ -136,6 +153,7 @@
|
||||
// ── Animate the main number ──
|
||||
animateValue(document.getElementById('resultAmount'), 0, totalPotential);
|
||||
|
||||
setCalcLoading(false);
|
||||
calcForm.classList.add('hidden');
|
||||
calcRes.classList.remove('hidden');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user