export function memberEngagementSurvey(form: FormTs) {
// Membership Engagement Survey for Non-Profit Organizations
// Demonstrates: NPS, MatrixQuestion, StarRating, EmojiRating, Slider, dynamic styling, conditional visibility
// ============================================
// STATE
// ============================================
const membershipYears = form.state<string | null>(null);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Member Engagement Survey',
computedValue: () => 'Help us serve you better. Your feedback shapes our programs and services.',
customStyles: {
backgroundColor: '#0891b2',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Member Profile
// ============================================
const profileSection = form.addSubform('profile', {
title: 'About Your Membership'
});
profileSection.addRow(row => {
row.addDropdown('membershipLength', {
label: 'How long have you been a member?',
options: [
{ id: 'less-1', name: 'Less than 1 year' },
{ id: '1-2', name: '1-2 years' },
{ id: '3-5', name: '3-5 years' },
{ id: '6-10', name: '6-10 years' },
{ id: 'more-10', name: 'More than 10 years' }
],
isRequired: true,
onValueChange: (val) => membershipYears.set(val ?? null)
}, '1fr');
row.addDropdown('membershipType', {
label: 'Membership type',
options: [
{ id: 'individual', name: 'Individual' },
{ id: 'family', name: 'Family' },
{ id: 'student', name: 'Student' },
{ id: 'senior', name: 'Senior' },
{ id: 'lifetime', name: 'Lifetime' },
{ id: 'corporate', name: 'Corporate' }
],
isRequired: true
}, '1fr');
});
profileSection.addRow(row => {
row.addCheckboxList('participationAreas', {
label: 'Which programs or activities have you participated in? (Select all that apply)',
options: [
{ id: 'events', name: 'Events & gatherings' },
{ id: 'workshops', name: 'Workshops & training' },
{ id: 'volunteering', name: 'Volunteering' },
{ id: 'committees', name: 'Committees & leadership' },
{ id: 'newsletter', name: 'Newsletter & publications' },
{ id: 'mentorship', name: 'Mentorship programs' },
{ id: 'networking', name: 'Networking opportunities' },
{ id: 'none', name: 'None yet' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 2: Overall Satisfaction (NPS)
// ============================================
const npsSection = form.addSubform('nps', {
title: 'Overall Satisfaction',
customStyles: () => {
const category = npsSection.ratingScale('memberNps')?.npsCategory();
if (category === 'promoter') return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (category === 'passive') return { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' };
if (category === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #cbd5e1' };
}
});
npsSection.addRow(row => {
row.addRatingScale('memberNps', {
preset: 'nps',
label: 'How likely are you to recommend membership to a friend or colleague?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
npsSection.addRow(row => {
row.addTextarea('npsReason', {
label: () => {
const category = npsSection.ratingScale('memberNps')?.npsCategory();
switch (category) {
case 'promoter': return "That's wonderful! What do you value most about your membership?";
case 'passive': return "Thanks! What could we do to earn a higher rating?";
case 'detractor': return "We're sorry to hear that. What's the main issue with your membership?";
default: return 'Please share your thoughts';
}
},
placeholder: 'Your feedback helps us improve...',
rows: 3,
isVisible: () => npsSection.ratingScale('memberNps')?.value() !== null
});
});
// ============================================
// SECTION 3: Benefits Evaluation (MatrixQuestion)
// ============================================
const benefitsSection = form.addSubform('benefits', {
title: 'Membership Benefits',
isVisible: () => npsSection.ratingScale('memberNps')?.value() !== null
});
benefitsSection.addRow(row => {
row.addMatrixQuestion('benefitsRating', {
label: 'How would you rate the following membership benefits?',
rows: [
{ id: 'events', label: 'Events & programming', isRequired: true },
{ id: 'resources', label: 'Resources & publications', isRequired: true },
{ id: 'networking', label: 'Networking opportunities', isRequired: true },
{ id: 'discounts', label: 'Member discounts', isRequired: false },
{ id: 'advocacy', label: 'Advocacy & representation', isRequired: false },
{ id: 'community', label: 'Sense of community', isRequired: true }
],
columns: [
{ id: 'excellent', label: 'Excellent' },
{ id: 'good', label: 'Good' },
{ id: 'fair', label: 'Fair' },
{ id: 'poor', label: 'Poor' },
{ id: 'na', label: 'N/A' }
],
striped: true,
fullWidth: true
});
});
benefitsSection.addSpacer();
benefitsSection.addRow(row => {
row.addTextarea('missingBenefits', {
label: 'What benefits would you like to see added?',
placeholder: 'Share your ideas for new member benefits...',
rows: 2
});
});
// ============================================
// SECTION 4: Value Perception
// ============================================
const valueSection = form.addSubform('value', {
title: 'Value for Money',
isVisible: () => benefitsSection.matrixQuestion('benefitsRating')?.areAllRequiredRowsAnswered() ?? false
});
valueSection.addRow(row => {
row.addSlider('valueRating', {
label: 'How would you rate the overall value of your membership?',
min: 1,
max: 10,
step: 1,
defaultValue: 5,
showValue: true,
unit: '/10'
});
});
valueSection.addRow(row => {
row.addEmojiRating('valueFeeling', {
label: 'How do you feel about your membership investment?',
preset: 'satisfaction',
size: 'lg',
alignment: 'center'
});
});
// ============================================
// SECTION 5: Communication Preferences
// ============================================
const commSection = form.addSubform('communication', {
title: 'Communication & Engagement',
isVisible: () => valueSection.slider('valueRating')?.value() !== null
});
commSection.addRow(row => {
row.addRadioButton('commFrequency', {
label: 'How often would you like to hear from us?',
options: [
{ id: 'weekly', name: 'Weekly' },
{ id: 'biweekly', name: 'Every two weeks' },
{ id: 'monthly', name: 'Monthly' },
{ id: 'quarterly', name: 'Quarterly' }
],
orientation: 'horizontal'
}, '1fr');
});
commSection.addRow(row => {
row.addCheckboxList('preferredChannels', {
label: 'Preferred communication channels',
options: [
{ id: 'email', name: 'Email newsletter' },
{ id: 'social', name: 'Social media' },
{ id: 'sms', name: 'Text/SMS' },
{ id: 'mail', name: 'Postal mail' },
{ id: 'app', name: 'Mobile app notifications' }
],
orientation: 'horizontal',
max: 3
});
});
commSection.addRow(row => {
row.addStarRating('websiteRating', {
label: 'How would you rate our website/member portal?',
maxStars: 5,
size: 'lg',
alignment: 'center',
showCounter: true
});
});
// ============================================
// SECTION 6: Renewal Intent
// ============================================
const renewalSection = form.addSubform('renewal', {
title: 'Membership Renewal',
isVisible: () => commSection.starRating('websiteRating')?.value() !== null,
customStyles: {
backgroundColor: '#f0f9ff',
padding: '16px',
borderRadius: '8px'
}
});
renewalSection.addRow(row => {
row.addRatingScale('renewalLikelihood', {
preset: 'likert-5',
label: 'How likely are you to renew your membership?',
lowLabel: 'Very unlikely',
highLabel: 'Very likely',
alignment: 'center'
});
});
renewalSection.addRow(row => {
row.addRadioButton('renewalBarrier', {
label: () => {
const likelihood = renewalSection.ratingScale('renewalLikelihood')?.value();
if (likelihood !== null && likelihood !== undefined && likelihood <= 2) {
return "What's the main reason you might not renew?";
}
return "What would make you even more likely to renew?";
},
options: () => {
const likelihood = renewalSection.ratingScale('renewalLikelihood')?.value();
if (likelihood !== null && likelihood !== undefined && likelihood <= 2) {
return [
{ id: 'cost', name: 'Membership cost' },
{ id: 'time', name: 'No time to participate' },
{ id: 'value', name: 'Not enough value' },
{ id: 'moving', name: 'Moving/relocating' },
{ id: 'other', name: 'Other reason' }
];
}
return [
{ id: 'events', name: 'More events' },
{ id: 'discounts', name: 'Better discounts' },
{ id: 'networking', name: 'More networking' },
{ id: 'resources', name: 'More resources' },
{ id: 'already-great', name: 'Already planning to renew!' }
];
},
orientation: 'vertical',
isVisible: () => renewalSection.ratingScale('renewalLikelihood')?.value() !== null
});
});
// ============================================
// SECTION 7: Additional Feedback
// ============================================
const additionalSection = form.addSubform('additional', {
title: 'Final Thoughts',
isVisible: () => renewalSection.ratingScale('renewalLikelihood')?.value() !== null
});
additionalSection.addRow(row => {
row.addThumbRating('volunteerInterest', {
label: 'Would you be interested in volunteering or serving on a committee?',
showLabels: true,
upLabel: 'Yes, interested!',
downLabel: 'Not right now',
size: 'lg',
alignment: 'center'
});
});
additionalSection.addSpacer();
additionalSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Any other feedback or suggestions for improving your membership experience?',
placeholder: 'We value all feedback...',
rows: 4,
autoExpand: true
});
});
// ============================================
// SECTION 8: Contact (Optional)
// ============================================
const contactSection = form.addSubform('contact', {
title: 'Stay Connected (Optional)',
isVisible: () => additionalSection.thumbRating('volunteerInterest')?.value() !== null
});
contactSection.addRow(row => {
row.addCheckbox('shareEmail', {
label: 'Share my email for follow-up about my feedback'
});
});
contactSection.addRow(row => {
row.addEmail('email', {
label: 'Email address',
placeholder: 'your@email.com',
isVisible: () => contactSection.checkbox('shareEmail')?.value() === true,
isRequired: () => contactSection.checkbox('shareEmail')?.value() === true
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Your Feedback Summary',
isVisible: () => contactSection.checkbox('shareEmail')?.value() !== null ||
(additionalSection.thumbRating('volunteerInterest')?.value() !== null &&
contactSection.checkbox('shareEmail')?.value() === null)
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const npsScore = npsSection.ratingScale('memberNps')?.value();
const npsCategory = npsSection.ratingScale('memberNps')?.npsCategory();
const valueRating = valueSection.slider('valueRating')?.value();
const renewalScore = renewalSection.ratingScale('renewalLikelihood')?.value();
const volunteerInterest = additionalSection.thumbRating('volunteerInterest')?.value();
if (!npsScore) return '';
let emoji = '📊';
if (npsCategory === 'promoter') emoji = '🌟';
else if (npsCategory === 'passive') emoji = '👍';
else if (npsCategory === 'detractor') emoji = '💬';
let summary = `${emoji} Engagement Summary\n`;
summary += `${'═'.repeat(25)}\n\n`;
summary += `📈 Member NPS: ${npsScore}/10 (${npsCategory?.charAt(0).toUpperCase()}${npsCategory?.slice(1)})\n`;
if (valueRating) {
summary += `💰 Value Rating: ${valueRating}/10\n`;
}
if (renewalScore) {
const renewalLabels: Record<number, string> = {
1: 'Very Unlikely',
2: 'Unlikely',
3: 'Neutral',
4: 'Likely',
5: 'Very Likely'
};
summary += `🔄 Renewal Intent: ${renewalLabels[renewalScore] || renewalScore}\n`;
}
if (volunteerInterest) {
summary += `\n🙋 Volunteer Interest: ${volunteerInterest === 'up' ? 'Yes!' : 'Not now'}`;
}
return summary;
},
customStyles: () => {
const category = npsSection.ratingScale('memberNps')?.npsCategory();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (category === 'passive') {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
} else if (category === 'detractor') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#f1f5f9' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => npsSection.ratingScale('memberNps')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your input is invaluable in helping us improve membership experience. Together, we make our community stronger.'
});
}