export function implementationFeedback(form: FormTs) {
// Implementation Review Survey - B2B project implementation feedback
// Demonstrates: Multi-page, MatrixQuestion, StarRating, RatingScale (NPS), Slider, conditional sections, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Implementation Feedback',
computedValue: () => 'Help us improve our implementation process by sharing your experience.',
customStyles: {
backgroundColor: '#0f766e',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('implementationPages', {
heightMode: 'current-page'
});
// ============================================
// PAGE 1: Project Overview
// ============================================
const overviewPage = pages.addPage('overview');
const overviewSection = overviewPage.addSubform('overviewSection', {
title: 'Project Overview'
});
overviewSection.addRow(row => {
row.addTextbox('projectName', {
label: 'Project Name',
placeholder: 'e.g., CRM Implementation Q4 2024',
isRequired: true
}, '2fr');
row.addDropdown('projectType', {
label: 'Project Type',
options: [
{ id: 'new', name: 'New Implementation' },
{ id: 'upgrade', name: 'System Upgrade' },
{ id: 'migration', name: 'Data Migration' },
{ id: 'integration', name: 'Integration Project' },
{ id: 'customization', name: 'Customization' }
],
placeholder: 'Select type',
isRequired: true
}, '1fr');
});
overviewSection.addRow(row => {
row.addDropdown('companySize', {
label: 'Your Organization Size',
options: [
{ id: 'small', name: '1-50 employees' },
{ id: 'medium', name: '51-200 employees' },
{ id: 'large', name: '201-1000 employees' },
{ id: 'enterprise', name: '1000+ employees' }
],
placeholder: 'Select size'
}, '1fr');
row.addDropdown('role', {
label: 'Your Role in the Project',
options: [
{ id: 'sponsor', name: 'Executive Sponsor' },
{ id: 'pm', name: 'Project Manager' },
{ id: 'lead', name: 'Project Lead' },
{ id: 'user', name: 'End User' },
{ id: 'it', name: 'IT/Technical' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select role',
isRequired: true
}, '1fr');
});
overviewSection.addRow(row => {
row.addEmojiRating('overallImpression', {
label: 'How would you rate the overall implementation experience?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
overviewSection.addRow(row => {
row.addButton('nextToPhases', {
label: 'Continue to Phase Ratings',
onClick: () => pages.goToPage('phases'),
isDisabled: () => {
const name = overviewSection.textbox('projectName')?.value();
const type = overviewSection.dropdown('projectType')?.value();
return !name || !type;
}
});
});
// ============================================
// PAGE 2: Phase Ratings
// ============================================
const phasesPage = pages.addPage('phases');
const phasesSection = phasesPage.addSubform('phasesSection', {
title: 'Implementation Phases'
});
phasesSection.addRow(row => {
row.addTextPanel('phasesIntro', {
computedValue: () => 'Rate your satisfaction with each phase of the implementation.',
customStyles: {
fontSize: '14px',
color: '#475569',
marginBottom: '16px'
}
});
});
phasesSection.addRow(row => {
row.addMatrixQuestion('phaseRatings', {
label: 'How satisfied were you with each implementation phase?',
rows: [
{ id: 'kickoff', label: 'Kickoff & Planning', description: 'Initial meetings, scope definition', isRequired: true },
{ id: 'discovery', label: 'Discovery & Requirements', description: 'Understanding your needs', isRequired: true },
{ id: 'config', label: 'Configuration & Setup', description: 'System configuration and customization', isRequired: true },
{ id: 'data', label: 'Data Migration', description: 'Moving your data to the new system', isRequired: false },
{ id: 'testing', label: 'Testing & UAT', description: 'User acceptance testing', isRequired: true },
{ id: 'training', label: 'Training & Documentation', description: 'Learning how to use the system', isRequired: true },
{ id: 'golive', label: 'Go-Live', description: 'Launch day experience', isRequired: true },
{ id: 'hypercare', label: 'Post-Launch Support', description: 'Support after go-live', isRequired: false }
],
columns: [
{ id: '1', label: 'Very Poor' },
{ id: '2', label: 'Poor' },
{ id: '3', label: 'Average' },
{ id: '4', label: 'Good' },
{ id: '5', label: 'Excellent' },
{ id: 'na', label: 'N/A' }
],
striped: true,
fullWidth: true
});
});
// Weakest phase follow-up
const weakPhaseSection = phasesSection.addSubform('weakPhase', {
title: 'Area for Improvement',
isVisible: () => phasesSection.matrixQuestion('phaseRatings')?.areAllRequiredRowsAnswered() ?? false,
customStyles: { marginTop: '20px' }
});
weakPhaseSection.addRow(row => {
row.addRadioButton('weakestPhase', {
label: 'Which phase needs the most improvement?',
options: [
{ id: 'kickoff', name: 'Kickoff & Planning' },
{ id: 'discovery', name: 'Discovery & Requirements' },
{ id: 'config', name: 'Configuration & Setup' },
{ id: 'data', name: 'Data Migration' },
{ id: 'testing', name: 'Testing & UAT' },
{ id: 'training', name: 'Training & Documentation' },
{ id: 'golive', name: 'Go-Live' },
{ id: 'hypercare', name: 'Post-Launch Support' },
{ id: 'none', name: 'All phases were satisfactory' }
],
orientation: 'vertical'
});
});
weakPhaseSection.addSpacer();
weakPhaseSection.addRow(row => {
row.addTextarea('phaseImprovements', {
label: () => {
const phase = weakPhaseSection.radioButton('weakestPhase')?.value();
const phaseLabels: Record<string, string> = {
'kickoff': 'Kickoff & Planning',
'discovery': 'Discovery & Requirements',
'config': 'Configuration & Setup',
'data': 'Data Migration',
'testing': 'Testing & UAT',
'training': 'Training & Documentation',
'golive': 'Go-Live',
'hypercare': 'Post-Launch Support'
};
if (phase && phase !== 'none') {
return `How could the ${phaseLabels[phase]} phase be improved?`;
}
return 'Any suggestions for improvement?';
},
placeholder: 'Share specific suggestions...',
rows: 3,
autoExpand: true,
isVisible: () => weakPhaseSection.radioButton('weakestPhase')?.value() !== null
});
});
phasesSection.addSpacer();
phasesSection.addRow(row => {
row.addButton('backToOverview', {
label: 'Back',
onClick: () => pages.goToPage('overview')
});
row.addButton('nextToSupport', {
label: 'Continue to Support & Communication',
onClick: () => pages.goToPage('support'),
isDisabled: () => !(phasesSection.matrixQuestion('phaseRatings')?.areAllRequiredRowsAnswered() ?? false)
});
});
// ============================================
// PAGE 3: Support & Communication
// ============================================
const supportPage = pages.addPage('support');
const supportSection = supportPage.addSubform('supportSection', {
title: 'Support & Communication'
});
supportSection.addRow(row => {
row.addStarRating('overallSupport', {
label: 'Overall support quality during implementation',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
supportSection.addRow(row => {
row.addStarRating('responsiveness', {
label: 'Response Time',
tooltip: 'How quickly did the team respond to your questions?',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
row.addStarRating('expertise', {
label: 'Technical Expertise',
tooltip: 'Knowledge and skills of the implementation team',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
});
supportSection.addRow(row => {
row.addStarRating('communication', {
label: 'Communication Quality',
tooltip: 'Clarity and frequency of project updates',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
row.addStarRating('proactivity', {
label: 'Proactive Problem Solving',
tooltip: 'Identifying and addressing issues before they became problems',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
});
// Implementation team rating
const teamSection = supportPage.addSubform('teamSection', {
title: 'Implementation Team',
isVisible: () => supportSection.starRating('overallSupport')?.value() !== null
});
teamSection.addRow(row => {
row.addTextbox('projectManager', {
label: 'Your Project Manager Name (optional)',
placeholder: 'e.g., John Smith'
}, '1fr');
row.addStarRating('pmRating', {
label: 'PM Performance',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
});
teamSection.addRow(row => {
row.addRadioButton('teamSize', {
label: 'Was the implementation team size appropriate?',
options: [
{ id: 'too-small', name: 'Understaffed - needed more resources' },
{ id: 'right', name: 'Right size for the project' },
{ id: 'too-large', name: 'Overstaffed - too many people involved' }
],
orientation: 'horizontal'
});
});
supportPage.addRow(row => {
row.addButton('backToPhases', {
label: 'Back',
onClick: () => pages.goToPage('phases')
});
row.addButton('nextToOutcomes', {
label: 'Continue to Outcomes',
onClick: () => pages.goToPage('outcomes'),
isDisabled: () => supportSection.starRating('overallSupport')?.value() === null
});
});
// ============================================
// PAGE 4: Outcomes & Value
// ============================================
const outcomesPage = pages.addPage('outcomes');
const outcomesSection = outcomesPage.addSubform('outcomesSection', {
title: 'Project Outcomes'
});
outcomesSection.addRow(row => {
row.addThumbRating('metGoals', {
label: 'Did the project meet your business objectives?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'center',
size: 'lg'
}, '1fr');
row.addThumbRating('onTime', {
label: 'Was the project delivered on time?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'center',
size: 'lg'
}, '1fr');
row.addThumbRating('onBudget', {
label: 'Was the project within budget?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'center',
size: 'lg'
}, '1fr');
});
outcomesSection.addRow(row => {
row.addSlider('userAdoption', {
label: 'Current user adoption level',
min: 0,
max: 100,
step: 5,
defaultValue: 50,
showValue: true,
unit: '%'
}, '1fr');
row.addSlider('businessValue', {
label: 'Business value realized so far',
min: 0,
max: 100,
step: 5,
defaultValue: 50,
showValue: true,
unit: '%'
}, '1fr');
});
// Timeline section
const timelineSection = outcomesPage.addSubform('timelineSection', {
title: 'Timeline Assessment'
});
timelineSection.addRow(row => {
row.addRadioButton('timelineDeviation', {
label: 'How did the actual timeline compare to the original plan?',
options: [
{ id: 'early', name: 'Finished early' },
{ id: 'on-time', name: 'On schedule' },
{ id: 'slight-delay', name: 'Slightly delayed (< 2 weeks)' },
{ id: 'moderate-delay', name: 'Moderate delay (2-4 weeks)' },
{ id: 'significant-delay', name: 'Significant delay (> 1 month)' }
],
orientation: 'vertical'
});
});
timelineSection.addRow(row => {
row.addTextarea('delayReasons', {
label: 'What caused the delay?',
placeholder: 'Describe the main factors...',
rows: 2,
autoExpand: true,
isVisible: () => {
const val = timelineSection.radioButton('timelineDeviation')?.value();
return val === 'slight-delay' || val === 'moderate-delay' || val === 'significant-delay';
}
});
});
// NPS Section
const npsSection = outcomesPage.addSubform('npsSection', {
title: 'Recommendation'
});
npsSection.addRow(row => {
row.addRatingScale('npsScore', {
preset: 'nps',
label: 'How likely are you to recommend our implementation services to others?',
showSegmentColors: true,
showCategoryLabel: true,
showConfettiOnPromoter: true,
alignment: 'center'
});
});
npsSection.addRow(row => {
row.addTextarea('npsReason', {
label: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return 'What made the implementation experience great?';
if (category === 'detractor') return 'What would need to change for you to recommend us?';
return 'What could we do to improve?';
},
placeholder: 'Share your thoughts...',
rows: 3,
autoExpand: true,
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
});
outcomesPage.addRow(row => {
row.addButton('backToSupport', {
label: 'Back',
onClick: () => pages.goToPage('support')
});
row.addButton('nextToSummary', {
label: 'Continue to Summary',
onClick: () => pages.goToPage('summary'),
isDisabled: () => npsSection.ratingScale('npsScore')?.value() === null
});
});
// ============================================
// PAGE 5: Summary
// ============================================
const summaryPage = pages.addPage('summary');
const summarySection = summaryPage.addSubform('summarySection', {
title: 'Your Feedback Summary'
});
summarySection.addRow(row => {
row.addTextPanel('summaryDisplay', {
computedValue: () => {
const impression = overviewSection.emojiRating('overallImpression')?.value();
const support = supportSection.starRating('overallSupport')?.value();
const nps = npsSection.ratingScale('npsScore')?.value();
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
const metGoals = outcomesSection.thumbRating('metGoals')?.value();
const onTime = outcomesSection.thumbRating('onTime')?.value();
const adoption = outcomesSection.slider('userAdoption')?.value();
const impressionLabels: Record<string, string> = {
'very-bad': 'Very Dissatisfied',
'bad': 'Dissatisfied',
'neutral': 'Neutral',
'good': 'Satisfied',
'excellent': 'Very Satisfied'
};
let emoji = '📋';
if (impression === 'excellent') emoji = '🎉';
else if (impression === 'good') emoji = '😊';
else if (impression === 'neutral') emoji = '😐';
else if (impression === 'bad' || impression === 'very-bad') emoji = '😟';
let summary = `${emoji} IMPLEMENTATION FEEDBACK\n`;
summary += '═'.repeat(30) + '\n\n';
summary += `Overall: ${impressionLabels[impression || ''] || 'Not rated'}\n`;
if (support) {
summary += `Support: ${'★'.repeat(support)}${'☆'.repeat(5 - support)} (${support}/5)\n`;
}
summary += '\n📊 Outcomes:\n';
summary += ` Goals Met: ${metGoals === 'up' ? '✅' : metGoals === 'down' ? '❌' : '—'}\n`;
summary += ` On Time: ${onTime === 'up' ? '✅' : onTime === 'down' ? '❌' : '—'}\n`;
if (adoption !== null && adoption !== undefined) {
summary += ` Adoption: ${adoption}%\n`;
}
if (nps !== null && nps !== undefined && npsCategory) {
const catLabels: Record<string, string> = {
'promoter': 'Promoter',
'passive': 'Passive',
'detractor': 'Detractor'
};
summary += `\n📈 NPS: ${nps}/10 (${catLabels[npsCategory]})`;
}
return summary;
},
customStyles: () => {
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
const baseStyles = {
padding: '20px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
};
if (npsCategory === 'promoter') {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
}
if (npsCategory === 'passive') {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
if (npsCategory === 'detractor') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#f1f5f9', borderLeft: '4px solid #64748b' };
}
});
});
// Final feedback
const finalSection = summaryPage.addSubform('finalSection', {
title: 'Final Thoughts'
});
finalSection.addRow(row => {
row.addTextarea('additionalFeedback', {
label: 'Anything else you would like to share?',
placeholder: 'Share any additional thoughts, concerns, or praise...',
rows: 4,
autoExpand: true
});
});
finalSection.addRow(row => {
row.addCheckbox('canContact', {
label: 'You may contact me to discuss my feedback further'
});
});
finalSection.addRow(row => {
row.addEmail('contactEmail', {
label: 'Your email',
placeholder: 'email@company.com',
isVisible: () => finalSection.checkbox('canContact')?.value() === true,
isRequired: () => finalSection.checkbox('canContact')?.value() === true
});
});
summaryPage.addRow(row => {
row.addButton('backToOutcomes', {
label: 'Back',
onClick: () => pages.goToPage('outcomes')
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Implementation Feedback',
isVisible: () => pages.currentPageIndex() === 4
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your detailed insights help us continuously improve our implementation methodology and deliver better outcomes for all clients. We truly appreciate you taking the time to share your experience.'
});
}