export function vacationRentalFeedback(form: FormTs) {
// Vacation Rental Review Form - Airbnb/VRBO Style
// Demonstrates: Multi-page wizard, StarRating, MatrixQuestion, EmojiRating, ThumbRating, Slider, SuggestionChips
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Share Your Stay Experience',
computedValue: () => 'Your honest feedback helps hosts improve and future guests make informed decisions.',
customStyles: {
backgroundColor: '#0891b2',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('rentalReviewPages');
// ============================================
// PAGE 1: Overall & First Impressions
// ============================================
const page1 = pages.addPage('overall');
page1.addRow(row => {
row.addTextPanel('page1Title', {
label: '',
computedValue: () => 'Part 1: Overall Experience',
customStyles: { fontWeight: 'bold', fontSize: '18px', marginBottom: '8px' }
});
});
// Overall Rating Section
const overallSection = page1.addSubform('overallSection', {
title: 'How Was Your Stay?',
customStyles: () => {
const rating = overallSection.starRating('overallRating')?.value();
if (rating && rating >= 4) return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (rating && rating <= 2) return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #cbd5e1' };
}
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'Overall, how would you rate your stay?',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
overallSection.addRow(row => {
row.addEmojiRating('stayMood', {
label: 'How did you feel about your experience?',
preset: 'satisfaction',
size: 'lg',
alignment: 'center',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
});
// Recommendation
const recommendSection = page1.addSubform('recommendSection', {
title: 'Would You Recommend?',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
recommendSection.addRow(row => {
row.addThumbRating('wouldRecommend', {
label: 'Would you recommend this property to friends?',
size: 'lg',
showLabels: true,
upLabel: 'Yes, definitely!',
downLabel: 'No, probably not',
alignment: 'center'
});
});
// ============================================
// PAGE 2: Property Ratings
// ============================================
const page2 = pages.addPage('property');
page2.addRow(row => {
row.addTextPanel('page2Title', {
label: '',
computedValue: () => 'Part 2: Property Details',
customStyles: { fontWeight: 'bold', fontSize: '18px', marginBottom: '8px' }
});
});
// Property Ratings Matrix
const propertySection = page2.addSubform('propertySection', {
title: 'Rate the Property'
});
propertySection.addRow(row => {
row.addMatrixQuestion('propertyRatings', {
label: 'Please rate the following aspects of the property:',
rows: [
{ id: 'accuracy', label: 'Listing Accuracy (photos/description match reality)', isRequired: true },
{ id: 'cleanliness', label: 'Cleanliness', isRequired: true },
{ id: 'comfort', label: 'Comfort & Amenities', isRequired: true },
{ id: 'location', label: 'Location', isRequired: false },
{ id: 'checkin', label: 'Check-in Process', isRequired: false },
{ id: 'value', label: 'Value for Money', isRequired: false }
],
columns: [
{ id: '1', label: '1' },
{ id: '2', label: '2' },
{ id: '3', label: '3' },
{ id: '4', label: '4' },
{ id: '5', label: '5' }
],
striped: true,
fullWidth: true
});
});
// Value Slider
const valueSection = page2.addSubform('valueSection', {
title: 'Value Assessment'
});
valueSection.addRow(row => {
row.addSlider('valueRating', {
label: 'How would you rate the overall value for the price paid?',
min: 1,
max: 10,
step: 1,
showValue: true,
defaultValue: 5
});
});
valueSection.addRow(row => {
row.addTextPanel('valueComment', {
computedValue: () => {
const value = valueSection.slider('valueRating')?.value();
if (value && value >= 8) return '💰 Excellent value!';
if (value && value >= 5) return '💵 Fair value for the price.';
if (value) return '⚠️ Could be better value.';
return '';
},
customStyles: { fontStyle: 'italic', textAlign: 'center', padding: '8px' }
});
});
// ============================================
// PAGE 3: Highlights & Issues
// ============================================
const page3 = pages.addPage('details');
page3.addRow(row => {
row.addTextPanel('page3Title', {
label: '',
computedValue: () => 'Part 3: Highlights & Concerns',
customStyles: { fontWeight: 'bold', fontSize: '18px', marginBottom: '8px' }
});
});
// What was great - for positive ratings
const highlightsSection = page3.addSubform('highlightsSection', {
title: 'What Made Your Stay Great?',
isVisible: () => {
const rating = overallSection.starRating('overallRating')?.value();
return rating !== null && rating !== undefined && rating >= 3;
},
customStyles: { backgroundColor: '#ecfdf5', padding: '16px', borderRadius: '8px' }
});
highlightsSection.addRow(row => {
row.addSuggestionChips('highlights', {
label: 'Select the highlights of your stay:',
suggestions: [
{ id: 'clean', name: 'Spotlessly clean' },
{ id: 'comfy-bed', name: 'Comfortable bed' },
{ id: 'great-location', name: 'Great location' },
{ id: 'beautiful-view', name: 'Beautiful view' },
{ id: 'well-equipped', name: 'Well-equipped kitchen' },
{ id: 'fast-wifi', name: 'Fast WiFi' },
{ id: 'quiet', name: 'Quiet & peaceful' },
{ id: 'host-responsive', name: 'Responsive host' },
{ id: 'easy-checkin', name: 'Easy check-in' },
{ id: 'local-tips', name: 'Great local tips' }
],
alignment: 'center'
});
});
// Issues encountered - for any rating
const issuesSection = page3.addSubform('issuesSection', {
title: 'Any Issues Encountered?',
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
issuesSection.addRow(row => {
row.addCheckboxList('issuesEncountered', {
label: 'Did you experience any of these issues? (select all that apply)',
options: [
{ id: 'none', name: 'No issues at all!' },
{ id: 'cleanliness', name: 'Cleanliness issues' },
{ id: 'noise', name: 'Noise/disturbances' },
{ id: 'inaccurate', name: 'Listing inaccuracies' },
{ id: 'amenities', name: 'Missing/broken amenities' },
{ id: 'wifi', name: 'WiFi problems' },
{ id: 'heating-cooling', name: 'Heating/cooling issues' },
{ id: 'pests', name: 'Pests' },
{ id: 'safety', name: 'Safety concerns' },
{ id: 'parking', name: 'Parking issues' }
],
orientation: 'vertical'
});
});
issuesSection.addSpacer();
issuesSection.addRow(row => {
row.addTextarea('issueDetails', {
label: 'Please describe any issues in detail:',
placeholder: 'Help us understand what went wrong so we can improve...',
rows: 3,
isVisible: () => {
const issues = issuesSection.checkboxList('issuesEncountered')?.value() || [];
return issues.length > 0 && !issues.includes('none');
}
});
});
// ============================================
// PAGE 4: Host & Communication
// ============================================
const page4 = pages.addPage('host');
page4.addRow(row => {
row.addTextPanel('page4Title', {
label: '',
computedValue: () => 'Part 4: Host & Communication',
customStyles: { fontWeight: 'bold', fontSize: '18px', marginBottom: '8px' }
});
});
// Host Rating
const hostSection = page4.addSubform('hostSection', {
title: 'Your Host',
customStyles: () => {
const rating = hostSection.starRating('hostRating')?.value();
if (rating && rating >= 4) return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (rating && rating <= 2) return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #cbd5e1' };
}
});
hostSection.addRow(row => {
row.addStarRating('hostRating', {
label: 'How would you rate your host?',
maxStars: 5,
size: 'xl',
alignment: 'center'
});
});
hostSection.addRow(row => {
row.addMatrixQuestion('hostAttributes', {
label: 'Please rate your host on:',
rows: [
{ id: 'communication', label: 'Communication responsiveness', isRequired: true },
{ id: 'helpfulness', label: 'Helpfulness', isRequired: false },
{ id: 'professionalism', label: 'Professionalism', isRequired: false },
{ id: 'instructions', label: 'Clear instructions', isRequired: false }
],
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true,
isVisible: () => hostSection.starRating('hostRating')?.value() !== null
});
});
// Final comments
const commentsSection = page4.addSubform('commentsSection', {
title: 'Final Thoughts'
});
commentsSection.addSpacer();
commentsSection.addRow(row => {
row.addTextarea('publicReview', {
label: 'Write a review that could be shared publicly:',
placeholder: 'Describe your experience for future guests. What should they expect?',
rows: 4
});
});
commentsSection.addSpacer();
commentsSection.addRow(row => {
row.addTextarea('privateHost', {
label: 'Private message to the host (only host sees this):',
placeholder: 'Share any private feedback, suggestions, or thanks...',
rows: 2
});
});
// ============================================
// SUMMARY SECTION (after pages)
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Review Summary',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const overall = overallSection.starRating('overallRating')?.value();
const mood = overallSection.emojiRating('stayMood')?.value();
const recommend = recommendSection.thumbRating('wouldRecommend')?.value();
const value = valueSection.slider('valueRating')?.value();
const host = hostSection.starRating('hostRating')?.value();
const highlights = highlightsSection.suggestionChips('highlights')?.value() || [];
const issues = issuesSection.checkboxList('issuesEncountered')?.value() || [];
if (!overall) return '';
let summary = '🏠 Stay Review Summary\n';
summary += '━'.repeat(25) + '\n\n';
// Overall
summary += `⭐ Overall Rating: ${'★'.repeat(overall)}${'☆'.repeat(5-overall)} ${overall}/5\n`;
// Mood
if (mood) {
const moodLabels: Record<string, string> = {
'very-bad': '😢 Very Disappointed',
'bad': '😕 Disappointed',
'neutral': '😐 Okay',
'good': '🙂 Happy',
'excellent': '😍 Loved It!'
};
summary += `${moodLabels[mood] || mood}\n`;
}
// Host
if (host) {
summary += `\n👤 Host Rating: ${'★'.repeat(host)}${host}/5\n`;
}
// Value
if (value) {
summary += `💰 Value: ${value}/10\n`;
}
// Recommendation
if (recommend === 'up') {
summary += '\n✅ Would recommend to friends';
} else if (recommend === 'down') {
summary += '\n❌ Would not recommend';
}
// Highlights
if (highlights.length > 0) {
summary += `\n\n✨ ${highlights.length} highlights selected`;
}
// Issues
if (issues.length > 0 && !issues.includes('none')) {
summary += `\n⚠️ ${issues.length} issues reported`;
} else if (issues.includes('none')) {
summary += '\n💚 No issues reported';
}
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: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (overall && overall <= 2) {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Review'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Review!',
message: 'Your feedback helps hosts improve and assists future guests in finding the perfect accommodation. We appreciate you taking the time to share your experience.'
});
}