export function fanGameDaySurvey(form: FormTs) {
// Game Day Fan Experience Survey
// Demonstrates: StarRating, EmojiRating, MatrixQuestion, Slider, SuggestionChips, ThumbRating, dynamic styling
// ============================================
// STATE
// ============================================
const purchasedFood = form.state(false);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Game Day Experience Survey',
computedValue: () => 'Help us make every game day unforgettable! Share your experience.',
customStyles: {
backgroundColor: '#dc2626',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Game & Attendance Info
// ============================================
const gameSection = form.addSubform('game', {
title: 'About Your Visit'
});
gameSection.addRow(row => {
row.addDatepicker('gameDate', {
label: 'Date of the game',
maxDate: () => new Date().toISOString(),
isRequired: true
}, '1fr');
row.addDropdown('opponent', {
label: 'Opponent team',
options: [
{ id: 'team-a', name: 'City Eagles' },
{ id: 'team-b', name: 'Northern Stars' },
{ id: 'team-c', name: 'Metro United' },
{ id: 'team-d', name: 'Coastal FC' },
{ id: 'team-e', name: 'Mountain Lions' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select opponent...'
}, '1fr');
});
gameSection.addRow(row => {
row.addDropdown('seatingArea', {
label: 'Where were your seats?',
options: [
{ id: 'vip', name: 'VIP/Suite' },
{ id: 'club', name: 'Club Level' },
{ id: 'lower', name: 'Lower Bowl' },
{ id: 'upper', name: 'Upper Deck' },
{ id: 'standing', name: 'Standing/GA' },
{ id: 'fan-zone', name: 'Fan Zone' }
],
isRequired: true
}, '1fr');
row.addDropdown('ticketType', {
label: 'Ticket type',
options: [
{ id: 'season', name: 'Season ticket holder' },
{ id: 'single', name: 'Single game purchase' },
{ id: 'group', name: 'Group/corporate' },
{ id: 'comp', name: 'Complimentary' },
{ id: 'resale', name: 'Resale/secondary market' }
]
}, '1fr');
});
gameSection.addRow(row => {
row.addDropdown('attendedWith', {
label: 'Who did you attend with?',
options: [
{ id: 'alone', name: 'Alone' },
{ id: 'partner', name: 'Partner/spouse' },
{ id: 'family', name: 'Family with kids' },
{ id: 'friends', name: 'Friends' },
{ id: 'coworkers', name: 'Coworkers/business' }
]
}, '1fr');
row.addInteger('groupSize', {
label: 'Total people in your group',
min: 1,
max: 20,
defaultValue: 2
}, '1fr');
});
// ============================================
// SECTION 2: Overall Experience & Atmosphere
// ============================================
const atmosphereSection = form.addSubform('atmosphere', {
title: 'Game Day Atmosphere',
isVisible: () => gameSection.dropdown('seatingArea')?.value() !== null,
customStyles: () => {
const rating = atmosphereSection.emojiRating('overallMood')?.value();
if (rating === 'excellent' || rating === 'good') {
return { backgroundColor: '#fef2f2', padding: '16px', borderRadius: '8px' };
}
return { padding: '16px', borderRadius: '8px', border: '1px dashed #e5e7eb' };
}
});
atmosphereSection.addRow(row => {
row.addEmojiRating('overallMood', {
label: 'How would you rate the overall game day atmosphere?',
preset: 'satisfaction',
size: 'lg',
alignment: 'center'
});
});
atmosphereSection.addRow(row => {
row.addStarRating('crowdEnergy', {
label: 'Crowd energy & engagement',
maxStars: 5,
size: 'lg',
alignment: 'center',
showCounter: true
}, '1fr');
row.addStarRating('entertainment', {
label: 'Entertainment & activities',
maxStars: 5,
size: 'lg',
alignment: 'center',
showCounter: true
}, '1fr');
});
atmosphereSection.addRow(row => {
row.addSuggestionChips('bestMoments', {
label: 'What were the highlights? (Select all that apply)',
suggestions: [
{ id: 'game', name: 'The game itself' },
{ id: 'atmosphere', name: 'Electric atmosphere' },
{ id: 'halftime', name: 'Halftime show' },
{ id: 'music', name: 'Music & DJ' },
{ id: 'mascot', name: 'Mascot antics' },
{ id: 'fan-cam', name: 'Fan cam/jumbotron' },
{ id: 'giveaway', name: 'Giveaways/promotions' },
{ id: 'socializing', name: 'Time with friends/family' }
],
max: 4,
alignment: 'center'
});
});
// ============================================
// SECTION 3: Facilities & Seating
// ============================================
const facilitiesSection = form.addSubform('facilities', {
title: 'Stadium Facilities',
isVisible: () => atmosphereSection.emojiRating('overallMood')?.value() !== null
});
facilitiesSection.addRow(row => {
row.addMatrixQuestion('facilitiesRating', {
label: 'Rate the following stadium aspects:',
rows: [
{ id: 'seating', label: 'Seat comfort & view', isRequired: true },
{ id: 'cleanliness', label: 'Cleanliness overall', isRequired: true },
{ id: 'restrooms', label: 'Restroom facilities', isRequired: true },
{ id: 'signage', label: 'Signage & wayfinding', isRequired: false },
{ id: 'accessibility', label: 'Accessibility', isRequired: false },
{ id: 'wifi', label: 'WiFi / connectivity', isRequired: false }
],
columns: [
{ id: 'excellent', label: 'Excellent' },
{ id: 'good', label: 'Good' },
{ id: 'average', label: 'Average' },
{ id: 'poor', label: 'Poor' },
{ id: 'na', label: 'N/A' }
],
striped: true,
fullWidth: true
});
});
facilitiesSection.addRow(row => {
row.addSlider('entryTime', {
label: 'How long did it take to enter the stadium (in minutes)?',
min: 0,
max: 45,
step: 5,
defaultValue: 10,
showValue: true,
unit: ' min'
}, '1fr');
row.addSlider('exitTime', {
label: 'How long to exit after the game?',
min: 0,
max: 45,
step: 5,
defaultValue: 15,
showValue: true,
unit: ' min'
}, '1fr');
});
// ============================================
// SECTION 4: Food & Beverage
// ============================================
const foodSection = form.addSubform('food', {
title: 'Food & Beverage',
isVisible: () => facilitiesSection.matrixQuestion('facilitiesRating')?.areAllRequiredRowsAnswered() ?? false
});
foodSection.addRow(row => {
row.addRadioButton('purchasedFoodDrink', {
label: 'Did you purchase food or beverages at the stadium?',
options: [
{ id: 'yes', name: 'Yes' },
{ id: 'no', name: 'No' }
],
orientation: 'horizontal',
onValueChange: (val) => purchasedFood.set(val === 'yes')
});
});
foodSection.addRow(row => {
row.addStarRating('foodQuality', {
label: 'Food quality',
maxStars: 5,
size: 'md',
alignment: 'center',
isVisible: () => purchasedFood()
}, '1fr');
row.addStarRating('foodValue', {
label: 'Value for money',
maxStars: 5,
size: 'md',
alignment: 'center',
isVisible: () => purchasedFood()
}, '1fr');
row.addStarRating('serviceSpeed', {
label: 'Service speed',
maxStars: 5,
size: 'md',
alignment: 'center',
isVisible: () => purchasedFood()
}, '1fr');
});
foodSection.addRow(row => {
row.addCheckboxList('foodPurchased', {
label: 'What did you purchase?',
options: [
{ id: 'snacks', name: 'Snacks (popcorn, nachos, etc.)' },
{ id: 'hotdog', name: 'Hot dogs / burgers' },
{ id: 'specialty', name: 'Specialty food items' },
{ id: 'beer', name: 'Beer' },
{ id: 'cocktails', name: 'Cocktails/mixed drinks' },
{ id: 'soda', name: 'Soft drinks' },
{ id: 'water', name: 'Water' },
{ id: 'merchandise', name: 'Merchandise' }
],
orientation: 'vertical',
isVisible: () => purchasedFood()
});
});
foodSection.addRow(row => {
row.addTextarea('foodFeedback', {
label: 'Any suggestions for food & beverage?',
placeholder: 'Menu items you\'d like to see, service improvements...',
rows: 2,
isVisible: () => purchasedFood()
});
});
// ============================================
// SECTION 5: Staff & Safety
// ============================================
const staffSection = form.addSubform('staff', {
title: 'Staff & Safety',
isVisible: () => foodSection.radioButton('purchasedFoodDrink')?.value() !== null
});
staffSection.addRow(row => {
row.addStarRating('staffFriendliness', {
label: 'Staff friendliness',
maxStars: 5,
size: 'lg',
alignment: 'center',
showCounter: true
}, '1fr');
row.addStarRating('securityExperience', {
label: 'Security experience',
maxStars: 5,
size: 'lg',
alignment: 'center',
showCounter: true
}, '1fr');
});
staffSection.addRow(row => {
row.addRadioButton('safetyFeeling', {
label: 'Did you feel safe throughout your visit?',
options: [
{ id: 'very-safe', name: 'Very safe' },
{ id: 'safe', name: 'Safe' },
{ id: 'neutral', name: 'Neutral' },
{ id: 'unsafe', name: 'Somewhat unsafe' },
{ id: 'very-unsafe', name: 'Very unsafe' }
],
orientation: 'horizontal'
});
});
staffSection.addRow(row => {
row.addTextarea('safetyIssues', {
label: 'Please describe any safety concerns:',
placeholder: 'Help us address the issue...',
rows: 2,
isVisible: () => {
const feeling = staffSection.radioButton('safetyFeeling')?.value();
return feeling === 'unsafe' || feeling === 'very-unsafe';
}
});
});
// ============================================
// SECTION 6: Value & Loyalty
// ============================================
const valueSection = form.addSubform('value', {
title: 'Overall Value & Loyalty',
isVisible: () => staffSection.starRating('staffFriendliness')?.value() !== null
});
valueSection.addRow(row => {
row.addRatingScale('overallValue', {
preset: 'likert-5',
label: 'The game day experience was worth the cost',
lowLabel: 'Strongly disagree',
highLabel: 'Strongly agree',
alignment: 'center'
});
});
valueSection.addRow(row => {
row.addThumbRating('returnIntent', {
label: 'Will you attend another game this season?',
showLabels: true,
upLabel: 'Definitely!',
downLabel: 'Unlikely',
size: 'lg',
alignment: 'center'
});
});
valueSection.addRow(row => {
row.addRatingScale('recommendScore', {
preset: 'nps',
label: 'How likely are you to recommend attending a game to friends or family?',
showSegmentColors: true,
showCategoryLabel: true,
alignment: 'center'
});
});
// ============================================
// SECTION 7: Final Feedback
// ============================================
const finalSection = form.addSubform('final', {
title: 'Final Thoughts',
isVisible: () => valueSection.ratingScale('recommendScore')?.value() !== null
});
finalSection.addSpacer();
finalSection.addRow(row => {
row.addTextarea('bestPart', {
label: 'What was the best part of your game day experience?',
placeholder: 'Share what made the day special...',
rows: 3
});
});
finalSection.addRow(row => {
row.addTextarea('improvement', {
label: 'What one thing would most improve your experience?',
placeholder: 'Your top suggestion...',
rows: 3
});
});
finalSection.addRow(row => {
row.addCheckbox('contactForPrizes', {
label: 'Enter me in the monthly fan prize drawing'
});
});
finalSection.addRow(row => {
row.addEmail('email', {
label: 'Email address (for prize notification)',
placeholder: 'your@email.com',
isVisible: () => finalSection.checkbox('contactForPrizes')?.value() === true,
isRequired: () => finalSection.checkbox('contactForPrizes')?.value() === true
});
});
// ============================================
// SECTION 8: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Experience Summary',
isVisible: () => finalSection.checkbox('contactForPrizes')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const mood = atmosphereSection.emojiRating('overallMood')?.value();
const crowdEnergy = atmosphereSection.starRating('crowdEnergy')?.value();
const entertainment = atmosphereSection.starRating('entertainment')?.value();
const nps = valueSection.ratingScale('recommendScore')?.value();
const npsCategory = valueSection.ratingScale('recommendScore')?.npsCategory();
const returnIntent = valueSection.thumbRating('returnIntent')?.value();
const seating = gameSection.dropdown('seatingArea')?.value();
const seatLabels: Record<string, string> = {
'vip': 'VIP/Suite',
'club': 'Club Level',
'lower': 'Lower Bowl',
'upper': 'Upper Deck',
'standing': 'Standing/GA',
'fan-zone': 'Fan Zone'
};
const moodLabels: Record<string, string> = {
'very-bad': '😢 Very Disappointed',
'bad': '😕 Disappointed',
'neutral': '😐 Mixed Feelings',
'good': '😊 Good Time',
'excellent': '🤩 Amazing!'
};
let summary = `🏟️ Game Day Summary\n`;
summary += `${'═'.repeat(22)}\n\n`;
if (seating) {
summary += `🎫 Seating: ${seatLabels[seating] || seating}\n`;
}
if (mood) {
summary += `😊 Experience: ${moodLabels[mood]}\n`;
}
if (crowdEnergy) {
summary += `🔥 Crowd Energy: ${'⭐'.repeat(crowdEnergy)}\n`;
}
if (entertainment) {
summary += `🎉 Entertainment: ${'⭐'.repeat(entertainment)}\n`;
}
if (nps !== null && nps !== undefined) {
summary += `\n📊 NPS: ${nps}/10`;
if (npsCategory) {
summary += ` (${npsCategory.charAt(0).toUpperCase()}${npsCategory.slice(1)})`;
}
summary += '\n';
}
if (returnIntent) {
summary += `\n🔄 Will return: ${returnIntent === 'up' ? '✅ Yes!' : '❌ Unlikely'}`;
}
return summary;
},
customStyles: () => {
const mood = atmosphereSection.emojiRating('overallMood')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (mood === 'excellent' || mood === 'good') {
return { ...baseStyles, backgroundColor: '#fef2f2', borderLeft: '4px solid #dc2626' };
} else if (mood === 'neutral') {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
} else if (mood === 'bad' || mood === 'very-bad') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#f1f5f9' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Fan Feedback',
isVisible: () => gameSection.dropdown('seatingArea')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You, True Fan!',
message: 'Your feedback helps us create the best game day experience. See you at the next home game!'
});
}