export function donorFeedbackSurvey(form: FormTs) {
// Donor Satisfaction Survey - Non-Profit Feedback Form
// Demonstrates: NPS, StarRating, MatrixQuestion, EmojiRating, SuggestionChips, conditional visibility, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Your Voice Matters to Our Mission',
computedValue: () => 'Thank you for being a valued supporter. Your feedback helps us serve our community better.',
customStyles: {
background: 'linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Donor Loyalty (NPS)
// ============================================
const npsSection = form.addSubform('npsSection', {
title: 'Donor Loyalty',
customStyles: () => {
const category = npsSection.ratingScale('donorNps')?.npsCategory();
if (category === 'promoter') return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (category === 'passive') return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
if (category === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #d4d4d8' };
}
});
npsSection.addRow(row => {
row.addRatingScale('donorNps', {
preset: 'nps',
label: 'How likely are you to recommend supporting our organization to friends and family?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
npsSection.addSpacer({ height: '16px' });
npsSection.addRow(row => {
row.addTextarea('npsReason', {
label: () => {
const category = npsSection.ratingScale('donorNps')?.npsCategory();
switch (category) {
case 'promoter': return "We're so grateful for your enthusiasm! What inspires you most about our work?";
case 'passive': return 'Thank you! What would make you feel more connected to our mission?';
case 'detractor': return "We're sorry to hear that. What could we do better to earn your trust?";
default: return 'Tell us more about your experience with our organization';
}
},
placeholder: () => {
const category = npsSection.ratingScale('donorNps')?.npsCategory();
if (category === 'promoter') return 'Share what makes our mission meaningful to you...';
if (category === 'passive') return 'Your suggestions help us grow stronger...';
if (category === 'detractor') return "We're listening and committed to improvement...";
return 'Your thoughts...';
},
rows: 3,
autoExpand: true,
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null
});
});
// ============================================
// SECTION 2: Impact & Transparency Rating
// ============================================
const impactSection = form.addSubform('impactSection', {
title: 'Impact & Transparency',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null,
customStyles: { backgroundColor: '#f8fafc', padding: '16px', borderRadius: '8px' }
});
impactSection.addRow(row => {
row.addMatrixQuestion('satisfactionMatrix', {
label: 'Please rate your satisfaction with the following:',
rows: [
{ id: 'impact', label: 'Clarity of impact reporting', isRequired: true },
{ id: 'transparency', label: 'Financial transparency' },
{ id: 'communication', label: 'Communication frequency & quality' },
{ id: 'acknowledgment', label: 'Donation acknowledgment' },
{ id: 'engagement', label: 'Opportunities to get involved' }
],
columns: [
{ id: 'very-dissatisfied', label: 'Very Dissatisfied' },
{ id: 'dissatisfied', label: 'Dissatisfied' },
{ id: 'neutral', label: 'Neutral' },
{ id: 'satisfied', label: 'Satisfied' },
{ id: 'very-satisfied', label: 'Very Satisfied' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 3: Emotional Connection
// ============================================
const emotionSection = form.addSubform('emotionSection', {
title: 'Your Connection to Our Cause',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null,
customStyles: { backgroundColor: '#fdf4ff', padding: '16px', borderRadius: '8px' }
});
emotionSection.addRow(row => {
row.addEmojiRating('emotionalConnection', {
label: 'How connected do you feel to our mission?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
emotionSection.addSpacer({ height: '16px' });
emotionSection.addRow(row => {
row.addStarRating('overallSatisfaction', {
label: 'Overall satisfaction with your donor experience',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
// ============================================
// SECTION 4: What Matters Most
// ============================================
const prioritiesSection = form.addSubform('prioritiesSection', {
title: 'What Matters Most to You',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null,
customStyles: { backgroundColor: '#f0fdf4', padding: '16px', borderRadius: '8px' }
});
prioritiesSection.addRow(row => {
row.addSuggestionChips('priorities', {
label: 'Select what matters most to you as a donor (up to 3)',
suggestions: [
{ id: 'impact-stories', name: 'Impact stories' },
{ id: 'financial-reports', name: 'Financial reports' },
{ id: 'volunteer-ops', name: 'Volunteer opportunities' },
{ id: 'events', name: 'Events & gatherings' },
{ id: 'newsletters', name: 'Regular updates' },
{ id: 'recognition', name: 'Donor recognition' },
{ id: 'personal-contact', name: 'Personal contact' },
{ id: 'matching-gifts', name: 'Matching gift programs' }
],
max: 3,
alignment: 'center'
});
});
// ============================================
// SECTION 5: Areas for Improvement (Detractors/Passives)
// ============================================
const improvementSection = form.addSubform('improvementSection', {
title: 'How Can We Improve?',
isVisible: () => {
const score = npsSection.ratingScale('donorNps')?.value();
return score !== null && score !== undefined && score <= 7;
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
improvementSection.addRow(row => {
row.addCheckboxList('improvementAreas', {
label: 'What areas need the most improvement?',
options: [
{ id: 'communication', name: 'Communication & updates' },
{ id: 'transparency', name: 'Financial transparency' },
{ id: 'impact', name: 'Showing impact of donations' },
{ id: 'acknowledgment', name: 'Donation acknowledgment' },
{ id: 'engagement', name: 'Engagement opportunities' },
{ id: 'ease', name: 'Ease of donating' },
{ id: 'website', name: 'Website experience' },
{ id: 'events', name: 'Events & activities' }
],
orientation: 'vertical'
});
});
improvementSection.addSpacer({ height: '12px' });
improvementSection.addRow(row => {
row.addTextarea('improvementDetails', {
label: 'Please share specific suggestions for improvement',
placeholder: 'Your ideas help us serve our community and donors better...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 6: Future Giving Intent
// ============================================
const futureSection = form.addSubform('futureSection', {
title: 'Future Support',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null
});
futureSection.addRow(row => {
row.addRadioButton('givingIntent', {
label: 'How likely are you to continue supporting our organization?',
options: [
{ id: 'definitely', name: 'Definitely will continue' },
{ id: 'probably', name: 'Probably will continue' },
{ id: 'unsure', name: 'Not sure' },
{ id: 'unlikely', name: 'Unlikely to continue' }
],
orientation: 'vertical'
});
});
futureSection.addRow(row => {
row.addCheckbox('increaseGiving', {
label: 'I am interested in increasing my giving or becoming a monthly donor',
isVisible: () => {
const intent = futureSection.radioButton('givingIntent')?.value();
return intent === 'definitely' || intent === 'probably';
}
});
});
// ============================================
// SECTION 7: Contact Preferences
// ============================================
const contactSection = form.addSubform('contactSection', {
title: 'Stay Connected',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null
});
contactSection.addRow(row => {
row.addCheckbox('allowContact', {
label: 'I would like someone to follow up with me about my feedback'
});
});
contactSection.addRow(row => {
row.addTextbox('contactName', {
label: 'Your name',
placeholder: 'Optional - for personalized follow-up',
isVisible: () => contactSection.checkbox('allowContact')?.value() === true
}, '1fr');
row.addEmail('contactEmail', {
label: 'Email address',
placeholder: 'your@email.com',
isRequired: () => contactSection.checkbox('allowContact')?.value() === true,
isVisible: () => contactSection.checkbox('allowContact')?.value() === true
}, '1fr');
});
// ============================================
// SECTION 8: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const npsScore = npsSection.ratingScale('donorNps')?.value();
const category = npsSection.ratingScale('donorNps')?.npsCategory();
const overallRating = emotionSection.starRating('overallSatisfaction')?.value();
const emotionalConnection = emotionSection.emojiRating('emotionalConnection')?.value();
const priorities = prioritiesSection.suggestionChips('priorities')?.value() || [];
const givingIntent = futureSection.radioButton('givingIntent')?.value();
if (npsScore === null || npsScore === undefined) return '';
let emoji = '';
if (category === 'promoter') emoji = '💜';
else if (category === 'passive') emoji = '💭';
else emoji = '🙏';
let summary = `${emoji} Donor Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
summary += `📊 NPS Score: ${npsScore}/10 (${category?.charAt(0).toUpperCase()}${category?.slice(1)})\n`;
if (overallRating) {
summary += `⭐ Overall Satisfaction: ${overallRating}/5 stars\n`;
}
if (emotionalConnection) {
const connectionLabels: Record<string, string> = {
'very-bad': '😟 Disconnected',
'bad': '😐 Somewhat disconnected',
'neutral': '🤔 Neutral',
'good': '😊 Connected',
'excellent': '💜 Deeply connected'
};
summary += `\n${connectionLabels[emotionalConnection] || emotionalConnection}\n`;
}
if (priorities.length > 0) {
summary += `\n🎯 Top priorities: ${priorities.length} selected`;
}
if (givingIntent) {
const intentLabels: Record<string, string> = {
'definitely': '✅ Will definitely continue',
'probably': '👍 Probably will continue',
'unsure': '🤷 Unsure',
'unlikely': '⚠️ Unlikely to continue'
};
summary += `\n${intentLabels[givingIntent] || givingIntent}`;
}
return summary;
},
customStyles: () => {
const category = npsSection.ratingScale('donorNps')?.npsCategory();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') {
return { ...baseStyles, backgroundColor: '#f3e8ff', borderLeft: '4px solid #a855f7' };
} else if (category === 'passive') {
return { ...baseStyles, backgroundColor: '#fef9c3', borderLeft: '4px solid #eab308' };
} else if (category === 'detractor') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return baseStyles;
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => npsSection.ratingScale('donorNps')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your voice helps us strengthen our mission and better serve our community. We deeply appreciate your support and your time in sharing these insights.'
});
}