export function restaurantFeedback(form: FormTs) {
// Restaurant Feedback - Comprehensive dining experience survey
// Demonstrates: MatrixQuestion, StarRating, EmojiRating, Slider, conditional sections
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'How Was Your Dining Experience?',
computedValue: () => 'Your feedback helps us serve you better',
customStyles: {
backgroundColor: '#dc2626',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Visit Details
// ============================================
const visitDetails = form.addSubform('visitDetails', {
title: 'Visit Details',
customStyles: { backgroundColor: '#fef2f2', padding: '16px', borderRadius: '8px' }
});
visitDetails.addRow(row => {
row.addDropdown('mealType', {
label: 'Type of Meal',
options: [
{ id: 'breakfast', name: 'Breakfast' },
{ id: 'lunch', name: 'Lunch' },
{ id: 'dinner', name: 'Dinner' },
{ id: 'brunch', name: 'Brunch' },
{ id: 'latenight', name: 'Late Night' }
],
placeholder: 'Select meal type',
isRequired: true
}, '1fr');
row.addDropdown('diningType', {
label: 'Dining Type',
options: [
{ id: 'dinein', name: 'Dine-in' },
{ id: 'takeout', name: 'Takeout' },
{ id: 'delivery', name: 'Delivery' },
{ id: 'catering', name: 'Catering' }
],
placeholder: 'Select dining type'
}, '1fr');
});
visitDetails.addRow(row => {
row.addDatepicker('visitDate', {
label: 'Date of Visit',
maxDate: new Date().toISOString()
}, '1fr');
row.addInteger('partySize', {
label: 'Party Size',
min: 1,
max: 20,
placeholder: 'Number of guests'
}, '1fr');
});
visitDetails.addRow(row => {
row.addRadioButton('visitFrequency', {
label: 'How often do you visit us?',
options: [
{ id: 'first', name: 'First time' },
{ id: 'occasional', name: 'Occasionally' },
{ id: 'monthly', name: 'Monthly' },
{ id: 'weekly', name: 'Weekly' },
{ id: 'regular', name: 'Regular' }
],
orientation: 'horizontal'
});
});
// ============================================
// SECTION 2: Overall Experience
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Experience',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
overallSection.addRow(row => {
row.addEmojiRating('overallMood', {
label: 'How would you describe your dining experience?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'Overall Restaurant Rating',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
// ============================================
// SECTION 3: Food Quality (MatrixQuestion)
// ============================================
const foodSection = form.addSubform('foodSection', {
title: 'Food Quality',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
customStyles: { padding: '16px', borderRadius: '8px', backgroundColor: '#fafafa' }
});
foodSection.addRow(row => {
row.addMatrixQuestion('foodRatings', {
label: 'Please rate the following aspects of your food:',
rows: [
{ id: 'taste', label: 'Taste & Flavor', isRequired: true },
{ id: 'freshness', label: 'Freshness of Ingredients', isRequired: true },
{ id: 'presentation', label: 'Presentation', isRequired: false },
{ id: 'portion', label: 'Portion Size', isRequired: false },
{ id: 'temperature', label: 'Temperature (Hot/Cold)', isRequired: false },
{ id: 'menu_variety', label: 'Menu Variety', isRequired: false }
],
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
});
});
foodSection.addRow(row => {
row.addTextarea('dishHighlight', {
label: 'Which dish did you enjoy most?',
placeholder: 'Tell us about your favorite dish...',
rows: 2,
autoExpand: true
});
});
// ============================================
// SECTION 4: Service Quality
// ============================================
const serviceSection = form.addSubform('serviceSection', {
title: 'Service Quality',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
serviceSection.addRow(row => {
row.addStarRating('serverRating', {
label: 'Server/Staff Friendliness',
maxStars: 5,
size: 'md'
}, '1fr');
row.addStarRating('speedRating', {
label: 'Speed of Service',
maxStars: 5,
size: 'md'
}, '1fr');
});
serviceSection.addRow(row => {
row.addStarRating('attentivenessRating', {
label: 'Staff Attentiveness',
maxStars: 5,
size: 'md'
}, '1fr');
row.addStarRating('knowledgeRating', {
label: 'Menu Knowledge',
maxStars: 5,
size: 'md',
tooltip: 'How well staff explained menu items'
}, '1fr');
});
serviceSection.addRow(row => {
row.addSlider('waitTime', {
label: 'How long did you wait for your food? (minutes)',
min: 0,
max: 60,
step: 5,
showValue: true,
unit: 'min'
});
});
serviceSection.addRow(row => {
row.addThumbRating('orderAccuracy', {
label: 'Was your order accurate?',
showLabels: true,
upLabel: 'Yes, correct',
downLabel: 'No, had issues',
alignment: 'left'
});
});
// Order issue follow-up
serviceSection.addRow(row => {
row.addTextarea('orderIssueDetails', {
label: 'What was wrong with your order?',
placeholder: 'Please describe the issue...',
rows: 2,
autoExpand: true,
isVisible: () => serviceSection.thumbRating('orderAccuracy')?.value() === 'down'
});
});
// ============================================
// SECTION 5: Ambiance & Cleanliness
// ============================================
const ambianceSection = form.addSubform('ambianceSection', {
title: 'Ambiance & Cleanliness',
isVisible: () => {
const diningType = visitDetails.dropdown('diningType')?.value();
return diningType === 'dinein' && overallSection.starRating('overallRating')?.value() !== null;
},
customStyles: { padding: '16px', borderRadius: '8px', backgroundColor: '#f0fdf4' }
});
ambianceSection.addRow(row => {
row.addStarRating('cleanlinessRating', {
label: 'Cleanliness',
maxStars: 5,
size: 'md'
}, '1fr');
row.addStarRating('ambianceRating', {
label: 'Ambiance/Atmosphere',
maxStars: 5,
size: 'md'
}, '1fr');
});
ambianceSection.addRow(row => {
row.addStarRating('noiseLevel', {
label: 'Noise Level',
maxStars: 5,
size: 'md',
tooltip: '5 = Perfect for conversation'
}, '1fr');
row.addStarRating('comfortRating', {
label: 'Seating Comfort',
maxStars: 5,
size: 'md'
}, '1fr');
});
// ============================================
// SECTION 6: Value for Money
// ============================================
const valueSection = form.addSubform('valueSection', {
title: 'Value for Money',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
valueSection.addRow(row => {
row.addSlider('valueForMoney', {
label: 'Value for Money',
min: 1,
max: 10,
step: 1,
showValue: true,
defaultValue: 5
});
});
valueSection.addRow(row => {
row.addRadioButton('pricePerception', {
label: 'How would you describe the prices?',
options: [
{ id: 'too_expensive', name: 'Too expensive' },
{ id: 'slightly_high', name: 'Slightly high' },
{ id: 'fair', name: 'Fair/Reasonable' },
{ id: 'good_value', name: 'Good value' },
{ id: 'excellent_value', name: 'Excellent value' }
],
orientation: 'horizontal'
});
});
// ============================================
// SECTION 7: Issues Section (Low Ratings)
// ============================================
const issuesSection = form.addSubform('issuesSection', {
title: 'We Want to Make It Right',
isVisible: () => {
const rating = overallSection.starRating('overallRating')?.value();
return rating !== null && rating !== undefined && rating <= 2;
},
customStyles: { padding: '16px', borderRadius: '8px', backgroundColor: '#fef2f2', borderLeft: '4px solid #ef4444' }
});
issuesSection.addRow(row => {
row.addCheckboxList('issueAreas', {
label: 'What areas need improvement?',
options: [
{ id: 'food_quality', name: 'Food quality' },
{ id: 'service_slow', name: 'Slow service' },
{ id: 'staff_rude', name: 'Staff attitude' },
{ id: 'cleanliness', name: 'Cleanliness' },
{ id: 'wrong_order', name: 'Wrong order' },
{ id: 'pricing', name: 'Pricing' },
{ id: 'wait_time', name: 'Long wait time' },
{ id: 'other', name: 'Other' }
],
orientation: 'vertical'
});
});
issuesSection.addRow(row => {
row.addTextarea('issueDetails', {
label: 'Please describe what happened',
placeholder: 'We take all feedback seriously and want to improve...',
rows: 3,
autoExpand: true,
isRequired: () => {
const issues = issuesSection.checkboxList('issueAreas')?.value() || [];
return issues.length > 0;
}
});
});
// ============================================
// SECTION 8: Positive Highlights (High Ratings)
// ============================================
const highlightsSection = form.addSubform('highlightsSection', {
title: 'What Made Your Visit Great?',
isVisible: () => {
const rating = overallSection.starRating('overallRating')?.value();
return rating !== null && rating !== undefined && rating >= 4;
},
customStyles: { padding: '16px', borderRadius: '8px', backgroundColor: '#ecfdf5', borderLeft: '4px solid #10b981' }
});
highlightsSection.addRow(row => {
row.addSuggestionChips('highlights', {
label: 'What did you love most? (Select up to 4)',
suggestions: [
{ id: 'delicious_food', name: 'Delicious Food' },
{ id: 'great_service', name: 'Great Service' },
{ id: 'nice_ambiance', name: 'Nice Ambiance' },
{ id: 'friendly_staff', name: 'Friendly Staff' },
{ id: 'good_portions', name: 'Good Portions' },
{ id: 'clean', name: 'Very Clean' },
{ id: 'good_value', name: 'Good Value' },
{ id: 'quick_service', name: 'Quick Service' }
],
max: 4,
alignment: 'center'
});
});
// ============================================
// SECTION 9: Recommendation
// ============================================
const recommendSection = form.addSubform('recommendSection', {
title: 'Would You Recommend Us?',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
customStyles: () => {
const nps = recommendSection.ratingScale('npsScore')?.npsCategory();
if (nps === 'promoter') return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (nps === 'passive') return { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' };
if (nps === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #cbd5e1' };
}
});
recommendSection.addRow(row => {
row.addRatingScale('npsScore', {
preset: 'nps',
label: 'How likely are you to recommend us to friends or family?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true
});
});
recommendSection.addRow(row => {
row.addCheckbox('returnIntent', {
label: 'I plan to visit again'
});
});
// ============================================
// SECTION 10: Additional Comments
// ============================================
const commentsSection = form.addSubform('commentsSection', {
title: 'Additional Comments',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
commentsSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Any other feedback or suggestions?',
placeholder: 'We appreciate all your thoughts...',
rows: 3,
autoExpand: true
});
});
commentsSection.addRow(row => {
row.addCheckbox('allowContact', {
label: 'You may contact me regarding my feedback'
});
});
commentsSection.addRow(row => {
row.addEmail('contactEmail', {
label: 'Email Address',
placeholder: 'your@email.com',
isVisible: () => commentsSection.checkbox('allowContact')?.value() === true,
isRequired: () => commentsSection.checkbox('allowContact')?.value() === true
});
});
// ============================================
// SUMMARY SECTION
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Your Feedback Summary',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const overall = overallSection.starRating('overallRating')?.value();
const mood = overallSection.emojiRating('overallMood')?.value();
const nps = recommendSection.ratingScale('npsScore')?.value();
const npsCategory = recommendSection.ratingScale('npsScore')?.npsCategory();
const highlights = highlightsSection.suggestionChips('highlights')?.value() || [];
const issues = issuesSection.checkboxList('issueAreas')?.value() || [];
if (overall === null || overall === undefined) return '';
let emoji = overall >= 4 ? '🍽️' : overall >= 3 ? '🤔' : '😔';
let summary = `${emoji} Dining Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
summary += `⭐ Overall Rating: ${overall}/5 stars\n`;
if (mood) {
const moodLabels: Record<string, string> = {
'very-bad': '😢 Very Disappointed',
'bad': '😕 Disappointed',
'neutral': '😐 It was OK',
'good': '😊 Satisfied',
'excellent': '😃 Delighted'
};
summary += `${moodLabels[mood] || mood}\n`;
}
if (nps !== null && nps !== undefined) {
summary += `\n📊 Recommendation: ${nps}/10`;
if (npsCategory) {
summary += ` (${npsCategory.charAt(0).toUpperCase()}${npsCategory.slice(1)})`;
}
}
if (highlights.length > 0) {
summary += `\n\n✨ Loved: ${highlights.length} items selected`;
}
if (issues.length > 0) {
summary += `\n⚠️ Issues: ${issues.length} areas flagged`;
}
return summary;
},
customStyles: () => {
const rating = overallSection.starRating('overallRating')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (rating !== null && rating !== undefined && rating >= 4) {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (rating !== null && rating !== undefined && rating >= 3) {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
} else if (rating !== null && rating !== undefined) {
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: 'Thank You for Dining With Us!',
message: 'Your feedback helps us create better dining experiences. We hope to welcome you back soon!'
});
}