export function themeParkFeedback(form: FormTs) {
// Theme Park Experience Survey - Multi-page wizard with comprehensive feedback
// Demonstrates: Pages, StarRating, EmojiRating, MatrixQuestion, Slider, CheckboxList, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Theme Park Experience Survey',
computedValue: () => 'Tell us about your magical day! Your feedback helps us create even better experiences.',
customStyles: {
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
padding: '28px',
borderRadius: '16px',
textAlign: 'center',
fontSize: '15px'
}
});
});
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('surveyPages', { heightMode: 'current-page' });
// ============================================
// PAGE 1: Visit Overview
// ============================================
const page1 = pages.addPage('visitOverview');
page1.addRow(row => {
row.addTextPanel('page1Title', {
label: 'Your Visit',
customStyles: {
fontSize: '20px',
fontWeight: 'bold',
color: '#4c1d95',
marginBottom: '8px'
}
});
});
// Visit date and party size
page1.addRow(row => {
row.addDatepicker('visitDate', {
label: 'When did you visit?',
isRequired: true,
maxDate: () => new Date().toISOString().split('T')[0]
}, '1fr');
row.addDropdown('partySize', {
label: 'How many people in your group?',
options: [
{ id: '1', name: 'Just me' },
{ id: '2', name: '2 people' },
{ id: '3-4', name: '3-4 people' },
{ id: '5-6', name: '5-6 people' },
{ id: '7+', name: '7 or more' }
],
isRequired: true
}, '1fr');
});
// Visitor type
page1.addRow(row => {
row.addRadioButton('visitorType', {
label: 'What type of visitor are you?',
options: [
{ id: 'first-time', name: 'First-time visitor' },
{ id: 'occasional', name: 'Occasional visitor (1-2 times/year)' },
{ id: 'regular', name: 'Regular visitor (3+ times/year)' },
{ id: 'season-pass', name: 'Season pass holder' }
],
orientation: 'vertical'
});
});
// Overall first impression
page1.addRow(row => {
row.addEmojiRating('firstImpression', {
label: 'What was your first impression when you arrived?',
preset: 'satisfaction',
size: 'lg',
alignment: 'center'
});
});
// Navigation to page 2
page1.addSpacer({ height: '20px' });
page1.addRow(row => {
row.addButton('toPage2', {
label: 'Next: Rate Attractions',
onClick: () => pages.goToPage('attractions')
});
});
// ============================================
// PAGE 2: Attractions & Rides
// ============================================
const page2 = pages.addPage('attractions');
page2.addRow(row => {
row.addTextPanel('page2Title', {
label: 'Attractions & Rides',
customStyles: {
fontSize: '20px',
fontWeight: 'bold',
color: '#4c1d95',
marginBottom: '8px'
}
});
});
// Wait time satisfaction
page2.addRow(row => {
row.addSlider('avgWaitTime', {
label: 'What was the average wait time you experienced? (minutes)',
min: 0,
max: 120,
step: 5,
defaultValue: 30,
unit: 'min',
showValue: true
});
});
page2.addRow(row => {
row.addRatingScale('waitTimeSatisfaction', {
label: () => {
const wait = page2.slider('avgWaitTime')?.value() ?? 30;
if (wait <= 15) return 'How satisfied were you with the short wait times?';
if (wait <= 45) return 'How satisfied were you with the wait times?';
return 'The waits were long. How did that affect your experience?';
},
preset: 'satisfaction',
alignment: 'center'
});
});
// Attraction ratings matrix
page2.addSpacer({ height: '16px' });
page2.addRow(row => {
row.addMatrixQuestion('attractionRatings', {
label: 'Rate the attractions you experienced',
rows: [
{ id: 'roller-coasters', label: 'Roller Coasters', isRequired: false },
{ id: 'family-rides', label: 'Family Rides', isRequired: false },
{ id: 'water-attractions', label: 'Water Attractions', isRequired: false },
{ id: 'shows', label: 'Shows & Entertainment', isRequired: false },
{ id: 'themed-areas', label: 'Themed Areas/Lands', isRequired: false }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Great' },
{ id: '5', label: 'Amazing' }
],
fullWidth: true
});
});
// Favorite attraction
page2.addSpacer({ height: '16px' });
page2.addRow(row => {
row.addTextbox('favoriteAttraction', {
label: 'What was your favorite attraction and why?',
placeholder: 'Tell us about your favorite ride or show...',
maxLength: 200
});
});
// Navigation
page2.addSpacer({ height: '20px' });
page2.addRow(row => {
row.addButton('backToPage1', {
label: 'Back',
onClick: () => pages.goToPage('visitOverview')
}, '1fr');
row.addButton('toPage3', {
label: 'Next: Food & Dining',
onClick: () => pages.goToPage('dining')
}, '1fr');
});
// ============================================
// PAGE 3: Food & Dining
// ============================================
const page3 = pages.addPage('dining');
page3.addRow(row => {
row.addTextPanel('page3Title', {
label: 'Food & Dining',
customStyles: {
fontSize: '20px',
fontWeight: 'bold',
color: '#4c1d95',
marginBottom: '8px'
}
});
});
// Did they eat at the park?
page3.addRow(row => {
row.addRadioButton('didDine', {
label: 'Did you eat at the park?',
options: [
{ id: 'yes', name: 'Yes, we ate at the park' },
{ id: 'snacks', name: 'Just snacks and drinks' },
{ id: 'no', name: 'No, we brought our own food' }
],
orientation: 'vertical'
});
});
// Dining ratings (conditional)
const diningSection = page3.addSubform('diningRatings', {
title: 'Rate Your Dining Experience',
isVisible: () => {
const didDine = page3.radioButton('didDine')?.value();
return didDine === 'yes' || didDine === 'snacks';
}
});
diningSection.addRow(row => {
row.addStarRating('foodQuality', {
label: 'Food Quality',
maxStars: 5,
size: 'md'
}, '1fr');
row.addStarRating('foodVariety', {
label: 'Menu Variety',
maxStars: 5,
size: 'md'
}, '1fr');
});
diningSection.addRow(row => {
row.addStarRating('foodValue', {
label: 'Value for Money',
maxStars: 5,
size: 'md'
}, '1fr');
row.addStarRating('foodService', {
label: 'Service Speed',
maxStars: 5,
size: 'md'
}, '1fr');
});
// Dietary options
diningSection.addRow(row => {
row.addCheckboxList('dietaryNeeds', {
label: 'Were the following dietary options available?',
options: [
{ id: 'vegetarian', name: 'Vegetarian' },
{ id: 'vegan', name: 'Vegan' },
{ id: 'gluten-free', name: 'Gluten-Free' },
{ id: 'allergen-info', name: 'Allergen Information' }
],
orientation: 'horizontal'
});
});
// Navigation
page3.addSpacer({ height: '20px' });
page3.addRow(row => {
row.addButton('backToPage2', {
label: 'Back',
onClick: () => pages.goToPage('attractions')
}, '1fr');
row.addButton('toPage4', {
label: 'Next: Staff & Facilities',
onClick: () => pages.goToPage('staff')
}, '1fr');
});
// ============================================
// PAGE 4: Staff & Facilities
// ============================================
const page4 = pages.addPage('staff');
page4.addRow(row => {
row.addTextPanel('page4Title', {
label: 'Staff & Facilities',
customStyles: {
fontSize: '20px',
fontWeight: 'bold',
color: '#4c1d95',
marginBottom: '8px'
}
});
});
// Staff ratings
page4.addRow(row => {
row.addMatrixQuestion('staffRatings', {
label: 'Rate our team members',
rows: [
{ id: 'friendliness', label: 'Friendliness', isRequired: true },
{ id: 'helpfulness', label: 'Helpfulness', isRequired: true },
{ id: 'knowledge', label: 'Knowledge', isRequired: false },
{ id: 'appearance', label: 'Professional Appearance', isRequired: false }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Great' },
{ id: '5', label: 'Excellent' }
],
fullWidth: true
});
});
// Facilities
page4.addSpacer({ height: '16px' });
page4.addRow(row => {
row.addStarRating('cleanliness', {
label: 'Park Cleanliness',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
page4.addRow(row => {
row.addStarRating('restrooms', {
label: 'Restroom Cleanliness',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
// Safety perception
page4.addRow(row => {
row.addThumbRating('feltSafe', {
label: 'Did you feel safe throughout your visit?',
showLabels: true,
upLabel: 'Yes, very safe',
downLabel: 'Had concerns',
alignment: 'center'
});
});
// Safety concerns (conditional)
page4.addRow(row => {
row.addTextarea('safetyConcerns', {
label: 'Please describe your safety concerns',
placeholder: 'What made you feel unsafe?',
rows: 3,
isVisible: () => page4.thumbRating('feltSafe')?.value() === 'down',
isRequired: () => page4.thumbRating('feltSafe')?.value() === 'down'
});
});
// Navigation
page4.addSpacer({ height: '20px' });
page4.addRow(row => {
row.addButton('backToPage3', {
label: 'Back',
onClick: () => pages.goToPage('dining')
}, '1fr');
row.addButton('toPage5', {
label: 'Next: Overall Experience',
onClick: () => pages.goToPage('overall')
}, '1fr');
});
// ============================================
// PAGE 5: Overall Experience
// ============================================
const page5 = pages.addPage('overall');
page5.addRow(row => {
row.addTextPanel('page5Title', {
label: 'Overall Experience',
customStyles: {
fontSize: '20px',
fontWeight: 'bold',
color: '#4c1d95',
marginBottom: '8px'
}
});
});
// Overall rating
page5.addRow(row => {
row.addRatingScale('npsScore', {
label: 'How likely are you to recommend our park to friends and family?',
preset: 'nps',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
// Value rating
page5.addRow(row => {
row.addStarRating('valueForMoney', {
label: 'Value for Money',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
// Would visit again
page5.addRow(row => {
row.addRadioButton('wouldReturn', {
label: 'Would you visit again?',
options: [
{ id: 'definitely', name: 'Definitely yes!' },
{ id: 'probably', name: 'Probably' },
{ id: 'maybe', name: 'Maybe' },
{ id: 'unlikely', name: 'Unlikely' },
{ id: 'no', name: 'No' }
],
orientation: 'horizontal'
});
});
// What could be improved (for lower scores)
const improvementsSection = page5.addSubform('improvements', {
title: 'Help Us Improve',
isVisible: () => {
const nps = page5.ratingScale('npsScore')?.value();
return nps !== null && nps !== undefined && nps <= 6;
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
improvementsSection.addRow(row => {
row.addSuggestionChips('improvementAreas', {
label: 'What areas need the most improvement?',
suggestions: [
{ id: 'wait-times', name: 'Wait Times' },
{ id: 'ride-variety', name: 'Ride Variety' },
{ id: 'food-quality', name: 'Food Quality' },
{ id: 'food-prices', name: 'Food Prices' },
{ id: 'cleanliness', name: 'Cleanliness' },
{ id: 'staff', name: 'Staff Service' },
{ id: 'ticket-price', name: 'Ticket Price' },
{ id: 'parking', name: 'Parking' }
],
max: 3,
alignment: 'center'
});
});
// Best moments (for higher scores)
const highlightsSection = page5.addSubform('highlights', {
title: 'Share Your Magical Moments',
isVisible: () => {
const nps = page5.ratingScale('npsScore')?.value();
return nps !== null && nps !== undefined && nps >= 7;
},
customStyles: { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' }
});
highlightsSection.addRow(row => {
row.addSuggestionChips('highlights', {
label: 'What made your visit special?',
suggestions: [
{ id: 'rides', name: 'Thrilling Rides' },
{ id: 'shows', name: 'Amazing Shows' },
{ id: 'atmosphere', name: 'Magical Atmosphere' },
{ id: 'staff', name: 'Friendly Staff' },
{ id: 'food', name: 'Great Food' },
{ id: 'theming', name: 'Immersive Theming' },
{ id: 'family-time', name: 'Family Time' },
{ id: 'memories', name: 'Making Memories' }
],
max: 4,
alignment: 'center'
});
});
// Additional comments
page5.addSpacer({ height: '16px' });
page5.addRow(row => {
row.addTextarea('additionalComments', {
label: () => {
const nps = page5.ratingScale('npsScore')?.value();
if (nps !== null && nps !== undefined && nps >= 9) {
return 'Any magical moments you want to share?';
}
return 'Any additional comments or suggestions?';
},
placeholder: 'Share your thoughts...',
rows: 3,
autoExpand: true
});
});
// Contact section
const contactSection = page5.addSubform('contact', {
title: 'Stay Connected'
});
contactSection.addRow(row => {
row.addCheckbox('allowContact', {
label: 'I would like to receive updates about special events and promotions'
});
});
contactSection.addRow(row => {
row.addEmail('email', {
label: 'Email address',
placeholder: 'your@email.com',
isVisible: () => contactSection.checkbox('allowContact')?.value() === true,
isRequired: () => contactSection.checkbox('allowContact')?.value() === true
});
});
// Summary
const summarySection = page5.addSubform('summary', {
title: 'Your Feedback Summary',
isVisible: () => page5.ratingScale('npsScore')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const nps = page5.ratingScale('npsScore')?.value();
const category = page5.ratingScale('npsScore')?.npsCategory();
const wouldReturn = page5.radioButton('wouldReturn')?.value();
const valueRating = page5.starRating('valueForMoney')?.value();
if (nps === null || nps === undefined) return '';
let emoji = category === 'promoter' ? '🎢' : category === 'passive' ? '🎡' : '🎠';
let summary = `${emoji} Visit Summary\n`;
summary += `${'═'.repeat(25)}\n\n`;
summary += `Recommendation Score: ${nps}/10\n`;
if (valueRating) {
summary += `Value Rating: ${'★'.repeat(valueRating)}${'☆'.repeat(5 - valueRating)}\n`;
}
if (wouldReturn) {
const returnLabels: Record<string, string> = {
'definitely': 'Will definitely return!',
'probably': 'Likely to return',
'maybe': 'Might return',
'unlikely': 'Unlikely to return',
'no': 'Will not return'
};
summary += `\n${returnLabels[wouldReturn] || wouldReturn}`;
}
return summary;
},
customStyles: () => {
const category = page5.ratingScale('npsScore')?.npsCategory();
const base = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') return { ...base, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
if (category === 'passive') return { ...base, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
return { ...base, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// Back button
page5.addSpacer({ height: '20px' });
page5.addRow(row => {
row.addButton('backToPage4', {
label: 'Back',
onClick: () => pages.goToPage('staff')
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => page5.ratingScale('npsScore')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your input helps us create more magical experiences. We hope to welcome you back soon for another adventure!'
});
}