export function jobsToBeDoneForm(form: FormTs) {
// Jobs To Be Done Interview Form - Customer Motivation Research
// Demonstrates: Pages, Textarea (scenario-based), RadioButton, RatingScale, SuggestionChips
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Understanding Your Decision',
computedValue: () => "Help us understand your journey to choosing our product. There are no right or wrong answers - we're interested in your story.",
customStyles: {
backgroundColor: '#8b5cf6',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('jtbdPages', {
heightMode: 'tallest-page'
});
// ============================================
// PAGE 1: The Trigger
// ============================================
const page1 = pages.addPage('trigger');
const triggerSection = page1.addSubform('triggerSection', {
title: 'The First Thought'
});
triggerSection.addRow(row => {
row.addTextPanel('triggerIntro', {
computedValue: () => "Let's go back to when you first thought about looking for a solution like ours.",
customStyles: {
fontStyle: 'italic',
color: '#6b7280',
marginBottom: '12px'
}
});
});
triggerSection.addRow(row => {
row.addTextarea('firstThought', {
label: 'Think back to when you first realized you needed a solution. What was happening in your life or work that triggered this thought?',
placeholder: 'Describe the situation, moment, or event that made you think "I need to do something about this"...',
rows: 4,
autoExpand: true,
isRequired: true
});
});
triggerSection.addRow(row => {
row.addRadioButton('triggerType', {
label: 'What best describes what triggered your search?',
options: [
{ id: 'pain', name: 'A specific pain or frustration I wanted to eliminate' },
{ id: 'opportunity', name: 'An opportunity I wanted to capture' },
{ id: 'change', name: 'A change in my situation (new role, growth, etc.)' },
{ id: 'recommendation', name: 'Someone recommended I look into this' },
{ id: 'curiosity', name: 'Curiosity about what was possible' }
],
orientation: 'vertical'
});
});
// ============================================
// PAGE 2: The Old Way
// ============================================
const page2 = pages.addPage('oldWay');
const oldWaySection = page2.addSubform('oldWaySection', {
title: 'Before Our Product'
});
oldWaySection.addRow(row => {
row.addTextarea('previousSolution', {
label: 'Before using our product, how were you solving this problem or getting this job done?',
placeholder: 'Describe your previous solution - could be another product, a manual process, or just living with the problem...',
rows: 4,
autoExpand: true
});
});
oldWaySection.addRow(row => {
row.addCheckboxList('oldWayProblems', {
label: 'What frustrated you most about your old way of doing things?',
options: [
{ id: 'time', name: 'Took too much time' },
{ id: 'effort', name: 'Required too much effort' },
{ id: 'cost', name: 'Too expensive' },
{ id: 'quality', name: 'Results weren\'t good enough' },
{ id: 'reliable', name: 'Unreliable or inconsistent' },
{ id: 'scale', name: 'Couldn\'t scale or grow' },
{ id: 'complex', name: 'Too complicated' },
{ id: 'integration', name: 'Didn\'t work with other tools' }
],
orientation: 'vertical'
});
});
oldWaySection.addSpacer();
oldWaySection.addRow(row => {
row.addRatingScale('oldWaySatisfaction', {
label: 'How satisfied were you with your old solution?',
preset: 'likert-5',
lowLabel: 'Very dissatisfied',
highLabel: 'Very satisfied',
alignment: 'center'
});
});
// ============================================
// PAGE 3: The Search
// ============================================
const page3 = pages.addPage('search');
const searchSection = page3.addSubform('searchSection', {
title: 'Looking for Alternatives'
});
searchSection.addRow(row => {
row.addTextarea('alternativesConsidered', {
label: 'What other solutions did you consider before choosing us? Why did you rule them out?',
placeholder: 'List competitors, alternatives, or approaches you evaluated...',
rows: 4,
autoExpand: true
});
});
searchSection.addRow(row => {
row.addCheckboxList('evaluationCriteria', {
label: 'What criteria were most important in your evaluation?',
options: [
{ id: 'price', name: 'Price / Value for money' },
{ id: 'features', name: 'Specific features' },
{ id: 'ease', name: 'Ease of use' },
{ id: 'speed', name: 'Speed of results' },
{ id: 'support', name: 'Customer support' },
{ id: 'reputation', name: 'Company reputation' },
{ id: 'reviews', name: 'Reviews and testimonials' },
{ id: 'integration', name: 'Integration with existing tools' },
{ id: 'security', name: 'Security and compliance' }
],
orientation: 'vertical'
});
});
searchSection.addSpacer();
searchSection.addRow(row => {
row.addSlider('searchDuration', {
label: 'Roughly how long did you spend evaluating options? (in weeks)',
min: 0,
max: 24,
step: 1,
showValue: true,
unit: 'weeks',
defaultValue: 4
});
});
// ============================================
// PAGE 4: Push & Pull Forces
// ============================================
const page4 = pages.addPage('forces');
const pushSection = page4.addSubform('pushSection', {
title: 'What Pushed You Away',
customStyles: {
backgroundColor: '#fef3c7',
padding: '16px',
borderRadius: '8px'
}
});
pushSection.addRow(row => {
row.addTextarea('pushForces', {
label: 'What finally pushed you to make a change? Was there a "last straw" moment?',
placeholder: 'Describe what made the status quo no longer acceptable...',
rows: 3,
autoExpand: true
});
});
const pullSection = page4.addSubform('pullSection', {
title: 'What Pulled You Toward Us',
customStyles: {
backgroundColor: '#d1fae5',
padding: '16px',
borderRadius: '8px'
}
});
pullSection.addRow(row => {
row.addTextarea('pullForces', {
label: 'What was most attractive about our solution? What made you think "this could work"?',
placeholder: 'Describe what drew you to our product specifically...',
rows: 3,
autoExpand: true
});
});
pullSection.addRow(row => {
row.addSuggestionChips('keyAttractors', {
label: 'Which aspects pulled you the most? (Select up to 3)',
suggestions: [
{ id: 'simplicity', name: 'Simplicity' },
{ id: 'power', name: 'Powerful features' },
{ id: 'price', name: 'Pricing' },
{ id: 'design', name: 'Design/UX' },
{ id: 'speed', name: 'Speed' },
{ id: 'support', name: 'Support' },
{ id: 'reputation', name: 'Reputation' },
{ id: 'recommendation', name: 'Recommendation' }
],
max: 3,
alignment: 'left'
});
});
// ============================================
// PAGE 5: Anxieties & Habits
// ============================================
const page5 = pages.addPage('anxieties');
const anxietySection = page5.addSubform('anxietySection', {
title: 'Hesitations'
});
anxietySection.addRow(row => {
row.addTextarea('anxieties', {
label: 'What concerns or hesitations did you have before deciding? What almost stopped you?',
placeholder: 'Describe any worries, doubts, or risks you were thinking about...',
rows: 3,
autoExpand: true
});
});
anxietySection.addRow(row => {
row.addCheckboxList('anxietyTypes', {
label: 'What types of concerns did you have?',
options: [
{ id: 'learn', name: 'Learning curve / time to learn' },
{ id: 'switch', name: 'Switching costs / migration effort' },
{ id: 'work', name: 'Will it actually work for my use case?' },
{ id: 'price', name: 'Is the price worth it?' },
{ id: 'lock', name: 'Getting locked in' },
{ id: 'support', name: 'Will I get help when I need it?' },
{ id: 'team', name: 'Will my team adopt it?' },
{ id: 'stability', name: 'Will the company be around?' }
],
orientation: 'vertical'
});
});
anxietySection.addSpacer();
anxietySection.addRow(row => {
row.addTextarea('whatConvinced', {
label: 'What ultimately convinced you to move forward despite these concerns?',
placeholder: 'What tipped the balance? A trial, a review, a conversation?',
rows: 3,
autoExpand: true
});
});
// ============================================
// PAGE 6: The Job & Outcome
// ============================================
const page6 = pages.addPage('outcome');
const jobSection = page6.addSubform('jobSection', {
title: 'The Job You Hired Us For'
});
jobSection.addRow(row => {
row.addTextarea('jobToBeDone', {
label: 'Complete this sentence: "I hired [our product] to help me ___________"',
placeholder: 'Describe the job, outcome, or progress you wanted to make...',
rows: 3,
autoExpand: true,
isRequired: true
});
});
jobSection.addRow(row => {
row.addRadioButton('jobType', {
label: 'What type of "job" is this primarily?',
options: [
{ id: 'functional', name: 'Functional - Get a specific task done' },
{ id: 'emotional', name: 'Emotional - Feel a certain way (confident, in control, etc.)' },
{ id: 'social', name: 'Social - Be perceived in a certain way by others' }
],
orientation: 'vertical'
});
});
const outcomeSection = page6.addSubform('outcomeSection', {
title: 'Results So Far'
});
outcomeSection.addRow(row => {
row.addStarRating('outcomeRating', {
label: 'How well is our product doing the job you hired it for?',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
outcomeSection.addRow(row => {
row.addTextarea('surprises', {
label: 'Has anything surprised you (positively or negatively) since you started using us?',
placeholder: 'Any unexpected benefits or disappointments?',
rows: 3,
autoExpand: true
});
});
// ============================================
// SUMMARY (Outside pages)
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'JTBD Interview Summary',
isVisible: () => {
const job = jobSection.textarea('jobToBeDone')?.value();
return job !== null && job !== '';
}
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const triggerType = triggerSection.radioButton('triggerType')?.value();
const oldSatisfaction = oldWaySection.ratingScale('oldWaySatisfaction')?.value();
const searchWeeks = searchSection.slider('searchDuration')?.value();
const jobType = jobSection.radioButton('jobType')?.value();
const outcome = outcomeSection.starRating('outcomeRating')?.value();
const attractors = pullSection.suggestionChips('keyAttractors')?.value() || [];
const triggerLabels: Record<string, string> = {
'pain': 'Pain/Frustration',
'opportunity': 'Opportunity',
'change': 'Situation Change',
'recommendation': 'Recommendation',
'curiosity': 'Curiosity'
};
const jobTypeLabels: Record<string, string> = {
'functional': 'Functional',
'emotional': 'Emotional',
'social': 'Social'
};
let summary = `🎯 JTBD Interview Insights\n`;
summary += `${'═'.repeat(28)}\n\n`;
if (triggerType) summary += `⚡ Trigger: ${triggerLabels[triggerType] || triggerType}\n`;
if (oldSatisfaction) summary += `😐 Old Solution: ${oldSatisfaction}/5 satisfaction\n`;
if (searchWeeks) summary += `🔍 Search Duration: ${searchWeeks} weeks\n`;
if (attractors.length > 0) summary += `🧲 Key Attractors: ${attractors.join(', ')}\n`;
if (jobType) summary += `📋 Job Type: ${jobTypeLabels[jobType] || jobType}\n`;
if (outcome) summary += `⭐ Outcome Rating: ${outcome}/5 stars`;
return summary;
},
customStyles: {
padding: '16px',
borderRadius: '8px',
backgroundColor: '#f5f3ff',
borderLeft: '4px solid #8b5cf6',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Complete Interview'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Story!',
message: 'Your insights help us build products that truly serve the jobs you need done. We read every response carefully to improve our understanding of customer needs.'
});
}