export function salesPipelineHealthQuiz(form: FormTs) {
form.setTitle(() => '📊 How Healthy Is Your Sales Pipeline?');
// ============ SCORING SYSTEM ============
const scores = form.state<Record<string, number>>({});
const updateScore = (category: string, points: number) => {
scores.update(current => ({ ...current, [category]: points }));
};
const getTotalScore = () => {
const s = scores();
return Object.values(s).reduce((sum, val) => sum + (val || 0), 0);
};
const getMaxScore = () => 100;
const getScorePercentage = () => Math.round((getTotalScore() / getMaxScore()) * 100);
const getHealthLevel = (): 'critical' | 'weak' | 'healthy' | 'strong' => {
const pct = getScorePercentage();
if (pct >= 80) return 'strong';
if (pct >= 60) return 'healthy';
if (pct >= 40) return 'weak';
return 'critical';
};
const getHealthLabel = () => {
const level = getHealthLevel();
const labels = {
critical: '🔴 Critical - Pipeline Needs Urgent Attention',
weak: '🟡 Weak - Significant Gaps to Address',
healthy: '🟢 Healthy - Good Foundation',
strong: '💪 Strong - High-Performing Pipeline'
};
return labels[level];
};
const getHealthColor = () => {
const level = getHealthLevel();
const colors = { critical: '#dc2626', weak: '#ca8a04', healthy: '#059669', strong: '#7c3aed' };
return colors[level];
};
// ============ COMPLETION SCREEN ============
form.configureCompletionScreen({
type: 'text',
title: () => getHealthLabel(),
message: () => {
const pct = getScorePercentage();
const level = getHealthLevel();
const messages = {
critical: `Your pipeline health score is ${pct}%. Your sales pipeline has critical gaps that are likely costing you revenue. Download your report for immediate action items.`,
weak: `Your pipeline health score is ${pct}%. There are significant opportunities to improve your pipeline efficiency. Review your personalized recommendations.`,
healthy: `Your pipeline health score is ${pct}%. Your pipeline is in good shape with room for optimization. See your report for fine-tuning opportunities.`,
strong: `Excellent! Your pipeline health score is ${pct}%. Your sales machine is running well. Your report includes advanced tactics to maintain momentum.`
};
return messages[level];
}
});
// ============ PAGES SETUP ============
const pages = form.addPages('quiz-pages', { heightMode: 'current-page' });
// ============ PAGE 1: Pipeline Basics ============
const page1 = pages.addPage('basics', { mobileBreakpoint: 500 });
page1.addRow(row => {
row.addTextPanel('header1', {
label: 'Step 1 of 6: Pipeline Basics',
computedValue: () => 'Understanding your current sales pipeline',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page1.addSpacer({ height: '24px' });
page1.addRow(row => {
row.addDropdown('dealCycle', {
label: 'What\'s your average sales cycle length?',
isRequired: true,
options: [
{ id: 'under30', name: '⚡ Under 30 days' },
{ id: '30-60', name: '📅 30-60 days' },
{ id: '60-90', name: '📆 60-90 days' },
{ id: '90-180', name: '🗓️ 90-180 days' },
{ id: 'over180', name: '📋 Over 180 days' }
],
placeholder: 'Select cycle length'
}, '1fr');
row.addDropdown('teamSize', {
label: 'Sales team size',
isRequired: true,
options: [
{ id: 'solo', name: '👤 Just me' },
{ id: '2-5', name: '👥 2-5 reps' },
{ id: '6-15', name: '👥 6-15 reps' },
{ id: '16-50', name: '🏢 16-50 reps' },
{ id: 'over50', name: '🏛️ 50+ reps' }
],
placeholder: 'Select team size'
}, '1fr');
});
page1.addRow(row => {
row.addRadioButton('pipelineCoverage', {
label: 'What\'s your pipeline coverage ratio? (Pipeline value ÷ Quota)',
tooltip: 'Industry standard is 3x-4x coverage for healthy pipelines',
isRequired: true,
orientation: 'vertical',
options: [
{ id: '4x+', name: '🚀 4x+ coverage - strong position' },
{ id: '3-4x', name: '✅ 3-4x coverage - healthy' },
{ id: '2-3x', name: '⚠️ 2-3x coverage - needs attention' },
{ id: 'under2x', name: '🚨 Under 2x - critical gap' },
{ id: 'unknown', name: '❓ Not sure / Don\'t track' }
],
onValueChange: (val) => {
const points = { '4x+': 15, '3-4x': 12, '2-3x': 7, 'under2x': 3, unknown: 0 };
updateScore('coverage', points[val as keyof typeof points] || 0);
}
});
});
// ============ PAGE 2: Lead Generation ============
const page2 = pages.addPage('leads', { mobileBreakpoint: 500 });
page2.addRow(row => {
row.addTextPanel('header2', {
label: 'Step 2 of 6: Lead Generation',
computedValue: () => 'How you fill your pipeline',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page2.addSpacer({ height: '24px' });
page2.addRow(row => {
row.addSuggestionChips('leadSources', {
label: 'What are your main lead sources?',
isRequired: true,
suggestions: [
{ id: 'inbound', name: '📥 Inbound/Marketing' },
{ id: 'outbound', name: '📞 Outbound/Cold' },
{ id: 'referrals', name: '🤝 Referrals' },
{ id: 'partners', name: '🔗 Partners' },
{ id: 'events', name: '🎪 Events/Trade shows' },
{ id: 'social', name: '📱 Social selling' }
],
min: 1,
alignment: 'center',
onValueChange: (val) => {
if (!val) return;
// Multiple sources = healthier, but diminishing returns
const points = Math.min(val.length * 3, 12);
updateScore('sources', points);
}
});
});
page2.addRow(row => {
row.addRadioButton('leadFlow', {
label: 'How consistent is your lead flow?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'predictable', name: '📈 Predictable - steady flow each month' },
{ id: 'variable', name: '📊 Variable - good months and slow months' },
{ id: 'unpredictable', name: '🎲 Unpredictable - feast or famine' },
{ id: 'declining', name: '📉 Declining - fewer leads over time' }
],
onValueChange: (val) => {
const points = { predictable: 10, variable: 6, unpredictable: 3, declining: 0 };
updateScore('leadFlow', points[val as keyof typeof points] || 0);
}
});
});
page2.addRow(row => {
row.addTextPanel('leadScore', {
computedValue: () => {
const s = scores();
const score = (s['sources'] || 0) + (s['leadFlow'] || 0);
return `📥 Lead Generation Score: ${score}/22`;
},
customStyles: {
fontSize: '1rem', fontWeight: '600', color: '#1e40af',
textAlign: 'center', padding: '12px', background: '#dbeafe',
borderRadius: '8px', marginTop: '1rem'
}
});
});
// ============ PAGE 3: Pipeline Quality ============
const page3 = pages.addPage('quality', { mobileBreakpoint: 500 });
page3.addRow(row => {
row.addTextPanel('header3', {
label: 'Step 3 of 6: Pipeline Quality',
computedValue: () => 'The quality of deals in your pipeline',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page3.addSpacer({ height: '24px' });
page3.addRow(row => {
row.addSlider('winRate', {
label: 'What\'s your average win rate?',
tooltip: 'Percentage of qualified opportunities you close',
isRequired: true,
min: 5,
max: 60,
step: 5,
defaultValue: 25,
showValue: true,
unit: '%',
onValueChange: (val) => {
if (val == null) return;
let points = 0;
if (val >= 40) points = 12;
else if (val >= 30) points = 10;
else if (val >= 20) points = 7;
else if (val >= 15) points = 4;
else points = 2;
updateScore('winRate', points);
}
});
});
page3.addRow(row => {
row.addRadioButton('dealQuality', {
label: 'How well-qualified are deals entering your pipeline?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'rigorous', name: '🎯 Rigorous - clear criteria, verified budget & authority' },
{ id: 'moderate', name: '✅ Moderate - some qualification before entering' },
{ id: 'loose', name: '⚠️ Loose - most leads enter pipeline quickly' },
{ id: 'none', name: '❌ None - everything goes in the pipeline' }
],
onValueChange: (val) => {
const points = { rigorous: 10, moderate: 7, loose: 3, none: 0 };
updateScore('qualification', points[val as keyof typeof points] || 0);
}
});
});
page3.addRow(row => {
row.addRadioButton('staleDeals', {
label: 'How many deals in your pipeline are stale (no activity 30+ days)?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'under10', name: '✅ Under 10% - pipeline is fresh' },
{ id: '10-25', name: '⚠️ 10-25% - some cleanup needed' },
{ id: '25-50', name: '😰 25-50% - significant stale deals' },
{ id: 'over50', name: '🚨 Over 50% - pipeline is clogged' }
],
onValueChange: (val) => {
const points = { 'under10': 8, '10-25': 5, '25-50': 2, 'over50': 0 };
updateScore('stale', points[val as keyof typeof points] || 0);
}
});
});
// ============ PAGE 4: Process & Tracking ============
const page4 = pages.addPage('process', { mobileBreakpoint: 500 });
page4.addRow(row => {
row.addTextPanel('header4', {
label: 'Step 4 of 6: Process & Tracking',
computedValue: () => 'How you manage your pipeline',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page4.addSpacer({ height: '24px' });
page4.addRow(row => {
row.addRadioButton('crm', {
label: 'How do you track your pipeline?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'crm-full', name: '💻 CRM with full adoption and data hygiene' },
{ id: 'crm-partial', name: '📊 CRM but inconsistent updates' },
{ id: 'spreadsheet', name: '📋 Spreadsheets / manual tracking' },
{ id: 'none', name: '🧠 In my head / minimal tracking' }
],
onValueChange: (val) => {
const points = { 'crm-full': 10, 'crm-partial': 6, spreadsheet: 3, none: 0 };
updateScore('crm', points[val as keyof typeof points] || 0);
}
});
});
page4.addRow(row => {
row.addRadioButton('stages', {
label: 'Do you have clearly defined pipeline stages with exit criteria?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'defined', name: '✅ Yes - documented stages with clear criteria' },
{ id: 'informal', name: '⚠️ Informal - stages exist but not standardized' },
{ id: 'none', name: '❌ No - no defined stages' }
],
onValueChange: (val) => {
const points = { defined: 8, informal: 4, none: 0 };
updateScore('stages', points[val as keyof typeof points] || 0);
}
});
});
page4.addRow(row => {
row.addRadioButton('reviews', {
label: 'How often do you review pipeline with your team/manager?',
isRequired: true,
orientation: 'vertical',
options: [
{ id: 'weekly', name: '📅 Weekly pipeline reviews' },
{ id: 'biweekly', name: '📆 Every 2 weeks' },
{ id: 'monthly', name: '🗓️ Monthly' },
{ id: 'rarely', name: '❌ Rarely or never' }
],
onValueChange: (val) => {
const points = { weekly: 7, biweekly: 5, monthly: 3, rarely: 0 };
updateScore('reviews', points[val as keyof typeof points] || 0);
}
});
});
// ============ PAGE 5: Results ============
const page5 = pages.addPage('results', { mobileBreakpoint: 500 });
page5.addRow(row => {
row.addTextPanel('header5', {
label: 'Step 5 of 6: Your Results',
computedValue: () => 'Your sales pipeline health assessment',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page5.addSpacer({ height: '24px' });
page5.addRow(row => {
row.addTextPanel('bigResult', {
computedValue: () => getHealthLabel(),
customStyles: {
fontSize: '1.5rem', fontWeight: '800', textAlign: 'center',
color: getHealthColor(), padding: '20px', background: '#f9fafb',
borderRadius: '12px', border: `3px solid ${getHealthColor()}`
}
});
});
page5.addRow(row => {
row.addTextPanel('scoreDisplay', {
computedValue: () => `Pipeline Health Score: ${getTotalScore()}/${getMaxScore()} (${getScorePercentage()}%)`,
customStyles: {
fontSize: '1.1rem', fontWeight: '600', textAlign: 'center',
color: '#374151', marginTop: '10px'
}
});
});
page5.addRow(row => {
row.addTextPanel('recommendation', {
computedValue: () => {
const level = getHealthLevel();
const recommendations = {
critical: '🔴 Focus on pipeline coverage first - you need more qualified opportunities. Implement lead qualification criteria immediately.',
weak: '🟡 Prioritize cleaning stale deals and improving qualification. Consider adding new lead sources.',
healthy: '🟢 Fine-tune your process - focus on improving win rates and reducing cycle time.',
strong: '💪 Maintain your discipline. Focus on scaling what works and coaching others.'
};
return recommendations[level];
},
customStyles: {
fontSize: '0.95rem', color: '#4b5563', textAlign: 'center',
padding: '15px', background: '#f3f4f6', borderRadius: '8px',
marginTop: '15px', lineHeight: '1.5'
}
});
});
const detailsSection = page5.addSubform('detailsBreakdown', {
title: '📊 Score Breakdown (click to expand)',
isCollapsible: true,
customStyles: { marginTop: '1rem', background: '#f9fafb', borderRadius: '8px' }
});
detailsSection.addRow(row => {
row.addTextPanel('coverageDetail', {
label: '📈 Pipeline Coverage',
computedValue: () => `${scores()['coverage'] || 0}/15`,
customStyles: { fontSize: '0.9rem', padding: '8px 12px', background: '#dbeafe', borderRadius: '6px' }
}, '1fr');
row.addTextPanel('leadsDetail', {
label: '📥 Lead Generation',
computedValue: () => {
const s = scores();
return `${(s['sources'] || 0) + (s['leadFlow'] || 0)}/22`;
},
customStyles: { fontSize: '0.9rem', padding: '8px 12px', background: '#dbeafe', borderRadius: '6px' }
}, '1fr');
});
detailsSection.addRow(row => {
row.addTextPanel('qualityDetail', {
label: '🎯 Pipeline Quality',
computedValue: () => {
const s = scores();
return `${(s['winRate'] || 0) + (s['qualification'] || 0) + (s['stale'] || 0)}/30`;
},
customStyles: { fontSize: '0.9rem', padding: '8px 12px', background: '#dbeafe', borderRadius: '6px' }
}, '1fr');
row.addTextPanel('processDetail', {
label: '⚙️ Process & Tracking',
computedValue: () => {
const s = scores();
return `${(s['crm'] || 0) + (s['stages'] || 0) + (s['reviews'] || 0)}/25`;
},
customStyles: { fontSize: '0.9rem', padding: '8px 12px', background: '#dbeafe', borderRadius: '6px' }
}, '1fr');
});
// ============ PAGE 6: Lead Capture ============
const page6 = pages.addPage('lead-capture', { mobileBreakpoint: 500 });
page6.addRow(row => {
row.addTextPanel('header6', {
label: 'Step 6 of 6: Get Your Report',
computedValue: () => 'Receive your personalized pipeline optimization plan',
customStyles: { fontSize: '0.9rem', color: '#6b7280', marginBottom: '1rem' }
});
});
page6.addSpacer({ height: '24px' });
page6.addRow(row => {
row.addTextbox('name', { label: 'Your Name', isRequired: true, placeholder: 'John Smith' }, '1fr');
row.addEmail('email', { label: 'Work Email', isRequired: true, placeholder: 'john@company.com' }, '1fr');
});
page6.addRow(row => {
row.addTextbox('company', { label: 'Company', placeholder: 'Acme Corp' }, '1fr');
row.addDropdown('role', {
label: 'Your Role',
options: [
{ id: 'rep', name: '💼 Sales Rep / AE' },
{ id: 'manager', name: '👔 Sales Manager' },
{ id: 'director', name: '📊 Director / VP Sales' },
{ id: 'founder', name: '🚀 Founder / CEO' },
{ id: 'other', name: '📦 Other' }
],
placeholder: 'Select role'
}, '1fr');
});
page6.addRow(row => {
row.addCheckboxList('consent', {
options: [
{ id: 'report', name: '📄 Send me my pipeline health report', isRequired: true },
{ id: 'tips', name: '💡 Send me sales pipeline tips' },
{ id: 'demo', name: '📞 I\'d like a pipeline review consultation' }
],
defaultValue: ['report'],
orientation: 'vertical'
});
});
// ============ PDF REPORT ============
form.configurePdf('pipeline-report', pdf => {
pdf.configure({
filename: 'sales-pipeline-health-report.pdf',
pageSize: 'A4',
allowUserDownload: true,
downloadButtonLabel: '📄 Download Pipeline Report',
header: { title: 'Sales Pipeline Health Report', subtitle: 'Your Personalized Assessment' },
footer: { text: 'Generated by FormTs Pipeline Health Quiz', showPageNumbers: true }
});
pdf.addSection('Executive Summary', section => {
section.addRow(row => {
row.addField('Pipeline Health', getHealthLabel());
row.addField('Overall Score', `${getScorePercentage()}%`);
});
});
pdf.addSection('Score Breakdown', section => {
const s = scores();
section.addTable(
['Category', 'Score', 'Max', 'Status'],
[
['Pipeline Coverage', `${s['coverage'] || 0}`, '15', (s['coverage'] || 0) >= 12 ? '✅ Good' : '⚠️ Improve'],
['Lead Generation', `${(s['sources'] || 0) + (s['leadFlow'] || 0)}`, '22', (s['sources'] || 0) + (s['leadFlow'] || 0) >= 16 ? '✅ Good' : '⚠️ Improve'],
['Pipeline Quality', `${(s['winRate'] || 0) + (s['qualification'] || 0) + (s['stale'] || 0)}`, '30', (s['winRate'] || 0) + (s['qualification'] || 0) + (s['stale'] || 0) >= 22 ? '✅ Good' : '⚠️ Improve'],
['Process & Tracking', `${(s['crm'] || 0) + (s['stages'] || 0) + (s['reviews'] || 0)}`, '25', (s['crm'] || 0) + (s['stages'] || 0) + (s['reviews'] || 0) >= 18 ? '✅ Good' : '⚠️ Improve']
]
);
});
pdf.addPageBreak();
pdf.addSection('Recommendations', section => {
const s = scores();
if ((s['coverage'] || 0) < 12) {
section.addText('• Pipeline Coverage: Aim for 3-4x coverage. Focus on adding more qualified opportunities.');
}
if ((s['sources'] || 0) + (s['leadFlow'] || 0) < 16) {
section.addText('• Lead Generation: Diversify lead sources. Don\'t rely on a single channel.');
}
if ((s['winRate'] || 0) < 10) {
section.addText('• Win Rate: Improve qualification to focus on winnable deals.');
}
if ((s['stale'] || 0) < 5) {
section.addText('• Stale Deals: Clean your pipeline regularly. Remove or re-engage stuck deals.');
}
if ((s['crm'] || 0) < 8) {
section.addText('• CRM Hygiene: Consistent data entry is critical for forecasting.');
}
});
});
form.configureSubmitButton({
label: () => `📊 Get My Report (Score: ${getScorePercentage()}%)`
});
form.configureSubmitBehavior({ sendToServer: true });
}