export function labTestFeedbackSurvey(form: FormTs) {
// Lab/Test Experience Survey - Healthcare Diagnostics Feedback
// Demonstrates: RatingScale (CES), StarRating, MatrixQuestion, EmojiRating, Slider, ThumbRating
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Lab Test Experience Survey',
computedValue: () => 'Help us improve your diagnostic experience. Your feedback is confidential.',
customStyles: {
backgroundColor: '#0d9488',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Test Information
// ============================================
const testInfoSection = form.addSubform('testInfo', {
title: 'About Your Test'
});
testInfoSection.addRow(row => {
row.addDropdown('testType', {
label: 'What type of test did you have?',
options: [
{ id: 'blood', name: 'Blood Draw / Blood Test' },
{ id: 'urine', name: 'Urine Test' },
{ id: 'imaging', name: 'Imaging (X-ray, MRI, CT)' },
{ id: 'biopsy', name: 'Biopsy / Tissue Sample' },
{ id: 'cardiac', name: 'Cardiac Testing (ECG, Echo)' },
{ id: 'respiratory', name: 'Respiratory / Pulmonary Test' },
{ id: 'home', name: 'At-Home Collection Kit' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select test type',
isRequired: true
}, '1fr');
row.addDatepicker('testDate', {
label: 'When was your test?',
maxDate: () => new Date().toISOString().split('T')[0]
}, '1fr');
});
testInfoSection.addRow(row => {
row.addRadioButton('visitReason', {
label: 'What was the purpose of this test?',
options: [
{ id: 'routine', name: 'Routine screening/checkup' },
{ id: 'diagnosis', name: 'Diagnosis of symptoms' },
{ id: 'monitoring', name: 'Monitoring existing condition' },
{ id: 'preop', name: 'Pre-operative requirement' },
{ id: 'followup', name: 'Follow-up from previous test' }
],
orientation: 'horizontal'
});
});
// ============================================
// SECTION 2: Scheduling & Preparation
// ============================================
const schedulingSection = form.addSubform('scheduling', {
title: 'Scheduling & Preparation'
});
schedulingSection.addRow(row => {
row.addRatingScale('schedulingEffort', {
label: 'How easy was it to schedule your appointment?',
preset: 'ces',
lowLabel: 'Very Difficult',
highLabel: 'Very Easy',
alignment: 'center'
});
});
schedulingSection.addRow(row => {
row.addMatrixQuestion('prepRatings', {
label: 'Rate the preparation process:',
rows: [
{ id: 'instructions', label: 'Clarity of prep instructions', isRequired: true },
{ id: 'reminder', label: 'Appointment reminders' },
{ id: 'fasting', label: 'Fasting/dietary requirements info' },
{ id: 'location', label: 'Finding the lab location' }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 3: Wait Time & Check-In
// ============================================
const waitSection = form.addSubform('waitTime', {
title: 'Check-In & Wait Time'
});
waitSection.addRow(row => {
row.addSlider('actualWait', {
label: 'How long did you wait past your appointment time?',
min: 0,
max: 60,
step: 5,
unit: 'minutes',
showValue: true,
defaultValue: 10
}, '1fr');
row.addEmojiRating('waitSatisfaction', {
label: 'How did you feel about the wait?',
preset: 'satisfaction',
size: 'md',
alignment: 'center'
}, '1fr');
});
waitSection.addRow(row => {
row.addStarRating('checkinProcess', {
label: 'Rate the check-in process',
maxStars: 5,
size: 'md',
alignment: 'center'
});
});
// Long wait follow-up
const longWaitSection = form.addSubform('longWait', {
title: 'About Your Wait',
isVisible: () => {
const wait = waitSection.slider('actualWait')?.value() ?? 0;
return wait >= 20;
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
longWaitSection.addRow(row => {
row.addCheckboxList('waitIssues', {
label: 'What contributed to the long wait?',
options: [
{ id: 'busy', name: 'Lab was very busy' },
{ id: 'staff', name: 'Staff shortage' },
{ id: 'equipment', name: 'Equipment issues' },
{ id: 'walkins', name: 'Too many walk-ins' },
{ id: 'unknown', name: 'No explanation given' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 4: Sample Collection Experience
// ============================================
const collectionSection = form.addSubform('collection', {
title: 'Sample Collection Experience',
isVisible: () => {
const testType = testInfoSection.dropdown('testType')?.value();
return testType !== 'imaging' && testType !== 'home';
}
});
collectionSection.addRow(row => {
row.addMatrixQuestion('collectionRatings', {
label: 'Rate the collection process:',
rows: [
{ id: 'explanation', label: 'Procedure explanation', isRequired: true },
{ id: 'comfort', label: 'Physical comfort' },
{ id: 'technique', label: 'Staff technique/skill' },
{ id: 'care', label: 'Staff care and attention' },
{ id: 'privacy', label: 'Privacy during procedure' }
],
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// Blood draw specific - pain/anxiety
const bloodDrawSection = form.addSubform('bloodDraw', {
title: 'Blood Draw Details',
isVisible: () => testInfoSection.dropdown('testType')?.value() === 'blood',
customStyles: { backgroundColor: '#f0f9ff', padding: '16px', borderRadius: '8px' }
});
bloodDrawSection.addRow(row => {
row.addSlider('painLevel', {
label: 'Pain level during the draw',
min: 0,
max: 10,
step: 1,
showValue: true,
defaultValue: 2
}, '1fr');
row.addSlider('anxietyLevel', {
label: 'Your anxiety level',
min: 0,
max: 10,
step: 1,
showValue: true,
defaultValue: 3
}, '1fr');
});
bloodDrawSection.addRow(row => {
row.addRadioButton('numAttempts', {
label: 'How many attempts were needed to draw blood?',
options: [
{ id: '1', name: 'First try' },
{ id: '2', name: '2 attempts' },
{ id: '3', name: '3+ attempts' }
],
orientation: 'horizontal'
});
});
// ============================================
// SECTION 5: Results Delivery
// ============================================
const resultsSection = form.addSubform('results', {
title: 'Results Delivery'
});
resultsSection.addRow(row => {
row.addRatingScale('resultsEffort', {
label: 'How easy was it to access your results?',
preset: 'ces',
lowLabel: 'Very Difficult',
highLabel: 'Very Easy',
alignment: 'center'
});
});
resultsSection.addRow(row => {
row.addRadioButton('resultsMethod', {
label: 'How did you receive your results?',
options: [
{ id: 'portal', name: 'Patient portal' },
{ id: 'app', name: 'Mobile app' },
{ id: 'call', name: 'Phone call' },
{ id: 'letter', name: 'Letter/mail' },
{ id: 'inperson', name: 'In-person appointment' },
{ id: 'waiting', name: 'Still waiting' }
],
orientation: 'horizontal'
});
});
resultsSection.addRow(row => {
row.addSlider('resultsDays', {
label: 'How many days until you received results?',
min: 0,
max: 14,
step: 1,
unit: 'days',
showValue: true,
defaultValue: 3,
isVisible: () => resultsSection.radioButton('resultsMethod')?.value() !== 'waiting'
}, '1fr');
row.addStarRating('resultsSpeed', {
label: 'Satisfaction with turnaround time',
maxStars: 5,
size: 'md',
alignment: 'center',
isVisible: () => resultsSection.radioButton('resultsMethod')?.value() !== 'waiting'
}, '1fr');
});
// ============================================
// SECTION 6: Results Clarity
// ============================================
const claritySection = form.addSubform('clarity', {
title: 'Understanding Your Results',
isVisible: () => resultsSection.radioButton('resultsMethod')?.value() !== 'waiting'
});
claritySection.addRow(row => {
row.addMatrixQuestion('clarityRatings', {
label: 'Rate how well you understood:',
rows: [
{ id: 'numbers', label: 'Test values/numbers', isRequired: true },
{ id: 'ranges', label: 'Normal vs abnormal ranges' },
{ id: 'meaning', label: 'What results mean for your health' },
{ id: 'nextSteps', label: 'Recommended next steps' },
{ id: 'terminology', label: 'Medical terminology used' }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: 'unclear', label: 'Unclear' },
{ id: 'somewhat', label: 'Somewhat Clear' },
{ id: 'clear', label: 'Clear' },
{ id: 'very', label: 'Very Clear' }
],
striped: true,
fullWidth: true
});
});
claritySection.addRow(row => {
row.addThumbRating('neededHelp', {
label: 'Did you need to contact someone to explain results?',
size: 'lg',
showLabels: true,
upLabel: 'Yes, I needed help',
downLabel: 'No, I understood them',
alignment: 'center'
});
});
// ============================================
// SECTION 7: Overall Experience
// ============================================
const overallSection = form.addSubform('overall', {
title: 'Overall Experience'
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'Overall, how would you rate your lab experience?',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
overallSection.addRow(row => {
row.addRatingScale('recommendLab', {
label: 'How likely are you to recommend this lab to others?',
preset: 'nps',
showCategoryLabel: true,
showSegmentColors: true,
alignment: 'center'
});
});
// ============================================
// SECTION 8: Open Feedback
// ============================================
const feedbackSection = form.addSubform('feedback', {
title: 'Additional Comments'
});
feedbackSection.addSpacer({ height: '8px' });
feedbackSection.addRow(row => {
row.addTextarea('comments', {
label: 'Any suggestions to improve our lab services?',
placeholder: 'Share what went well or what could be better...',
rows: 4
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Your Feedback Summary',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const testType = testInfoSection.dropdown('testType')?.value();
const schedulingEffort = schedulingSection.ratingScale('schedulingEffort')?.value();
const waitTime = waitSection.slider('actualWait')?.value();
const waitSatisfaction = waitSection.emojiRating('waitSatisfaction')?.value();
const resultsEffort = resultsSection.ratingScale('resultsEffort')?.value();
const resultsDays = resultsSection.slider('resultsDays')?.value();
const overallRating = overallSection.starRating('overallRating')?.value();
const nps = overallSection.ratingScale('recommendLab')?.npsCategory();
const neededHelp = claritySection.thumbRating('neededHelp')?.value();
const testLabels: Record<string, string> = {
'blood': 'Blood Draw',
'urine': 'Urine Test',
'imaging': 'Imaging',
'biopsy': 'Biopsy',
'cardiac': 'Cardiac Test',
'respiratory': 'Respiratory Test',
'home': 'At-Home Kit',
'other': 'Other Test'
};
const waitLabels: Record<string, string> = {
'very-bad': 'Very Dissatisfied',
'bad': 'Dissatisfied',
'neutral': 'Neutral',
'good': 'Satisfied',
'excellent': 'Very Satisfied'
};
let summary = `Lab Experience Summary\n`;
summary += `${''.repeat(22)}\n\n`;
if (testType) {
summary += ` Test Type: ${testLabels[testType] || testType}\n`;
}
summary += `\n Scheduling:\n`;
if (schedulingEffort) {
const effortLabel = schedulingEffort >= 5 ? 'Easy' : schedulingEffort >= 3 ? 'Moderate' : 'Difficult';
summary += ` Effort: ${schedulingEffort}/7 (${effortLabel})\n`;
}
summary += `\n Wait Experience:\n`;
if (waitTime !== null && waitTime !== undefined) {
summary += ` Wait Time: ${waitTime} minutes\n`;
}
if (waitSatisfaction) {
summary += ` Satisfaction: ${waitLabels[waitSatisfaction] || waitSatisfaction}\n`;
}
summary += `\n Results:\n`;
if (resultsEffort) {
const effortLabel = resultsEffort >= 5 ? 'Easy' : resultsEffort >= 3 ? 'Moderate' : 'Difficult';
summary += ` Access Effort: ${resultsEffort}/7 (${effortLabel})\n`;
}
if (resultsDays !== null && resultsDays !== undefined) {
summary += ` Turnaround: ${resultsDays} days\n`;
}
if (neededHelp) {
summary += ` Needed Help: ${neededHelp === 'up' ? 'Yes' : 'No'}\n`;
}
summary += `\n Overall:\n`;
if (overallRating) {
summary += ` Rating: ${overallRating}/5 stars\n`;
}
if (nps) {
summary += ` NPS: ${nps.charAt(0).toUpperCase() + nps.slice(1)}\n`;
}
return summary;
},
customStyles: () => {
const overallRating = overallSection.starRating('overallRating')?.value() ?? 0;
const baseStyles = {
padding: '20px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (overallRating >= 4) return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
if (overallRating >= 3) return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Lab Feedback'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank you for your feedback!',
message: 'Your input helps us provide better diagnostic services. We appreciate you taking the time to share your experience with us.'
});
}