export function repairServiceFeedback(form: FormTs) {
// Repair Service Feedback - Comprehensive service quality assessment
// Demonstrates: RatingScale (CES), StarRating, ThumbRating, MatrixQuestion, Datepicker, dynamic labels
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Repair Service Feedback',
computedValue: () => 'Help us improve our service by sharing your repair experience.',
customStyles: {
backgroundColor: '#0284c7',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Service Details
// ============================================
const serviceSection = form.addSubform('serviceDetails', {
title: 'Service Details'
});
serviceSection.addRow(row => {
row.addDropdown('serviceType', {
label: 'What type of repair service did you receive?',
options: [
{ id: 'electronics', name: 'Electronics Repair' },
{ id: 'appliance', name: 'Appliance Repair' },
{ id: 'computer', name: 'Computer/Laptop Repair' },
{ id: 'phone', name: 'Phone/Tablet Repair' },
{ id: 'hvac', name: 'HVAC/Heating/Cooling' },
{ id: 'plumbing', name: 'Plumbing' },
{ id: 'electrical', name: 'Electrical' },
{ id: 'automotive', name: 'Automotive' },
{ id: 'other', name: 'Other' }
],
isRequired: true,
placeholder: 'Select service type...'
}, '1fr');
row.addDatepicker('serviceDate', {
label: 'Service completion date',
isRequired: true,
maxDate: () => new Date().toISOString().split('T')[0]
}, '1fr');
});
serviceSection.addRow(row => {
row.addTextbox('technicianName', {
label: 'Technician name (if known)',
placeholder: 'Enter technician name...'
}, '1fr');
row.addTextbox('ticketNumber', {
label: 'Service ticket/order number',
placeholder: 'e.g., SR-12345'
}, '1fr');
});
// ============================================
// SECTION 2: Repair Outcome
// ============================================
const outcomeSection = form.addSubform('repairOutcome', {
title: 'Repair Outcome'
});
outcomeSection.addRow(row => {
row.addRadioButton('repairResolved', {
label: 'Was your issue fully resolved?',
options: [
{ id: 'yes', name: 'Yes, completely resolved' },
{ id: 'partial', name: 'Partially resolved' },
{ id: 'no', name: 'No, issue persists' }
],
orientation: 'vertical',
isRequired: true
});
});
// Conditional: If not fully resolved
const unresolvedSection = outcomeSection.addSubform('unresolvedDetails', {
title: 'Tell us more about the issue',
isVisible: () => {
const resolved = outcomeSection.radioButton('repairResolved')?.value();
return resolved === 'partial' || resolved === 'no';
},
customStyles: { backgroundColor: '#fef2f2', padding: '16px', borderRadius: '8px' }
});
unresolvedSection.addRow(row => {
row.addCheckboxList('unresolvedReasons', {
label: 'What issues remain?',
options: [
{ id: 'same-problem', name: 'Same problem returned' },
{ id: 'new-problem', name: 'New problem appeared' },
{ id: 'incomplete', name: 'Repair was incomplete' },
{ id: 'wrong-diagnosis', name: 'Wrong diagnosis' },
{ id: 'parts-issue', name: 'Parts not available' }
],
orientation: 'vertical'
});
});
unresolvedSection.addRow(row => {
row.addTextarea('unresolvedDescription', {
label: 'Please describe the remaining issue',
placeholder: 'Describe what is still not working...',
rows: 3,
isRequired: true
});
});
// ============================================
// SECTION 3: Customer Effort Score
// ============================================
const cesSection = form.addSubform('effortScore', {
title: 'Service Ease'
});
cesSection.addRow(row => {
row.addRatingScale('ces', {
label: 'How easy was it to get your item repaired?',
preset: 'ces',
alignment: 'center',
isRequired: true
});
});
// Effort details (conditional based on CES)
cesSection.addRow(row => {
row.addSuggestionChips('effortFactors', {
label: () => {
const ces = cesSection.ratingScale('ces')?.value();
if (ces && ces <= 3) return 'What made the process difficult?';
if (ces && ces >= 5) return 'What made the process easy?';
return 'What factors affected your experience?';
},
suggestions: () => {
const ces = cesSection.ratingScale('ces')?.value();
if (ces && ces <= 3) {
return [
{ id: 'scheduling', name: 'Hard to schedule' },
{ id: 'wait-time', name: 'Long wait time' },
{ id: 'communication', name: 'Poor communication' },
{ id: 'location', name: 'Inconvenient location' },
{ id: 'multiple-visits', name: 'Multiple visits needed' },
{ id: 'paperwork', name: 'Too much paperwork' }
];
}
return [
{ id: 'easy-booking', name: 'Easy booking' },
{ id: 'fast-service', name: 'Fast service' },
{ id: 'good-communication', name: 'Clear communication' },
{ id: 'convenient', name: 'Convenient location' },
{ id: 'one-visit', name: 'Fixed in one visit' },
{ id: 'pickup-delivery', name: 'Pickup/delivery available' }
];
},
isVisible: () => cesSection.ratingScale('ces')?.value() !== null,
alignment: 'center'
});
});
// ============================================
// SECTION 4: Technician Evaluation
// ============================================
const techSection = form.addSubform('technicianEval', {
title: 'Technician Evaluation',
isVisible: () => serviceSection.textbox('technicianName')?.value()?.trim() !== ''
});
techSection.addRow(row => {
row.addTextPanel('techInfo', {
computedValue: () => {
const name = serviceSection.textbox('technicianName')?.value();
return `Rate your experience with ${name || 'the technician'}`;
},
customStyles: { fontStyle: 'italic', color: '#64748b', marginBottom: '8px' }
});
});
techSection.addRow(row => {
row.addMatrixQuestion('technicianRatings', {
label: 'Please rate the technician on the following',
rows: [
{ id: 'professionalism', label: 'Professionalism', isRequired: true },
{ id: 'knowledge', label: 'Technical Knowledge', isRequired: true },
{ id: 'communication', label: 'Communication', isRequired: true },
{ id: 'punctuality', label: 'Punctuality', isRequired: false },
{ id: 'workmanship', label: 'Quality of Work', isRequired: true }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
fullWidth: true
});
});
// ============================================
// SECTION 5: Service Quality Ratings
// ============================================
const qualitySection = form.addSubform('qualityRatings', {
title: 'Service Quality'
});
qualitySection.addRow(row => {
row.addStarRating('repairQuality', {
label: 'Quality of Repair',
maxStars: 5,
size: 'lg',
showConfettiOnMax: true
}, '1fr');
row.addStarRating('turnaroundTime', {
label: 'Turnaround Time',
maxStars: 5,
size: 'lg'
}, '1fr');
});
qualitySection.addRow(row => {
row.addStarRating('communicationRating', {
label: 'Communication & Updates',
maxStars: 5,
size: 'lg'
}, '1fr');
row.addStarRating('pricingTransparency', {
label: 'Pricing Transparency',
maxStars: 5,
size: 'lg'
}, '1fr');
});
// Pricing satisfaction
qualitySection.addRow(row => {
row.addThumbRating('priceFair', {
label: 'Was the final price fair for the service provided?',
showLabels: true,
upLabel: 'Yes, fair price',
downLabel: 'No, too expensive',
alignment: 'center'
});
});
// Price concern follow-up
qualitySection.addRow(row => {
row.addTextarea('priceComments', {
label: 'What would you consider a fair price?',
placeholder: 'Share your thoughts on pricing...',
rows: 2,
isVisible: () => qualitySection.thumbRating('priceFair')?.value() === 'down'
});
});
// ============================================
// SECTION 6: Overall Satisfaction
// ============================================
const overallSection = form.addSubform('overallSatisfaction', {
title: 'Overall Satisfaction'
});
overallSection.addRow(row => {
row.addRatingScale('npsScore', {
label: 'How likely are you to recommend our repair service?',
preset: 'nps',
showCategoryLabel: true,
showSegmentColors: true,
alignment: 'center',
isRequired: true
});
});
overallSection.addRow(row => {
row.addRadioButton('wouldUseAgain', {
label: 'Would you use our repair service again?',
options: [
{ id: 'definitely', name: 'Definitely' },
{ id: 'probably', name: 'Probably' },
{ id: 'not-sure', name: 'Not sure' },
{ id: 'probably-not', name: 'Probably not' },
{ id: 'no', name: 'No' }
],
orientation: 'horizontal'
});
});
// Comments section
overallSection.addSpacer({ height: '16px' });
overallSection.addRow(row => {
row.addTextarea('comments', {
label: () => {
const nps = overallSection.ratingScale('npsScore')?.npsCategory();
if (nps === 'promoter') return 'What did we do well? Share your positive experience!';
if (nps === 'detractor') return 'How can we make things right? Your feedback helps us improve.';
return 'Any additional comments or suggestions?';
},
placeholder: 'Share your thoughts...',
rows: 4,
autoExpand: true
});
});
// ============================================
// SECTION 7: Contact Permission
// ============================================
const contactSection = form.addSubform('contactSection', {
title: 'Follow-Up'
});
contactSection.addRow(row => {
row.addCheckbox('allowFollowUp', {
label: 'A manager may contact me to discuss my feedback'
});
});
contactSection.addRow(row => {
row.addEmail('contactEmail', {
label: 'Email address',
placeholder: 'your@email.com',
isVisible: () => contactSection.checkbox('allowFollowUp')?.value() === true,
isRequired: () => contactSection.checkbox('allowFollowUp')?.value() === true
}, '1fr');
row.addTextbox('contactPhone', {
label: 'Phone number (optional)',
placeholder: 'Your phone number',
isVisible: () => contactSection.checkbox('allowFollowUp')?.value() === true
}, '1fr');
});
// ============================================
// SECTION 8: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => overallSection.ratingScale('npsScore')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const nps = overallSection.ratingScale('npsScore')?.value();
const category = overallSection.ratingScale('npsScore')?.npsCategory();
const ces = cesSection.ratingScale('ces')?.value();
const resolved = outcomeSection.radioButton('repairResolved')?.value();
const repairQuality = qualitySection.starRating('repairQuality')?.value();
if (nps === null || nps === undefined) return '';
let emoji = category === 'promoter' ? '🔧' : category === 'passive' ? '🛠️' : '⚠️';
let summary = `${emoji} Service Feedback Summary\n`;
summary += `${'═'.repeat(28)}\n\n`;
// Resolution status
const resolvedLabels: Record<string, string> = {
'yes': '✅ Issue Resolved',
'partial': '⚠️ Partially Resolved',
'no': '❌ Issue Not Resolved'
};
if (resolved) {
summary += `${resolvedLabels[resolved] || resolved}\n`;
}
// CES
if (ces !== null && ces !== undefined) {
const effort = ces >= 5 ? 'Easy' : ces >= 3 ? 'Moderate' : 'Difficult';
summary += `Effort Level: ${effort} (${ces}/7)\n`;
}
// Repair quality
if (repairQuality) {
summary += `Repair Quality: ${'★'.repeat(repairQuality)}${'☆'.repeat(5 - repairQuality)}\n`;
}
// NPS
summary += `\nRecommendation: ${nps}/10 (${category})`;
return summary;
},
customStyles: () => {
const category = overallSection.ratingScale('npsScore')?.npsCategory();
const base = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') return { ...base, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
if (category === 'passive') return { ...base, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
return { ...base, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => overallSection.ratingScale('npsScore')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your feedback helps us deliver better repair services. We appreciate you taking the time to share your experience with us.'
});
}