export function deliveryFeedbackSurvey(form: FormTs) {
// Delivery Experience Survey
// Demonstrates: StarRating, EmojiRating, ThumbRating, RatingScale, MatrixQuestion, Slider, conditional sections
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'How Was Your Delivery?',
computedValue: () => 'Your feedback helps us improve our delivery service.',
customStyles: {
backgroundColor: '#0284c7',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Order Information
// ============================================
const orderSection = form.addSubform('orderSection', {
title: 'Order Details'
});
orderSection.addRow(row => {
row.addTextbox('orderNumber', {
label: 'Order Number (optional)',
placeholder: 'e.g., ORD-12345'
}, '1fr');
row.addDatepicker('deliveryDate', {
label: 'Delivery Date',
maxDate: () => new Date().toISOString(),
isRequired: true
}, '200px');
});
orderSection.addRow(row => {
row.addDropdown('deliveryType', {
label: 'Delivery Type',
options: [
{ id: 'standard', name: 'Standard Delivery' },
{ id: 'express', name: 'Express/Next-Day' },
{ id: 'same-day', name: 'Same-Day Delivery' },
{ id: 'scheduled', name: 'Scheduled Time Slot' },
{ id: 'pickup', name: 'Pickup Point/Locker' }
],
placeholder: 'Select delivery type...'
}, '1fr');
row.addDropdown('carrier', {
label: 'Delivery Carrier',
options: [
{ id: 'in-house', name: 'Our Delivery Team' },
{ id: 'fedex', name: 'FedEx' },
{ id: 'ups', name: 'UPS' },
{ id: 'dhl', name: 'DHL' },
{ id: 'usps', name: 'USPS' },
{ id: 'other', name: 'Other Carrier' }
],
placeholder: 'Select carrier...'
}, '1fr');
});
// ============================================
// SECTION 2: Overall Rating
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Experience'
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'How would you rate your delivery experience?',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
overallSection.addRow(row => {
row.addTextPanel('ratingMessage', {
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
computedValue: () => {
const rating = overallSection.starRating('overallRating')?.value();
if (rating === null || rating === undefined) return '';
if (rating === 5) return 'Excellent! We are thrilled you had a great experience!';
if (rating === 4) return 'Great! Thank you for the positive feedback.';
if (rating === 3) return 'Thanks! Let us know how we can improve.';
return 'We are sorry to hear that. Please tell us what went wrong.';
},
customStyles: () => {
const rating = overallSection.starRating('overallRating')?.value();
const base = { padding: '12px', borderRadius: '6px', textAlign: 'center', fontStyle: 'italic' };
if (rating === null || rating === undefined) return base;
if (rating >= 4) return { ...base, backgroundColor: '#dbeafe', color: '#1e40af' };
if (rating === 3) return { ...base, backgroundColor: '#fef3c7', color: '#92400e' };
return { ...base, backgroundColor: '#fee2e2', color: '#991b1b' };
}
});
});
// ============================================
// SECTION 3: Delivery Timing
// ============================================
const timingSection = form.addSubform('timingSection', {
title: 'Delivery Timing',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
timingSection.addRow(row => {
row.addRadioButton('onTime', {
label: 'Was your order delivered on time?',
options: [
{ id: 'early', name: 'Early' },
{ id: 'on-time', name: 'On Time' },
{ id: 'slightly-late', name: 'Slightly Late' },
{ id: 'very-late', name: 'Very Late' }
],
orientation: 'horizontal'
});
});
// Late delivery follow-up
timingSection.addRow(row => {
row.addSlider('hoursLate', {
label: 'How many hours late was the delivery?',
min: 1,
max: 72,
step: 1,
defaultValue: 2,
showValue: true,
unit: 'hrs',
isVisible: () => {
const timing = timingSection.radioButton('onTime')?.value();
return timing === 'slightly-late' || timing === 'very-late';
}
});
});
timingSection.addRow(row => {
row.addEmojiRating('communicationRating', {
label: 'How was the communication about your delivery?',
preset: 'satisfaction',
size: 'md',
showLabels: true,
alignment: 'center'
});
});
// ============================================
// SECTION 4: Driver/Courier Evaluation
// ============================================
const driverSection = form.addSubform('driverSection', {
title: 'Delivery Driver',
isVisible: () => {
const deliveryType = orderSection.dropdown('deliveryType')?.value();
const rating = overallSection.starRating('overallRating')?.value();
return rating !== null && deliveryType !== 'pickup';
}
});
driverSection.addRow(row => {
row.addThumbRating('metDriver', {
label: 'Did you interact with the delivery driver?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'left'
});
});
const driverEvalSection = form.addSubform('driverEvalSection', {
title: 'Rate Your Driver',
isVisible: () => driverSection.thumbRating('metDriver')?.value() === 'up',
customStyles: { backgroundColor: '#f0f9ff', padding: '16px', borderRadius: '8px' }
});
driverEvalSection.addRow(row => {
row.addMatrixQuestion('driverMatrix', {
label: 'Please rate the driver on the following:',
rows: [
{ id: 'courtesy', label: 'Courtesy and friendliness' },
{ id: 'professionalism', label: 'Professionalism' },
{ id: 'communication', label: 'Communication' },
{ id: 'handling', label: 'Package handling care' },
{ id: 'instructions', label: 'Following delivery instructions' }
],
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
});
});
driverEvalSection.addSpacer({ height: '16px' });
driverEvalSection.addRow(row => {
row.addStarRating('driverOverall', {
label: 'Overall driver rating',
maxStars: 5,
size: 'lg',
alignment: 'center'
});
});
// ============================================
// SECTION 5: Package Condition
// ============================================
const packageSection = form.addSubform('packageSection', {
title: 'Package Condition',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
packageSection.addRow(row => {
row.addRadioButton('packageCondition', {
label: 'How was the condition of your package when it arrived?',
options: [
{ id: 'perfect', name: 'Perfect condition' },
{ id: 'minor-damage', name: 'Minor box damage, contents fine' },
{ id: 'damaged', name: 'Package and/or contents damaged' },
{ id: 'opened', name: 'Package appeared opened' }
],
orientation: 'vertical',
isRequired: true
});
});
// Damage details
const damageSection = form.addSubform('damageSection', {
title: 'Damage Details',
isVisible: () => {
const condition = packageSection.radioButton('packageCondition')?.value();
return condition === 'damaged' || condition === 'opened';
},
customStyles: { backgroundColor: '#fef2f2', padding: '16px', borderRadius: '8px' }
});
damageSection.addRow(row => {
row.addCheckboxList('damageType', {
label: 'What type of damage occurred?',
options: [
{ id: 'crushed', name: 'Box crushed or dented' },
{ id: 'wet', name: 'Water damage' },
{ id: 'torn', name: 'Box torn or ripped' },
{ id: 'item-broken', name: 'Item inside broken' },
{ id: 'item-missing', name: 'Item missing from package' },
{ id: 'wrong-item', name: 'Wrong item received' }
],
orientation: 'vertical'
});
});
damageSection.addRow(row => {
row.addTextarea('damageDetails', {
label: 'Please describe the damage',
placeholder: 'Provide details about the damage...',
rows: 2,
isRequired: true
});
});
damageSection.addRow(row => {
row.addRadioButton('damageResolution', {
label: 'What would you like us to do?',
options: [
{ id: 'replacement', name: 'Send replacement' },
{ id: 'refund', name: 'Issue refund' },
{ id: 'contact', name: 'Contact me to discuss' },
{ id: 'nothing', name: 'No action needed' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 6: Delivery Location
// ============================================
const locationSection = form.addSubform('locationSection', {
title: 'Delivery Location',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
locationSection.addRow(row => {
row.addRadioButton('deliveryLocation', {
label: 'Where was the package left?',
options: [
{ id: 'hand', name: 'Handed to me/someone' },
{ id: 'door', name: 'Front door' },
{ id: 'mailbox', name: 'Mailbox' },
{ id: 'locker', name: 'Package locker' },
{ id: 'neighbor', name: 'With neighbor' },
{ id: 'other', name: 'Other location' }
],
orientation: 'horizontal'
});
});
locationSection.addRow(row => {
row.addThumbRating('photoProvided', {
label: 'Did you receive a delivery photo confirmation?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'left'
}, '1fr');
row.addThumbRating('safeLocation', {
label: 'Was it left in a safe/secure location?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'left'
}, '1fr');
});
// ============================================
// SECTION 7: Recommendation
// ============================================
const recommendSection = form.addSubform('recommendSection', {
title: 'Recommendation',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
recommendSection.addRow(row => {
row.addRatingScale('npsScore', {
label: 'How likely are you to recommend our delivery service?',
preset: 'nps',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true
});
});
// ============================================
// SECTION 8: Additional Feedback
// ============================================
const feedbackSection = form.addSubform('feedbackSection', {
title: 'Additional Comments',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
feedbackSection.addRow(row => {
row.addSuggestionChips('highlights', {
label: 'What did you like about the delivery?',
suggestions: [
{ id: 'fast', name: 'Fast delivery' },
{ id: 'tracking', name: 'Good tracking' },
{ id: 'driver', name: 'Friendly driver' },
{ id: 'condition', name: 'Great packaging' },
{ id: 'communication', name: 'Clear communication' },
{ id: 'flexible', name: 'Flexible options' },
{ id: 'secure', name: 'Secure location' }
],
max: 3,
alignment: 'center'
});
});
feedbackSection.addSpacer({ height: '16px' });
feedbackSection.addRow(row => {
row.addTextarea('comments', {
label: 'Any other feedback or suggestions?',
placeholder: 'Share your thoughts on how we can improve...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Feedback Summary',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const overall = overallSection.starRating('overallRating')?.value();
const timing = timingSection.radioButton('onTime')?.value();
const condition = packageSection.radioButton('packageCondition')?.value();
const driverRating = driverEvalSection.starRating('driverOverall')?.value();
const nps = recommendSection.ratingScale('npsScore')?.value();
const deliveryType = orderSection.dropdown('deliveryType')?.value();
if (!overall) return '';
const timingLabels: Record<string, string> = {
'early': 'Early',
'on-time': 'On Time',
'slightly-late': 'Slightly Late',
'very-late': 'Very Late'
};
const conditionLabels: Record<string, string> = {
'perfect': 'Perfect',
'minor-damage': 'Minor Damage',
'damaged': 'Damaged',
'opened': 'Opened'
};
const typeLabels: Record<string, string> = {
'standard': 'Standard',
'express': 'Express',
'same-day': 'Same-Day',
'scheduled': 'Scheduled',
'pickup': 'Pickup'
};
let summary = `Delivery Feedback Summary\n`;
summary += `${'='.repeat(26)}\n\n`;
if (deliveryType) {
summary += `Delivery Type: ${typeLabels[deliveryType] || deliveryType}\n`;
}
summary += `Overall Rating: ${'*'.repeat(overall)}${'*'.repeat(5 - overall)} (${overall}/5)\n`;
if (timing) {
summary += `Delivery Timing: ${timingLabels[timing] || timing}\n`;
}
if (condition) {
const conditionEmoji = condition === 'perfect' ? '' : '';
summary += `Package Condition: ${conditionLabels[condition] || condition} ${conditionEmoji}\n`;
}
if (driverRating) {
summary += `Driver Rating: ${driverRating}/5\n`;
}
if (nps !== null && nps !== undefined) {
summary += `NPS Score: ${nps}/10\n`;
}
return summary;
},
customStyles: () => {
const overall = overallSection.starRating('overallRating')?.value() || 0;
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (overall >= 4) {
return { ...baseStyles, backgroundColor: '#dbeafe', borderLeft: '4px solid #0284c7' };
} else if (overall >= 3) {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your input helps us deliver better experiences. We appreciate you taking the time to share your thoughts.'
});
}