export function sportsFacilitySurvey(form: FormTs) {
// Sports Facility Rating Form - Sports & Recreation Feedback
// Demonstrates: MatrixQuestion, StarRating, EmojiRating, CheckboxList, Slider, Datepicker, Timepicker, dynamic visibility
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Rate Your Facility Experience',
computedValue: () => 'Help us keep our facility in top shape. Your feedback drives improvements!',
customStyles: {
background: 'linear-gradient(135deg, #059669 0%, #10b981 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Visit Information
// ============================================
const visitSection = form.addSubform('visitSection', {
title: 'Your Visit',
customStyles: { backgroundColor: '#f0fdf4', padding: '16px', borderRadius: '8px' }
});
visitSection.addRow(row => {
row.addDatepicker('visitDate', {
label: 'Date of your visit',
maxDate: () => new Date().toISOString(),
isRequired: true
}, '1fr');
row.addTimepicker('visitTime', {
label: 'Approximate time',
isRequired: true
}, '1fr');
});
visitSection.addRow(row => {
row.addCheckboxList('areasUsed', {
label: 'Which areas did you use?',
options: [
{ id: 'cardio', name: 'Cardio area' },
{ id: 'weights', name: 'Weight room / Free weights' },
{ id: 'machines', name: 'Weight machines' },
{ id: 'pool', name: 'Swimming pool' },
{ id: 'courts', name: 'Courts (basketball, tennis, etc.)' },
{ id: 'group-fitness', name: 'Group fitness studios' },
{ id: 'locker-room', name: 'Locker rooms / Showers' },
{ id: 'track', name: 'Running track' },
{ id: 'spa', name: 'Spa / Sauna' }
],
orientation: 'vertical',
min: 1,
isRequired: true
});
});
// ============================================
// SECTION 2: Equipment Quality (MatrixQuestion)
// ============================================
const equipmentSection = form.addSubform('equipmentSection', {
title: 'Equipment Quality',
customStyles: { backgroundColor: '#f8fafc', padding: '16px', borderRadius: '8px' }
});
equipmentSection.addRow(row => {
row.addMatrixQuestion('equipmentMatrix', {
label: 'Please rate the equipment in areas you used:',
rows: [
{ id: 'condition', label: 'Equipment condition / maintenance', isRequired: true },
{ id: 'cleanliness', label: 'Equipment cleanliness' },
{ id: 'availability', label: 'Equipment availability (not busy)' },
{ id: 'variety', label: 'Variety of equipment' },
{ id: 'modern', label: 'Modern / up-to-date equipment' }
],
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'very-good', label: 'Very Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
equipmentSection.addSpacer({ height: '16px' });
equipmentSection.addRow(row => {
row.addThumbRating('equipmentIssues', {
label: 'Did you notice any broken or out-of-service equipment?',
showLabels: true,
upLabel: 'Yes, there were issues',
downLabel: 'No, everything worked',
alignment: 'center'
});
});
equipmentSection.addRow(row => {
row.addTextarea('equipmentProblems', {
label: 'Please describe the equipment issues',
placeholder: 'What equipment was broken or not working? Where was it located?',
rows: 2,
autoExpand: true,
isVisible: () => equipmentSection.thumbRating('equipmentIssues')?.value() === 'up',
isRequired: () => equipmentSection.thumbRating('equipmentIssues')?.value() === 'up'
});
});
// ============================================
// SECTION 3: Cleanliness & Environment
// ============================================
const cleanlinessSection = form.addSubform('cleanlinessSection', {
title: 'Cleanliness & Environment',
customStyles: () => {
const cleanRating = cleanlinessSection.starRating('overallCleanliness')?.value();
if (cleanRating !== null && cleanRating !== undefined) {
if (cleanRating >= 4) return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (cleanRating >= 3) return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
}
return { backgroundColor: '#fefce8', padding: '16px', borderRadius: '8px' };
}
});
cleanlinessSection.addRow(row => {
row.addStarRating('overallCleanliness', {
label: 'Overall facility cleanliness',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
cleanlinessSection.addRow(row => {
row.addMatrixQuestion('cleanlinessMatrix', {
label: 'Rate cleanliness in specific areas:',
rows: [
{ id: 'workout-floor', label: 'Workout floor / Gym area' },
{ id: 'locker-rooms', label: 'Locker rooms' },
{ id: 'showers', label: 'Showers / Bathrooms' },
{ id: 'common-areas', label: 'Common areas / Lobby' }
],
columns: [
{ id: 'dirty', label: 'Dirty' },
{ id: 'needs-attention', label: 'Needs Attention' },
{ id: 'acceptable', label: 'Acceptable' },
{ id: 'clean', label: 'Clean' },
{ id: 'spotless', label: 'Spotless' }
],
striped: true,
fullWidth: true
});
});
cleanlinessSection.addSpacer({ height: '16px' });
cleanlinessSection.addRow(row => {
row.addSlider('crowdLevel', {
label: 'How crowded was the facility during your visit?',
min: 1,
max: 5,
step: 1,
showValue: true,
defaultValue: 3
}, '1fr');
row.addSlider('temperature', {
label: 'How was the temperature/climate?',
min: 1,
max: 5,
step: 1,
showValue: true,
defaultValue: 3
}, '1fr');
});
cleanlinessSection.addRow(row => {
row.addTextPanel('scaleGuide', {
computedValue: () => {
const crowd = cleanlinessSection.slider('crowdLevel')?.value();
const temp = cleanlinessSection.slider('temperature')?.value();
const crowdLabels = ['', 'Empty', 'Light', 'Moderate', 'Busy', 'Overcrowded'];
const tempLabels = ['', 'Too Cold', 'Cool', 'Just Right', 'Warm', 'Too Hot'];
return `Crowd: ${crowdLabels[crowd || 3]} | Climate: ${tempLabels[temp || 3]}`;
},
customStyles: {
textAlign: 'center',
color: '#6b7280',
fontSize: '14px'
}
});
});
// ============================================
// SECTION 4: Staff & Service
// ============================================
const staffSection = form.addSubform('staffSection', {
title: 'Staff & Service',
customStyles: { backgroundColor: '#eff6ff', padding: '16px', borderRadius: '8px' }
});
staffSection.addRow(row => {
row.addEmojiRating('staffInteraction', {
label: 'How would you rate your interactions with staff?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
staffSection.addRow(row => {
row.addStarRating('staffKnowledge', {
label: 'Staff knowledge & helpfulness',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
row.addStarRating('staffAvailability', {
label: 'Staff availability when needed',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
});
// ============================================
// SECTION 5: Amenities
// ============================================
const amenitiesSection = form.addSubform('amenitiesSection', {
title: 'Amenities & Extras',
customStyles: { backgroundColor: '#fdf4ff', padding: '16px', borderRadius: '8px' }
});
amenitiesSection.addRow(row => {
row.addSuggestionChips('usedAmenities', {
label: 'Which amenities did you use or appreciate?',
suggestions: [
{ id: 'parking', name: 'Parking' },
{ id: 'towels', name: 'Towel service' },
{ id: 'lockers', name: 'Lockers' },
{ id: 'water', name: 'Water stations' },
{ id: 'wifi', name: 'WiFi' },
{ id: 'cafe', name: 'Cafe/Juice bar' },
{ id: 'pro-shop', name: 'Pro shop' },
{ id: 'childcare', name: 'Childcare' },
{ id: 'classes', name: 'Group classes' },
{ id: 'personal-training', name: 'Personal training' }
],
alignment: 'left'
});
});
amenitiesSection.addSpacer({ height: '16px' });
amenitiesSection.addRow(row => {
row.addCheckboxList('missingAmenities', {
label: 'What amenities would you like us to add?',
options: [
{ id: 'more-equipment', name: 'More of certain equipment' },
{ id: 'extended-hours', name: 'Extended hours' },
{ id: 'more-classes', name: 'More group class options' },
{ id: 'recovery-zone', name: 'Recovery/Stretching zone' },
{ id: 'smoothie-bar', name: 'Smoothie bar' },
{ id: 'childcare', name: 'Childcare services' },
{ id: 'outdoor-area', name: 'Outdoor workout area' },
{ id: 'virtual-classes', name: 'Virtual/On-demand classes' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 6: Overall Experience
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Experience',
customStyles: () => {
const overall = overallSection.starRating('overallRating')?.value();
if (overall !== null && overall !== undefined) {
if (overall >= 4) return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (overall >= 3) return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
}
return { padding: '16px', borderRadius: '8px', border: '1px dashed #d4d4d8' };
}
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'Overall, how would you rate your visit today?',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
overallSection.addRow(row => {
row.addRatingScale('recommendScore', {
preset: 'nps',
label: 'How likely are you to recommend our facility to a friend?',
showSegmentColors: true,
showCategoryLabel: true,
alignment: 'center'
});
});
overallSection.addSpacer({ height: '16px' });
overallSection.addRow(row => {
row.addTextarea('additionalFeedback', {
label: () => {
const category = overallSection.ratingScale('recommendScore')?.npsCategory();
if (category === 'promoter') return "That's fantastic! What do you love most about our facility?";
if (category === 'detractor') return "We're sorry to hear that. What should we focus on improving?";
return 'Any additional comments or suggestions?';
},
placeholder: 'Share your thoughts...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 7: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const visitDate = visitSection.datepicker('visitDate')?.value();
const areasUsed = visitSection.checkboxList('areasUsed')?.value() || [];
const cleanliness = cleanlinessSection.starRating('overallCleanliness')?.value();
const overall = overallSection.starRating('overallRating')?.value();
const nps = overallSection.ratingScale('recommendScore')?.value();
const npsCategory = overallSection.ratingScale('recommendScore')?.npsCategory();
if (!overall) return '';
let summary = '๐๏ธ Facility Feedback Summary\n';
summary += `${'โ'.repeat(28)}\n\n`;
if (visitDate) {
const date = new Date(visitDate);
summary += `๐
Visit: ${date.toLocaleDateString()}\n`;
}
summary += `๐ Areas used: ${areasUsed.length}\n`;
if (cleanliness) {
const cleanEmoji = cleanliness >= 4 ? 'โจ' : cleanliness >= 3 ? '๐งน' : 'โ ๏ธ';
summary += `\n${cleanEmoji} Cleanliness: ${cleanliness}/5 stars`;
}
summary += `\nโญ Overall: ${overall}/5 stars`;
if (nps !== null && nps !== undefined) {
const npsEmoji = npsCategory === 'promoter' ? '๐' : npsCategory === 'passive' ? '๐' : '๐ด';
summary += `\n${npsEmoji} NPS: ${nps}/10 (${npsCategory?.charAt(0).toUpperCase()}${npsCategory?.slice(1)})`;
}
return summary;
},
customStyles: () => {
const overall = overallSection.starRating('overallRating')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (overall && overall >= 4) {
return { ...baseStyles, backgroundColor: '#dcfce7', borderLeft: '4px solid #10b981' };
} else if (overall && overall >= 3) {
return { ...baseStyles, backgroundColor: '#fef9c3', borderLeft: '4px solid #eab308' };
} else if (overall) {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return baseStyles;
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thanks for Your Feedback!',
message: 'Your input helps us maintain and improve our facility. We take every comment seriously and use your feedback to create the best possible experience for all members.'
});
}