export function meetupFeedback(form: FormTs) {
// Meetup/Community Event Feedback Form
// Demonstrates: EmojiRating, StarRating, SuggestionChips, ThumbRating,
// RadioButton, conditional visibility, casual/fun styling, computed values
// ============================================
// STATE
// ============================================
const eventFormat = form.state<string | null>(null);
const overallVibe = form.state<string | null>(null);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'How Was the Meetup?',
computedValue: () => 'Thanks for joining us! Quick feedback helps us make future events even better.',
customStyles: {
background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 50%, #3b82f6 100%)',
color: 'white',
padding: '28px',
borderRadius: '16px',
textAlign: 'center',
fontSize: '14px'
}
});
});
// ============================================
// SECTION 1: EVENT FORMAT
// ============================================
const formatSection = form.addSubform('formatSection', {
customStyles: {
backgroundColor: '#f5f3ff',
padding: '16px',
borderRadius: '12px'
}
});
formatSection.addRow(row => {
row.addRadioButton('eventFormat', {
label: 'How did you attend?',
options: [
{ id: 'in-person', name: 'In-person' },
{ id: 'virtual', name: 'Virtual/Online' },
{ id: 'hybrid', name: 'Hybrid (started one way, switched)' }
],
orientation: 'horizontal',
onValueChange: (v) => eventFormat.set(v ?? null)
});
});
// ============================================
// SECTION 2: OVERALL VIBE
// ============================================
const vibeSection = form.addSubform('vibeSection', {
title: 'The Vibe',
isVisible: () => eventFormat() !== null,
customStyles: {
backgroundColor: '#fdf4ff',
padding: '16px',
borderRadius: '12px'
}
});
vibeSection.addRow(row => {
row.addEmojiRating('overallVibe', {
label: 'How was the overall vibe?',
preset: 'mood',
size: 'lg',
alignment: 'center',
onValueChange: (v) => overallVibe.set(v ?? null)
});
});
vibeSection.addRow(row => {
row.addSuggestionChips('vibeWords', {
label: 'Pick words that describe the event (up to 3):',
suggestions: [
{ id: 'inspiring', name: 'Inspiring' },
{ id: 'fun', name: 'Fun' },
{ id: 'informative', name: 'Informative' },
{ id: 'friendly', name: 'Friendly' },
{ id: 'casual', name: 'Casual' },
{ id: 'professional', name: 'Professional' },
{ id: 'crowded', name: 'Too crowded' },
{ id: 'awkward', name: 'Awkward' }
],
max: 3,
alignment: 'center'
});
});
// ============================================
// SECTION 3: TALKS/PRESENTATIONS
// ============================================
const talksSection = form.addSubform('talksSection', {
title: 'The Talks',
isVisible: () => overallVibe() !== null
});
talksSection.addRow(row => {
row.addStarRating('talkQuality', {
label: 'Rate the talk(s)/presentation(s):',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
talksSection.addRow(row => {
row.addMatrixQuestion('talkAspects', {
label: 'How did the talks score on:',
rows: [
{ id: 'relevance', label: 'Topic relevance' },
{ id: 'depth', label: 'Technical depth' },
{ id: 'delivery', label: 'Speaker delivery' },
{ id: 'length', label: 'Appropriate length' }
],
columns: [
{ id: 'poor', label: '👎' },
{ id: 'ok', label: '👌' },
{ id: 'good', label: '👍' },
{ id: 'great', label: '🔥' }
],
alignment: 'center'
});
});
talksSection.addRow(row => {
row.addTextarea('topicSuggestions', {
label: 'What topics would you love to see at future meetups?',
placeholder: 'Share your ideas...',
rows: 2
});
});
// ============================================
// SECTION 4: NETWORKING
// ============================================
const networkingSection = form.addSubform('networkingSection', {
title: 'Networking & Community',
isVisible: () => talksSection.starRating('talkQuality')?.value() !== null
});
networkingSection.addRow(row => {
row.addThumbRating('metNewPeople', {
label: 'Did you meet interesting new people?',
showLabels: true,
upLabel: 'Yes!',
downLabel: 'Not really',
alignment: 'center',
size: 'lg'
});
});
networkingSection.addRow(row => {
row.addSlider('networkingQuality', {
label: 'Rate the networking opportunities:',
min: 1,
max: 5,
step: 1,
showValue: true,
defaultValue: 3
});
});
networkingSection.addRow(row => {
row.addCheckboxList('networkingHelpers', {
label: 'What helped with networking?',
options: [
{ id: 'icebreakers', name: 'Icebreaker activities' },
{ id: 'smallGroups', name: 'Small group discussions' },
{ id: 'breaks', name: 'Good break timing' },
{ id: 'badges', name: 'Name badges/tags' },
{ id: 'slack', name: 'Event Slack/Discord' },
{ id: 'nothing', name: 'Nothing specific' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 5: VENUE/PLATFORM (Conditional)
// ============================================
// In-person venue section
const venueSection = form.addSubform('venueSection', {
title: 'The Venue',
isVisible: () => eventFormat() === 'in-person' || eventFormat() === 'hybrid',
customStyles: {
backgroundColor: '#ecfdf5',
padding: '16px',
borderRadius: '12px'
}
});
venueSection.addRow(row => {
row.addStarRating('venueRating', {
label: 'Rate the venue:',
maxStars: 5,
size: 'md',
alignment: 'center'
});
});
venueSection.addRow(row => {
row.addSuggestionChips('venueHighlights', {
label: 'What worked well?',
suggestions: [
{ id: 'location', name: 'Great location' },
{ id: 'space', name: 'Good space' },
{ id: 'food', name: 'Nice food/drinks' },
{ id: 'av', name: 'Good A/V' },
{ id: 'seating', name: 'Comfy seating' },
{ id: 'parking', name: 'Easy parking' }
],
alignment: 'center'
});
});
venueSection.addRow(row => {
row.addCheckboxList('venueIssues', {
label: 'Any venue issues?',
options: [
{ id: 'none', name: 'No issues!' },
{ id: 'noise', name: 'Too noisy' },
{ id: 'temp', name: 'Temperature issues' },
{ id: 'crowded', name: 'Too crowded' },
{ id: 'access', name: 'Hard to access' },
{ id: 'wifi', name: 'Poor WiFi' }
],
orientation: 'vertical'
});
});
// Virtual platform section
const platformSection = form.addSubform('platformSection', {
title: 'The Platform',
isVisible: () => eventFormat() === 'virtual' || eventFormat() === 'hybrid',
customStyles: {
backgroundColor: '#eff6ff',
padding: '16px',
borderRadius: '12px'
}
});
platformSection.addRow(row => {
row.addStarRating('platformRating', {
label: 'Rate the virtual experience:',
maxStars: 5,
size: 'md',
alignment: 'center'
});
});
platformSection.addRow(row => {
row.addMatrixQuestion('platformAspects', {
label: 'Rate these aspects:',
rows: [
{ id: 'video', label: 'Video quality' },
{ id: 'audio', label: 'Audio quality' },
{ id: 'chat', label: 'Chat/Q&A functionality' },
{ id: 'ease', label: 'Ease of joining' }
],
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'ok', label: 'OK' },
{ id: 'good', label: 'Good' }
]
});
});
// ============================================
// SECTION 6: FUTURE EVENTS
// ============================================
const futureSection = form.addSubform('futureSection', {
title: 'Looking Ahead',
isVisible: () => {
const format = eventFormat();
if (format === 'in-person') return venueSection.starRating('venueRating')?.value() !== null;
if (format === 'virtual') return platformSection.starRating('platformRating')?.value() !== null;
return (venueSection.starRating('venueRating')?.value() !== null) || (platformSection.starRating('platformRating')?.value() !== null);
}
});
futureSection.addRow(row => {
row.addThumbRating('willReturn', {
label: 'Will you come to the next meetup?',
showLabels: true,
upLabel: "I'll be there!",
downLabel: 'Probably not',
alignment: 'center',
size: 'lg'
});
});
futureSection.addRow(row => {
row.addRadioButton('preferredFormat', {
label: 'What format do you prefer for future events?',
options: [
{ id: 'in-person', name: 'In-person only' },
{ id: 'virtual', name: 'Virtual only' },
{ id: 'hybrid', name: 'Hybrid (both options)' },
{ id: 'either', name: 'Either works for me' }
],
orientation: 'vertical'
});
});
futureSection.addRow(row => {
row.addCheckboxList('wantMore', {
label: 'What would you like more of?',
options: [
{ id: 'talks', name: 'More technical talks' },
{ id: 'workshops', name: 'Hands-on workshops' },
{ id: 'networking', name: 'Networking time' },
{ id: 'lightning', name: 'Lightning talks' },
{ id: 'panel', name: 'Panel discussions' },
{ id: 'social', name: 'Social events' }
],
orientation: 'vertical',
max: 3
});
});
// ============================================
// SECTION 7: FINAL THOUGHTS
// ============================================
const finalSection = form.addSubform('finalSection', {
title: 'Final Thoughts',
isVisible: () => futureSection.thumbRating('willReturn')?.value() !== null
});
finalSection.addRow(row => {
row.addThumbRating('wouldRecommend', {
label: 'Would you recommend this meetup to a friend?',
showLabels: true,
upLabel: 'Definitely!',
downLabel: 'Probably not',
alignment: 'center',
size: 'lg'
});
});
finalSection.addSpacer({ height: '16px' });
finalSection.addRow(row => {
row.addTextarea('anythingElse', {
label: () => {
const vibe = overallVibe();
if (vibe === 'excited' || vibe === 'happy') return 'What made it great? Any shoutouts?';
if (vibe === 'sad' || vibe === 'down') return 'How can we do better next time?';
return 'Anything else you want to share?';
},
placeholder: "We read every response! Don't hold back...",
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 8: FUN SUMMARY
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Your Meetup Report Card',
isVisible: () => finalSection.thumbRating('wouldRecommend')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryPanel', {
computedValue: () => {
const vibe = overallVibe();
const talkRating = talksSection.starRating('talkQuality')?.value();
const metPeople = networkingSection.thumbRating('metNewPeople')?.value();
const willReturn = futureSection.thumbRating('willReturn')?.value();
const wouldRecommend = finalSection.thumbRating('wouldRecommend')?.value();
const vibeEmojis: Record<string, string> = {
'sad': '😢', 'down': '😔', 'neutral': '😐', 'happy': '😊', 'excited': '🤩'
};
let emoji = '🎉';
if (vibe === 'sad' || vibe === 'down') emoji = '💔';
else if (wouldRecommend === 'up' && willReturn === 'up') emoji = '🚀';
let summary = `${emoji} Meetup Report Card\n`;
summary += `${'═'.repeat(25)}\n\n`;
summary += `Vibe: ${vibe ? vibeEmojis[vibe] || vibe : 'N/A'}\n`;
summary += `Talks: ${talkRating ? '⭐'.repeat(talkRating) : 'N/A'}\n`;
summary += `Met cool people: ${metPeople === 'up' ? '✅' : metPeople === 'down' ? '❌' : 'N/A'}\n`;
summary += `Coming back: ${willReturn === 'up' ? '✅ Yes!' : willReturn === 'down' ? '❌ Nope' : 'N/A'}\n`;
summary += `Would recommend: ${wouldRecommend === 'up' ? '✅ Totally' : wouldRecommend === 'down' ? '❌ Nah' : 'N/A'}`;
return summary;
},
customStyles: () => {
const wouldRecommend = finalSection.thumbRating('wouldRecommend')?.value();
const baseStyles = {
padding: '20px',
borderRadius: '12px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (wouldRecommend === 'up') {
return { ...baseStyles, background: 'linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%)', borderLeft: '4px solid #22c55e' };
}
if (wouldRecommend === 'down') {
return { ...baseStyles, background: 'linear-gradient(135deg, #fef3c7 0%, #fde68a 100%)', borderLeft: '4px solid #f59e0b' };
}
return { ...baseStyles, background: '#f5f3ff', borderLeft: '4px solid #8b5cf6' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const wouldRecommend = finalSection.thumbRating('wouldRecommend')?.value();
if (wouldRecommend === 'up') return 'Submit & See You Next Time!';
return 'Submit Feedback';
},
isVisible: () => finalSection.thumbRating('wouldRecommend')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: () => {
const wouldRecommend = finalSection.thumbRating('wouldRecommend')?.value();
if (wouldRecommend === 'up') return 'Thanks! See You at the Next One!';
return 'Thanks for Your Feedback!';
},
message: () => {
const wouldRecommend = finalSection.thumbRating('wouldRecommend')?.value();
if (wouldRecommend === 'up') {
return "We're so glad you enjoyed it! Keep an eye on our channels for the next meetup announcement.";
}
return 'Your feedback helps us build a better community. We hope to see you at a future event!';
}
});
}