export function airportExperience(form: FormTs) {
// Airport Experience Survey - Comprehensive passenger journey feedback
// Demonstrates: MatrixQuestion, StarRating, EmojiRating, RatingScale, Slider, Dropdown, conditional visibility
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: '✈️ Airport Experience Survey',
computedValue: () => 'Help us improve your journey. Share your experience at our airport today.',
customStyles: {
background: 'linear-gradient(135deg, #0369a1 0%, #0ea5e9 100%)',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Trip Context
// ============================================
const tripSection = form.addSubform('trip', {
title: 'Your Trip Details'
});
tripSection.addRow(row => {
row.addRadioButton('tripPurpose', {
label: 'What is the purpose of your trip?',
options: [
{ id: 'business', name: 'Business' },
{ id: 'leisure', name: 'Leisure / Vacation' },
{ id: 'visiting', name: 'Visiting family/friends' },
{ id: 'other', name: 'Other' }
],
orientation: 'horizontal',
isRequired: true
});
});
tripSection.addRow(row => {
row.addRadioButton('passengerType', {
label: 'How did you use this airport today?',
options: [
{ id: 'departing', name: 'Departing (starting journey here)' },
{ id: 'arriving', name: 'Arriving (ending journey here)' },
{ id: 'connecting', name: 'Connecting (between flights)' }
],
orientation: 'vertical',
isRequired: true
});
});
tripSection.addRow(row => {
row.addDropdown('terminal', {
label: 'Which terminal(s) did you use?',
options: [
{ id: 'T1', name: 'Terminal 1' },
{ id: 'T2', name: 'Terminal 2' },
{ id: 'T3', name: 'Terminal 3 (International)' },
{ id: 'multiple', name: 'Multiple terminals' }
],
isRequired: true
}, '1fr');
row.addDropdown('frequency', {
label: 'How often do you travel through this airport?',
options: [
{ id: 'first', name: 'First time' },
{ id: 'occasional', name: 'Occasionally (1-2x/year)' },
{ id: 'frequent', name: 'Frequently (3-10x/year)' },
{ id: 'very-frequent', name: 'Very frequent (10+/year)' }
]
}, '1fr');
});
// ============================================
// SECTION 2: Check-in & Arrival (for departing passengers)
// ============================================
const checkinSection = form.addSubform('checkin', {
title: 'Check-in Experience',
isVisible: () => {
const type = tripSection.radioButton('passengerType')?.value();
return type === 'departing';
}
});
checkinSection.addRow(row => {
row.addRadioButton('checkinMethod', {
label: 'How did you check in?',
options: [
{ id: 'online', name: 'Online / Mobile' },
{ id: 'kiosk', name: 'Airport kiosk' },
{ id: 'counter', name: 'Airline counter' },
{ id: 'curbside', name: 'Curbside check-in' }
],
orientation: 'horizontal'
});
});
checkinSection.addRow(row => {
row.addStarRating('checkinRating', {
label: 'Rate your check-in experience',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
checkinSection.addRow(row => {
row.addSlider('checkinWait', {
label: 'Approximate wait time at check-in (minutes)',
min: 0,
max: 60,
step: 5,
defaultValue: 10,
showValue: true,
unit: ' min',
isVisible: () => {
const method = checkinSection.radioButton('checkinMethod')?.value();
return method === 'counter' || method === 'kiosk';
}
});
});
// ============================================
// SECTION 3: Security Screening
// ============================================
const securitySection = form.addSubform('security', {
title: 'Security Screening',
isVisible: () => {
const type = tripSection.radioButton('passengerType')?.value();
return type === 'departing' || type === 'connecting';
}
});
securitySection.addRow(row => {
row.addSlider('securityWait', {
label: 'Estimated wait time at security (minutes)',
min: 0,
max: 60,
step: 5,
defaultValue: 15,
showValue: true,
unit: ' min'
});
});
securitySection.addRow(row => {
row.addMatrixQuestion('securityRatings', {
label: 'Rate your security experience:',
rows: [
{ id: 'efficiency', label: 'Process efficiency', description: 'Queue management and throughput', isRequired: true },
{ id: 'staff', label: 'Staff professionalism', description: 'Courtesy and helpfulness', isRequired: true },
{ id: 'signage', label: 'Clear instructions', description: 'Signs, announcements, guidance', isRequired: true },
{ id: 'bins', label: 'Bin/tray availability', description: 'Equipment ready and clean' }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 4: Airport Facilities
// ============================================
const facilitiesSection = form.addSubform('facilities', {
title: 'Airport Facilities'
});
facilitiesSection.addRow(row => {
row.addMatrixQuestion('facilityRatings', {
label: 'Please rate the following facilities:',
rows: [
{ id: 'cleanliness', label: 'Cleanliness', description: 'Floors, seating, common areas', isRequired: true },
{ id: 'restrooms', label: 'Restrooms', description: 'Availability, cleanliness, supplies', isRequired: true },
{ id: 'seating', label: 'Seating areas', description: 'Availability and comfort', isRequired: true },
{ id: 'wifi', label: 'WiFi quality', description: 'Speed and reliability' },
{ id: 'charging', label: 'Charging stations', description: 'Availability of power outlets' },
{ id: 'wayfinding', label: 'Navigation/Signage', description: 'Ease of finding your way', isRequired: true }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 5: Dining & Retail
// ============================================
const diningSection = form.addSubform('dining', {
title: 'Dining & Shopping'
});
diningSection.addRow(row => {
row.addCheckboxList('usedServices', {
label: 'Which services did you use? (Select all that apply)',
options: [
{ id: 'restaurant', name: 'Restaurant / Sit-down dining' },
{ id: 'fastfood', name: 'Fast food / Quick service' },
{ id: 'coffee', name: 'Coffee shop / Café' },
{ id: 'bar', name: 'Bar / Lounge' },
{ id: 'retail', name: 'Retail shopping' },
{ id: 'dutyfree', name: 'Duty-free' },
{ id: 'none', name: 'Did not use any' }
],
orientation: 'vertical'
});
});
diningSection.addRow(row => {
row.addStarRating('diningQuality', {
label: 'Overall quality of food options',
maxStars: 5,
size: 'md',
alignment: 'left',
isVisible: () => {
const services = diningSection.checkboxList('usedServices')?.value() || [];
return services.includes('restaurant') || services.includes('fastfood') || services.includes('coffee');
}
}, '1fr');
row.addStarRating('diningValue', {
label: 'Value for money',
maxStars: 5,
size: 'md',
alignment: 'left',
isVisible: () => {
const services = diningSection.checkboxList('usedServices')?.value() || [];
return services.includes('restaurant') || services.includes('fastfood') || services.includes('coffee');
}
}, '1fr');
});
diningSection.addRow(row => {
row.addStarRating('shoppingVariety', {
label: 'Variety of shops',
maxStars: 5,
size: 'md',
alignment: 'left',
isVisible: () => {
const services = diningSection.checkboxList('usedServices')?.value() || [];
return services.includes('retail') || services.includes('dutyfree');
}
}, '1fr');
row.addStarRating('shoppingPrices', {
label: 'Prices / Value',
maxStars: 5,
size: 'md',
alignment: 'left',
isVisible: () => {
const services = diningSection.checkboxList('usedServices')?.value() || [];
return services.includes('retail') || services.includes('dutyfree');
}
}, '1fr');
});
// ============================================
// SECTION 6: Gate Experience
// ============================================
const gateSection = form.addSubform('gate', {
title: 'Gate Area Experience',
isVisible: () => {
const type = tripSection.radioButton('passengerType')?.value();
return type === 'departing' || type === 'connecting';
}
});
gateSection.addRow(row => {
row.addMatrixQuestion('gateRatings', {
label: 'Rate your gate area experience:',
rows: [
{ id: 'seating', label: 'Seating availability', isRequired: true },
{ id: 'info', label: 'Flight information displays' },
{ id: 'announcements', label: 'Boarding announcements clarity' },
{ id: 'boarding', label: 'Boarding process organization' }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 7: Overall Satisfaction
// ============================================
const overallSection = form.addSubform('overall', {
title: 'Overall Experience'
});
overallSection.addRow(row => {
row.addEmojiRating('overallExperience', {
label: 'How would you rate your overall airport experience?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
overallSection.addRow(row => {
row.addRatingScale('npsScore', {
label: 'How likely are you to recommend this airport to other travelers?',
preset: 'nps',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true
});
});
overallSection.addRow(row => {
row.addRatingScale('returnLikelihood', {
label: 'How likely are you to choose this airport for future travel?',
preset: 'likert-5',
lowLabel: 'Very unlikely',
highLabel: 'Very likely',
size: 'md',
alignment: 'center'
});
});
// ============================================
// SECTION 8: Improvement Suggestions
// ============================================
const suggestionsSection = form.addSubform('suggestions', {
title: 'Help Us Improve'
});
suggestionsSection.addRow(row => {
row.addSuggestionChips('improvementPriorities', {
label: 'What should we prioritize improving? (Select up to 3)',
suggestions: [
{ id: 'wait-times', name: 'Reduce wait times' },
{ id: 'cleanliness', name: 'Cleanliness' },
{ id: 'wifi', name: 'Better WiFi' },
{ id: 'seating', name: 'More seating' },
{ id: 'food-options', name: 'Food options' },
{ id: 'prices', name: 'Lower prices' },
{ id: 'signage', name: 'Better signage' },
{ id: 'charging', name: 'More charging stations' },
{ id: 'staff', name: 'Staff friendliness' },
{ id: 'accessibility', name: 'Accessibility' }
],
max: 3,
alignment: 'center'
});
});
suggestionsSection.addSpacer();
suggestionsSection.addRow(row => {
row.addTextarea('comments', {
label: 'Any additional comments or suggestions?',
placeholder: 'Share any specific feedback about your experience today...',
rows: 4,
autoExpand: true
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => overallSection.emojiRating('overallExperience')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const purpose = tripSection.radioButton('tripPurpose')?.value();
const type = tripSection.radioButton('passengerType')?.value();
const terminal = tripSection.dropdown('terminal')?.value();
const experience = overallSection.emojiRating('overallExperience')?.value();
const nps = overallSection.ratingScale('npsScore')?.value();
const priorities = suggestionsSection.suggestionChips('improvementPriorities')?.value() || [];
const purposeLabels: Record<string, string> = {
'business': 'Business',
'leisure': 'Leisure',
'visiting': 'Personal',
'other': 'Other'
};
const typeLabels: Record<string, string> = {
'departing': 'Departing',
'arriving': 'Arriving',
'connecting': 'Connecting'
};
const experienceLabels: Record<string, string> = {
'very-bad': '😢 Very Poor',
'bad': '😕 Below Average',
'neutral': '😐 Average',
'good': '😊 Good',
'excellent': '😃 Excellent'
};
let summary = `✈️ Airport Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
summary += `👤 Traveler: ${purposeLabels[purpose || ''] || 'Unknown'} - ${typeLabels[type || ''] || 'Unknown'}\n`;
summary += `🏢 Terminal: ${terminal || 'Not specified'}\n`;
if (experience) {
summary += `\n${experienceLabels[experience]}`;
}
if (nps !== null && nps !== undefined) {
summary += `\n📊 NPS: ${nps}/10`;
}
if (priorities.length > 0) {
summary += `\n\n🎯 Top priorities: ${priorities.length} selected`;
}
return summary;
},
customStyles: () => {
const experience = overallSection.emojiRating('overallExperience')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (experience === 'excellent' || experience === 'good') {
return { ...baseStyles, backgroundColor: '#dcfce7', borderLeft: '4px solid #22c55e' };
} else if (experience === 'very-bad' || experience === 'bad') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#f0f9ff', borderLeft: '4px solid #0ea5e9' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Airport Feedback'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Flying With Us!',
message: 'Your feedback helps us improve the travel experience for millions of passengers. Safe travels!'
});
}