export function libraryPublicFeedback(form: FormTs) {
// Public Library Services Feedback Form
// Demonstrates: MatrixQuestion, StarRating, EmojiRating, SuggestionChips, RadioButton, conditional visibility, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Library Patron Feedback',
computedValue: () => 'Help us serve you better! Your feedback shapes the future of our library.',
customStyles: {
background: 'linear-gradient(135deg, #0d9488 0%, #14b8a6 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Visit Information
// ============================================
const visitSection = form.addSubform('visitSection', {
title: 'About Your Visit',
customStyles: { backgroundColor: '#f0fdfa', padding: '16px', borderRadius: '8px' }
});
visitSection.addRow(row => {
row.addRadioButton('visitFrequency', {
label: 'How often do you visit our library?',
options: [
{ id: 'first', name: 'This is my first visit' },
{ id: 'rarely', name: 'A few times a year' },
{ id: 'monthly', name: 'Monthly' },
{ id: 'weekly', name: 'Weekly' },
{ id: 'daily', name: 'Almost daily' }
],
orientation: 'vertical',
isRequired: true
}, '1fr');
row.addCheckboxList('visitPurpose', {
label: 'What brought you to the library today?',
options: [
{ id: 'borrow', name: 'Borrow books/media' },
{ id: 'study', name: 'Study or work' },
{ id: 'internet', name: 'Use computers/internet' },
{ id: 'research', name: 'Research assistance' },
{ id: 'programs', name: 'Attend a program/event' },
{ id: 'children', name: "Children's activities" },
{ id: 'meeting', name: 'Meeting room use' },
{ id: 'browse', name: 'Browse and relax' }
],
orientation: 'vertical'
}, '1fr');
});
// ============================================
// SECTION 2: Services & Resources Rating
// ============================================
const servicesSection = form.addSubform('servicesSection', {
title: 'Rate Our Services & Resources',
customStyles: { backgroundColor: '#f8fafc', padding: '16px', borderRadius: '8px' }
});
servicesSection.addRow(row => {
row.addMatrixQuestion('servicesMatrix', {
label: 'Please rate your satisfaction with the following:',
rows: [
{ id: 'book-collection', label: 'Book collection variety and availability', isRequired: true },
{ id: 'digital', label: 'Digital resources (e-books, databases)' },
{ id: 'staff', label: 'Staff helpfulness and knowledge', isRequired: true },
{ id: 'computers', label: 'Computer and internet access' },
{ id: 'study-spaces', label: 'Study and reading areas' },
{ id: 'cleanliness', label: 'Facility cleanliness' },
{ id: 'hours', label: 'Operating hours' }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' },
{ id: 'na', label: 'N/A' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 3: Staff Interaction
// ============================================
const staffSection = form.addSubform('staffSection', {
title: 'Staff Interaction',
isVisible: () => {
const purposes = visitSection.checkboxList('visitPurpose')?.value() || [];
return purposes.includes('research') || purposes.includes('borrow');
},
customStyles: { backgroundColor: '#eff6ff', padding: '16px', borderRadius: '8px' }
});
staffSection.addRow(row => {
row.addStarRating('staffRating', {
label: 'How would you rate the staff assistance you received?',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
staffSection.addRow(row => {
row.addThumbRating('staffRecommend', {
label: 'Would you recommend our library based on staff service?',
showLabels: true,
upLabel: 'Absolutely!',
downLabel: 'Needs improvement',
alignment: 'center',
size: 'lg'
});
});
// ============================================
// SECTION 4: Overall Experience
// ============================================
const experienceSection = form.addSubform('experienceSection', {
title: 'Overall Experience'
});
experienceSection.addRow(row => {
row.addEmojiRating('overallMood', {
label: 'How would you describe your library visit today?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
experienceSection.addSpacer({ height: '16px' });
experienceSection.addRow(row => {
row.addRatingScale('npsScore', {
preset: 'nps',
label: 'How likely are you to recommend our library to friends and family?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
// ============================================
// SECTION 5: What We Do Well (Promoters)
// ============================================
const strengthsSection = form.addSubform('strengthsSection', {
title: 'What Do You Love About Our Library?',
isVisible: () => {
const score = experienceSection.ratingScale('npsScore')?.value();
return score !== null && score !== undefined && score >= 7;
},
customStyles: { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' }
});
strengthsSection.addRow(row => {
row.addSuggestionChips('strengths', {
label: 'Select what you appreciate most (up to 4)',
suggestions: [
{ id: 'collection', name: 'Great book selection' },
{ id: 'staff', name: 'Friendly staff' },
{ id: 'quiet', name: 'Quiet atmosphere' },
{ id: 'programs', name: 'Interesting programs' },
{ id: 'location', name: 'Convenient location' },
{ id: 'hours', name: 'Good hours' },
{ id: 'technology', name: 'Modern technology' },
{ id: 'kids-area', name: "Children's area" },
{ id: 'free-wifi', name: 'Free Wi-Fi' }
],
max: 4,
alignment: 'center'
});
});
// ============================================
// SECTION 6: Improvement Areas (Detractors/Passives)
// ============================================
const improvementSection = form.addSubform('improvementSection', {
title: 'How Can We Improve?',
isVisible: () => {
const score = experienceSection.ratingScale('npsScore')?.value();
return score !== null && score !== undefined && score <= 6;
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
improvementSection.addRow(row => {
row.addCheckboxList('improvements', {
label: 'What areas need the most improvement?',
options: [
{ id: 'more-books', name: 'More book variety' },
{ id: 'newer-books', name: 'More recent publications' },
{ id: 'more-computers', name: 'More computers available' },
{ id: 'longer-hours', name: 'Extended operating hours' },
{ id: 'more-seating', name: 'More seating/study space' },
{ id: 'quieter', name: 'Quieter environment' },
{ id: 'parking', name: 'Better parking' },
{ id: 'accessibility', name: 'Improved accessibility' },
{ id: 'programs', name: 'More programs/events' }
],
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 the community better...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 7: Programs Interest
// ============================================
const programsSection = form.addSubform('programsSection', {
title: 'Library Programs'
});
programsSection.addRow(row => {
row.addCheckboxList('programInterests', {
label: 'What types of programs would you like to see?',
options: [
{ id: 'book-clubs', name: 'Book clubs' },
{ id: 'author-talks', name: 'Author talks' },
{ id: 'tech-classes', name: 'Technology classes' },
{ id: 'kids-storytime', name: "Children's story time" },
{ id: 'teen-programs', name: 'Teen programs' },
{ id: 'senior-activities', name: 'Senior activities' },
{ id: 'job-help', name: 'Job search assistance' },
{ id: 'language', name: 'Language learning' }
],
orientation: 'vertical'
}, '1fr');
row.addRadioButton('programTime', {
label: 'When would you prefer programs?',
options: [
{ id: 'weekday-morning', name: 'Weekday mornings' },
{ id: 'weekday-afternoon', name: 'Weekday afternoons' },
{ id: 'weekday-evening', name: 'Weekday evenings' },
{ id: 'weekend', name: 'Weekends' },
{ id: 'any', name: 'Any time works' }
],
orientation: 'vertical'
}, '1fr');
});
// ============================================
// SECTION 8: Additional Comments
// ============================================
const commentsSection = form.addSubform('commentsSection', {
title: 'Additional Comments'
});
commentsSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Is there anything else you would like to share with us?',
placeholder: 'Tell us about a great experience, suggest a book, or share any thoughts...',
rows: 4,
autoExpand: true
});
});
// ============================================
// SECTION 9: Contact (Optional)
// ============================================
const contactSection = form.addSubform('contactSection', {
title: 'Stay Connected (Optional)'
});
contactSection.addRow(row => {
row.addCheckbox('wantsContact', {
label: 'I would like to be contacted about my feedback'
});
});
contactSection.addRow(row => {
row.addTextbox('contactName', {
label: 'Name',
placeholder: 'Your name',
isVisible: () => contactSection.checkbox('wantsContact')?.value() === true
}, '1fr');
row.addEmail('contactEmail', {
label: 'Email',
placeholder: 'your@email.com',
isRequired: () => contactSection.checkbox('wantsContact')?.value() === true,
isVisible: () => contactSection.checkbox('wantsContact')?.value() === true
}, '1fr');
});
contactSection.addRow(row => {
row.addCheckbox('libraryCard', {
label: 'I am interested in getting a library card',
isVisible: () => visitSection.radioButton('visitFrequency')?.value() === 'first'
});
});
// ============================================
// SECTION 10: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => experienceSection.ratingScale('npsScore')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const npsScore = experienceSection.ratingScale('npsScore')?.value();
const npsCategory = experienceSection.ratingScale('npsScore')?.npsCategory();
const mood = experienceSection.emojiRating('overallMood')?.value();
const frequency = visitSection.radioButton('visitFrequency')?.value();
const purposes = visitSection.checkboxList('visitPurpose')?.value() || [];
const strengths = strengthsSection.suggestionChips('strengths')?.value() || [];
const improvements = improvementSection.checkboxList('improvements')?.value() || [];
if (npsScore === null || npsScore === undefined) return '';
let emoji = '';
if (npsCategory === 'promoter') emoji = '📚';
else if (npsCategory === 'passive') emoji = '📖';
else emoji = '📝';
let summary = `${emoji} Library Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
summary += `📊 NPS Score: ${npsScore}/10 (${npsCategory?.charAt(0).toUpperCase()}${npsCategory?.slice(1)})\n`;
if (mood) {
const moodLabels: Record<string, string> = {
'very-bad': '😢 Poor experience',
'bad': '😕 Could be better',
'neutral': '😐 Okay visit',
'good': '😊 Good experience',
'excellent': '😍 Excellent visit!'
};
summary += `${moodLabels[mood] || mood}\n`;
}
const frequencyLabels: Record<string, string> = {
'first': 'First-time visitor',
'rarely': 'Occasional visitor',
'monthly': 'Monthly visitor',
'weekly': 'Weekly visitor',
'daily': 'Daily visitor'
};
if (frequency) {
summary += `\n👤 ${frequencyLabels[frequency] || frequency}`;
}
if (purposes.length > 0) {
summary += `\n📌 Visit purposes: ${purposes.length} selected`;
}
if (strengths.length > 0) {
summary += `\n✨ Appreciated: ${strengths.length} aspects`;
}
if (improvements.length > 0) {
summary += `\n⚡ To improve: ${improvements.length} areas`;
}
return summary;
},
customStyles: () => {
const category = experienceSection.ratingScale('npsScore')?.npsCategory();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #14b8a6' };
} 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;
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => experienceSection.ratingScale('npsScore')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your input helps us make our library a better place for everyone in our community. We appreciate you taking the time to share your thoughts!'
});
}