export function hotelCheckinFeedback(form: FormTs) {
// Hotel Check-in Experience Survey
// Demonstrates: RatingScale (CES), Slider, StarRating, EmojiRating, RadioButton, MatrixQuestion, ThumbRating, Timepicker
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Welcome! How Was Your Check-in?',
computedValue: () => 'Your feedback helps us make every arrival special.',
customStyles: {
backgroundColor: '#0d9488',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Check-in Details
// ============================================
const detailsSection = form.addSubform('details', {
title: 'Your Arrival'
});
detailsSection.addRow(row => {
row.addRadioButton('checkinType', {
label: 'How did you check in?',
options: [
{ id: 'front_desk', name: 'Front Desk' },
{ id: 'mobile', name: 'Mobile Check-in' },
{ id: 'kiosk', name: 'Self-Service Kiosk' },
{ id: 'express', name: 'Express/VIP Check-in' }
],
orientation: 'horizontal',
isRequired: true
});
});
detailsSection.addRow(row => {
row.addTimepicker('arrivalTime', {
label: 'Approximate arrival time'
}, '1fr');
row.addRadioButton('reservationType', {
label: 'Reservation type',
options: [
{ id: 'direct', name: 'Direct booking' },
{ id: 'ota', name: 'Online travel agency' },
{ id: 'corporate', name: 'Corporate/Group' },
{ id: 'loyalty', name: 'Loyalty program' }
],
orientation: 'vertical'
}, '1fr');
});
// ============================================
// SECTION 2: First Impressions
// ============================================
const impressionSection = form.addSubform('impressions', {
title: 'First Impressions',
customStyles: { backgroundColor: '#f0fdfa', padding: '16px', borderRadius: '8px' }
});
impressionSection.addRow(row => {
row.addEmojiRating('firstImpression', {
label: 'Your first impression when entering the lobby',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
impressionSection.addSpacer({ height: '12px' });
impressionSection.addRow(row => {
row.addThumbRating('wasGreeted', {
label: 'Were you greeted promptly upon arrival?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
size: 'md',
alignment: 'center'
});
});
// ============================================
// SECTION 3: Wait Time
// ============================================
const waitSection = form.addSubform('wait', {
title: 'Wait Time Experience',
isVisible: () => {
const type = detailsSection.radioButton('checkinType')?.value();
return type === 'front_desk' || type === 'kiosk';
}
});
waitSection.addRow(row => {
row.addSlider('waitMinutes', {
label: 'How long did you wait to be served? (minutes)',
min: 0,
max: 30,
step: 1,
defaultValue: 5,
showValue: true,
unit: 'min'
});
});
waitSection.addRow(row => {
row.addRatingScale('waitSatisfaction', {
preset: 'satisfaction',
label: 'How satisfied were you with the wait time?',
size: 'md',
alignment: 'center'
});
});
waitSection.addRow(row => {
row.addCheckbox('wasSeated', {
label: 'Seating was available while waiting',
isVisible: () => {
const wait = waitSection.slider('waitMinutes')?.value();
return wait !== null && wait !== undefined && wait > 5;
}
});
});
// ============================================
// SECTION 4: Staff Experience
// ============================================
const staffSection = form.addSubform('staff', {
title: 'Front Desk Staff',
isVisible: () => {
const type = detailsSection.radioButton('checkinType')?.value();
return type === 'front_desk' || type === 'express';
}
});
staffSection.addRow(row => {
row.addStarRating('staffOverall', {
label: 'Overall staff rating',
maxStars: 5,
size: 'lg',
showCounter: true,
alignment: 'center',
showConfettiOnMax: true
});
});
staffSection.addSpacer({ height: '16px' });
staffSection.addRow(row => {
row.addMatrixQuestion('staffRatings', {
label: 'Rate the staff on:',
rows: [
{ id: 'friendliness', label: 'Friendliness & warmth', isRequired: true },
{ id: 'efficiency', label: 'Speed & efficiency' },
{ id: 'knowledge', label: 'Knowledge & helpfulness' },
{ id: 'appearance', label: 'Professional appearance' }
],
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
staffSection.addSpacer({ height: '12px' });
staffSection.addRow(row => {
row.addTextbox('staffName', {
label: 'Staff member name (if you remember)',
placeholder: 'Help us recognize great service'
});
});
// ============================================
// SECTION 5: Check-in Process Effort
// ============================================
const effortSection = form.addSubform('effort', {
title: 'Check-in Ease'
});
effortSection.addRow(row => {
row.addRatingScale('effortScore', {
preset: 'ces',
label: 'How easy was the check-in process overall?',
size: 'md',
alignment: 'center',
isRequired: true
});
});
effortSection.addSpacer({ height: '16px' });
effortSection.addRow(row => {
row.addCheckboxList('effortIssues', {
label: 'Did you experience any of these issues?',
options: [
{ id: 'reservation', name: 'Reservation not found' },
{ id: 'id_issues', name: 'ID verification problems' },
{ id: 'payment', name: 'Payment processing issues' },
{ id: 'system_slow', name: 'Slow computer system' },
{ id: 'wrong_room', name: 'Wrong room type assigned' },
{ id: 'upgrade', name: 'Upgrade confusion' },
{ id: 'early_arrival', name: 'Room not ready (early arrival)' },
{ id: 'none', name: 'No issues - smooth process' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 6: Room Assignment
// ============================================
const roomSection = form.addSubform('room', {
title: 'Room Assignment'
});
roomSection.addRow(row => {
row.addThumbRating('gotRequestedRoom', {
label: 'Did you receive the room type you booked?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
size: 'md',
alignment: 'center'
});
});
roomSection.addRow(row => {
row.addRadioButton('roomLocation', {
label: 'Are you satisfied with your room location?',
options: [
{ id: 'very_satisfied', name: 'Very satisfied' },
{ id: 'satisfied', name: 'Satisfied' },
{ id: 'neutral', name: 'Neutral' },
{ id: 'dissatisfied', name: 'Dissatisfied' }
],
orientation: 'horizontal',
isVisible: () => roomSection.thumbRating('gotRequestedRoom')?.value() === 'up'
});
});
roomSection.addRow(row => {
row.addTextarea('roomIssue', {
label: 'What was the issue with your room?',
placeholder: 'Tell us what went wrong so we can make it right...',
rows: 2,
isVisible: () => roomSection.thumbRating('gotRequestedRoom')?.value() === 'down'
});
});
// ============================================
// SECTION 7: Information Provided
// ============================================
const infoSection = form.addSubform('info', {
title: 'Information & Orientation'
});
infoSection.addRow(row => {
row.addSuggestionChips('infoProvided', {
label: 'What information were you given at check-in?',
suggestions: [
{ id: 'wifi', name: 'WiFi details' },
{ id: 'breakfast', name: 'Breakfast info' },
{ id: 'amenities', name: 'Hotel amenities' },
{ id: 'restaurants', name: 'Dining options' },
{ id: 'checkout', name: 'Checkout time' },
{ id: 'local', name: 'Local recommendations' },
{ id: 'none', name: 'None provided' }
],
alignment: 'center'
});
});
infoSection.addRow(row => {
row.addThumbRating('infoSufficient', {
label: 'Was the information provided sufficient?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'Needed more',
size: 'md',
alignment: 'center',
isVisible: () => {
const info = infoSection.suggestionChips('infoProvided')?.value() || [];
return info.length > 0 && !info.includes('none');
}
});
});
// ============================================
// SECTION 8: Additional Comments
// ============================================
const commentsSection = form.addSubform('comments', {
title: 'Additional Feedback'
});
commentsSection.addSpacer({ height: '8px' });
commentsSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Any other comments about your check-in experience?',
placeholder: 'Share any additional thoughts, suggestions, or compliments...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => effortSection.ratingScale('effortScore')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const checkinType = detailsSection.radioButton('checkinType')?.value();
const firstImpression = impressionSection.emojiRating('firstImpression')?.value();
const wasGreeted = impressionSection.thumbRating('wasGreeted')?.value();
const waitMinutes = waitSection.slider('waitMinutes')?.value();
const staffRating = staffSection.starRating('staffOverall')?.value();
const effortScore = effortSection.ratingScale('effortScore')?.value();
const gotRoom = roomSection.thumbRating('gotRequestedRoom')?.value();
const typeLabels: Record<string, string> = {
'front_desk': 'Front Desk',
'mobile': 'Mobile Check-in',
'kiosk': 'Self-Service Kiosk',
'express': 'Express/VIP'
};
const impressionLabels: Record<string, string> = {
'very-bad': '😢 Poor',
'bad': '😕 Below Average',
'neutral': '😐 Neutral',
'good': '😊 Good',
'excellent': '😃 Excellent'
};
let summary = `🏨 Check-in Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
if (checkinType) {
summary += `📋 Check-in Type: ${typeLabels[checkinType] || checkinType}\n`;
}
if (firstImpression) {
summary += `👁️ First Impression: ${impressionLabels[firstImpression] || firstImpression}\n`;
}
if (wasGreeted !== null && wasGreeted !== undefined) {
summary += `👋 Greeted Promptly: ${wasGreeted === 'up' ? 'Yes' : 'No'}\n`;
}
if (waitMinutes !== null && waitMinutes !== undefined && (checkinType === 'front_desk' || checkinType === 'kiosk')) {
summary += `⏱️ Wait Time: ${waitMinutes} minutes\n`;
}
if (staffRating !== null && staffRating !== undefined) {
summary += `⭐ Staff Rating: ${'⭐'.repeat(staffRating)} (${staffRating}/5)\n`;
}
if (effortScore !== null && effortScore !== undefined) {
let effortLabel = effortScore <= 2 ? 'Difficult' : effortScore <= 4 ? 'Moderate' : effortScore <= 5 ? 'Easy' : 'Very Easy';
summary += `\n🎯 Ease Score: ${effortScore}/7 (${effortLabel})`;
}
if (gotRoom !== null && gotRoom !== undefined) {
summary += `\n🛏️ Got Requested Room: ${gotRoom === 'up' ? 'Yes' : 'No'}`;
}
return summary;
},
customStyles: () => {
const effortScore = effortSection.ratingScale('effortScore')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (effortScore !== null && effortScore !== undefined) {
if (effortScore >= 6) {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (effortScore >= 4) {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
} else {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
}
return baseStyles;
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => effortSection.ratingScale('effortScore')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: () => {
const effortScore = effortSection.ratingScale('effortScore')?.value();
if (effortScore !== null && effortScore !== undefined && effortScore >= 6) {
return 'Thank you! Enjoy your stay!';
}
return 'Thank you for your feedback';
},
message: () => {
const effortScore = effortSection.ratingScale('effortScore')?.value();
const gotRoom = roomSection.thumbRating('gotRequestedRoom')?.value();
if (gotRoom === 'down') {
return "We're sorry about the room issue. Our front desk team has been notified and will reach out to assist you.";
}
if (effortScore !== null && effortScore !== undefined && effortScore <= 3) {
return "We're sorry the check-in wasn't smooth. We've noted your feedback and will work to improve. Please contact our front desk if you need any assistance.";
}
return "We appreciate your feedback! It helps us provide the best possible experience for all our guests. Enjoy your stay!";
}
});
}