export function beneficiaryFeedbackForm(form: FormTs) {
// Program Beneficiary Feedback Form
// Demonstrates: EmojiRating, StarRating, MatrixQuestion, SuggestionChips, ThumbRating
// Focus: Accessibility-centered design for inclusive feedback collection
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Your Voice Matters',
computedValue: () => 'Help us serve you better. Your honest feedback makes our programs stronger.',
customStyles: {
backgroundColor: '#7c3aed',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center',
fontSize: '16px'
}
});
});
// ============================================
// SECTION 1: Overall Experience (Emoji-based for accessibility)
// ============================================
const experienceSection = form.addSubform('experienceSection', {
title: 'How Was Your Experience?',
customStyles: { backgroundColor: '#faf5ff', padding: '20px', borderRadius: '12px' }
});
experienceSection.addRow(row => {
row.addEmojiRating('overallExperience', {
label: 'How do you feel about our program overall?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
experienceSection.addRow(row => {
row.addTextPanel('experienceNote', {
computedValue: () => {
const exp = experienceSection.emojiRating('overallExperience')?.value();
if (exp === 'excellent') return 'We are so happy to hear that!';
if (exp === 'good') return 'Thank you! We appreciate your positive feedback.';
if (exp === 'neutral') return 'We would love to hear how we can do better.';
if (exp === 'bad' || exp === 'very-bad') return 'We are sorry. Please tell us what went wrong so we can improve.';
return '';
},
customStyles: () => {
const exp = experienceSection.emojiRating('overallExperience')?.value();
if (!exp) return { display: 'none' };
const colors: Record<string, string> = {
'excellent': '#d1fae5',
'good': '#dbeafe',
'neutral': '#fef3c7',
'bad': '#fee2e2',
'very-bad': '#fee2e2'
};
return {
backgroundColor: colors[exp] || '#f3f4f6',
padding: '12px',
borderRadius: '8px',
textAlign: 'center'
};
},
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
});
// ============================================
// SECTION 2: Program Aspects Rating
// ============================================
const aspectsSection = form.addSubform('aspectsSection', {
title: 'Rate Our Program',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
aspectsSection.addRow(row => {
row.addStarRating('staffHelpfulness', {
label: 'Staff helpfulness and friendliness',
maxStars: 5,
size: 'lg',
alignment: 'left',
showCounter: true
});
});
aspectsSection.addRow(row => {
row.addStarRating('programQuality', {
label: 'Quality of services or support received',
maxStars: 5,
size: 'lg',
alignment: 'left',
showCounter: true
});
});
aspectsSection.addRow(row => {
row.addStarRating('communication', {
label: 'Clear communication and information',
maxStars: 5,
size: 'lg',
alignment: 'left',
showCounter: true
});
});
aspectsSection.addRow(row => {
row.addStarRating('timeliness', {
label: 'Timeliness and scheduling convenience',
maxStars: 5,
size: 'lg',
alignment: 'left',
showCounter: true
});
});
// ============================================
// SECTION 3: Accessibility Assessment
// ============================================
const accessibilitySection = form.addSubform('accessibilitySection', {
title: 'Accessibility & Inclusion',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
accessibilitySection.addRow(row => {
row.addMatrixQuestion('accessibilityMatrix', {
label: 'How accessible was our program for you?',
rows: [
{ id: 'location', label: 'Physical location / Getting there' },
{ id: 'facilities', label: 'Building and facilities' },
{ id: 'materials', label: 'Written materials and forms' },
{ id: 'language', label: 'Language and communication' },
{ id: 'scheduling', label: 'Scheduling flexibility' }
],
columns: [
{ id: 'very-easy', label: 'Very Easy' },
{ id: 'easy', label: 'Easy' },
{ id: 'neutral', label: 'Okay' },
{ id: 'difficult', label: 'Difficult' },
{ id: 'na', label: 'N/A' }
],
striped: true,
fullWidth: true
});
});
accessibilitySection.addSpacer();
accessibilitySection.addRow(row => {
row.addTextarea('accessibilityBarriers', {
label: 'Did you face any barriers or challenges accessing our services?',
placeholder: 'Please describe any difficulties you experienced...',
rows: 3,
autoExpand: true,
isVisible: () => {
const matrix = accessibilitySection.matrixQuestion('accessibilityMatrix')?.value();
if (!matrix) return true;
return Object.values(matrix).some(v => v === 'difficult');
}
});
});
// ============================================
// SECTION 4: What Helped Most
// ============================================
const helpfulSection = form.addSubform('helpfulSection', {
title: 'What Helped You Most?',
isVisible: () => {
const exp = experienceSection.emojiRating('overallExperience')?.value();
return exp === 'excellent' || exp === 'good' || exp === 'neutral';
},
customStyles: { backgroundColor: '#ecfdf5', padding: '16px', borderRadius: '8px' }
});
helpfulSection.addRow(row => {
row.addSuggestionChips('helpfulAspects', {
label: 'Select what was most helpful (choose up to 4)',
suggestions: [
{ id: 'staff-support', name: 'Staff support' },
{ id: 'resources', name: 'Resources provided' },
{ id: 'training', name: 'Training/Education' },
{ id: 'community', name: 'Community connection' },
{ id: 'financial-aid', name: 'Financial assistance' },
{ id: 'counseling', name: 'Counseling/Guidance' },
{ id: 'referrals', name: 'Referrals to other services' },
{ id: 'follow-up', name: 'Follow-up support' }
],
max: 4,
alignment: 'left'
});
});
// ============================================
// SECTION 5: Areas for Improvement
// ============================================
const improvementSection = form.addSubform('improvementSection', {
title: 'How Can We Improve?',
isVisible: () => {
const exp = experienceSection.emojiRating('overallExperience')?.value();
return exp === 'neutral' || exp === 'bad' || exp === 'very-bad';
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
improvementSection.addRow(row => {
row.addSuggestionChips('improvementAreas', {
label: 'What should we improve?',
suggestions: [
{ id: 'wait-times', name: 'Reduce wait times' },
{ id: 'more-staff', name: 'More staff availability' },
{ id: 'location', name: 'Better location/access' },
{ id: 'hours', name: 'Extended hours' },
{ id: 'communication', name: 'Better communication' },
{ id: 'language', name: 'More language options' },
{ id: 'follow-up', name: 'Better follow-up' },
{ id: 'resources', name: 'More resources' }
],
alignment: 'left'
});
});
improvementSection.addSpacer();
improvementSection.addRow(row => {
row.addTextarea('improvementDetails', {
label: 'Please tell us more about how we can improve',
placeholder: 'Your suggestions help us serve you better...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 6: Program Impact
// ============================================
const impactSection = form.addSubform('impactSection', {
title: 'Program Impact',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
impactSection.addRow(row => {
row.addRatingScale('lifeImpact', {
label: 'How much did this program improve your situation?',
preset: 'custom',
min: 1,
max: 5,
lowLabel: 'No improvement',
highLabel: 'Major improvement',
variant: 'segmented',
size: 'lg'
});
});
impactSection.addRow(row => {
row.addThumbRating('recommend', {
label: 'Would you recommend this program to others?',
size: 'lg',
showLabels: true,
upLabel: 'Yes, I would',
downLabel: 'No',
alignment: 'center'
});
});
// ============================================
// SECTION 7: Additional Comments
// ============================================
const commentsSection = form.addSubform('commentsSection', {
title: 'Anything Else?',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
commentsSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Is there anything else you would like to share with us?',
placeholder: 'Your story, suggestions, or questions...',
rows: 4,
autoExpand: true
});
});
// ============================================
// SECTION 8: Contact (Optional)
// ============================================
const contactSection = form.addSubform('contactSection', {
title: 'Stay Connected (Optional)',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
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: 'How should we address you?',
isVisible: () => contactSection.checkbox('allowContact')?.value() === true,
isRequired: () => contactSection.checkbox('allowContact')?.value() === true
});
});
contactSection.addRow(row => {
row.addTextbox('contactPhone', {
label: 'Phone number (optional)',
placeholder: 'Best number to reach you',
isVisible: () => contactSection.checkbox('allowContact')?.value() === true
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Your Feedback Summary',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const experience = experienceSection.emojiRating('overallExperience')?.value();
const staffRating = aspectsSection.starRating('staffHelpfulness')?.value();
const programRating = aspectsSection.starRating('programQuality')?.value();
const recommend = impactSection.thumbRating('recommend')?.value();
const impact = impactSection.ratingScale('lifeImpact')?.value();
if (!experience) return '';
const expLabels: Record<string, string> = {
'excellent': 'Excellent',
'good': 'Good',
'neutral': 'Neutral',
'bad': 'Poor',
'very-bad': 'Very Poor'
};
let summary = 'Thank you for your feedback!\n';
summary += '━'.repeat(30) + '\n\n';
summary += `Overall Experience: ${expLabels[experience] || experience}\n`;
if (staffRating) summary += `Staff Rating: ${'★'.repeat(staffRating)}${'☆'.repeat(5 - staffRating)}\n`;
if (programRating) summary += `Program Quality: ${'★'.repeat(programRating)}${'☆'.repeat(5 - programRating)}\n`;
if (impact) summary += `Life Impact: ${impact}/5\n`;
if (recommend) summary += `Would Recommend: ${recommend === 'up' ? 'Yes' : 'No'}\n`;
return summary;
},
customStyles: {
backgroundColor: '#f3f4f6',
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => !!experienceSection.emojiRating('overallExperience')?.value()
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You!',
message: 'Your feedback is incredibly valuable to us. It helps us improve our programs and better serve our community. Thank you for taking the time to share your experience.'
});
}