export function clinicalTrialFeedbackSurvey(form: FormTs) {
// Clinical Trial Participant Feedback - Research study experience evaluation
// Demonstrates: MatrixQuestion, StarRating, EmojiRating, RatingScale, Slider, conditional visibility
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Study Participant Feedback',
computedValue: () => 'Your feedback helps us improve the research experience for all participants. All responses are confidential.',
customStyles: {
backgroundColor: '#0891b2',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Study Information
// ============================================
const studySection = form.addSubform('studySection', {
title: 'Study Information'
});
studySection.addRow(row => {
row.addDropdown('studyPhase', {
label: 'Where are you in the study?',
options: [
{ id: 'just-enrolled', name: 'Just enrolled (after consent)' },
{ id: 'early-treatment', name: 'Early treatment phase' },
{ id: 'mid-study', name: 'Mid-study' },
{ id: 'near-end', name: 'Near study completion' },
{ id: 'completed', name: 'Completed the study' },
{ id: 'withdrew', name: 'Withdrew from study' }
],
isRequired: true,
placeholder: 'Select your current phase...'
}, '1fr');
row.addRadioButton('visitCount', {
label: 'Approximate number of study visits so far',
options: [
{ id: '1-2', name: '1-2 visits' },
{ id: '3-5', name: '3-5 visits' },
{ id: '6-10', name: '6-10 visits' },
{ id: 'more-10', name: 'More than 10' }
],
orientation: 'vertical'
}, '1fr');
});
// Withdrawal reason (conditional)
studySection.addSpacer();
studySection.addRow(row => {
row.addCheckboxList('withdrawReason', {
label: 'Why did you withdraw from the study?',
options: [
{ id: 'side-effects', name: 'Side effects/adverse reactions' },
{ id: 'time-commitment', name: 'Too much time commitment' },
{ id: 'travel', name: 'Travel/distance to site' },
{ id: 'personal', name: 'Personal/life circumstances' },
{ id: 'no-benefit', name: 'Felt no benefit' },
{ id: 'staff-issues', name: 'Issues with study staff' },
{ id: 'other', name: 'Other reasons' }
],
orientation: 'vertical',
isVisible: () => studySection.dropdown('studyPhase')?.value() === 'withdrew'
});
});
// ============================================
// SECTION 2: Informed Consent Experience
// ============================================
const consentSection = form.addSubform('consentSection', {
title: 'Informed Consent Process',
customStyles: () => {
const understanding = consentSection.ratingScale('consentUnderstanding')?.value();
if (understanding && understanding >= 4) return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (understanding && understanding <= 2) return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#f0f9ff', padding: '16px', borderRadius: '8px' };
}
});
consentSection.addRow(row => {
row.addRatingScale('consentUnderstanding', {
preset: 'likert-5',
label: 'How well did you understand the study before agreeing to participate?',
lowLabel: 'Very confused',
highLabel: 'Completely clear',
size: 'md',
alignment: 'center',
isRequired: true
});
});
consentSection.addSpacer({ height: '16px' });
consentSection.addRow(row => {
row.addMatrixQuestion('consentMatrix', {
label: 'Please rate the consent process:',
rows: [
{ id: 'explained-risks', label: 'Risks were clearly explained', isRequired: true },
{ id: 'explained-benefits', label: 'Potential benefits were explained', isRequired: true },
{ id: 'time-to-decide', label: 'Had enough time to decide', isRequired: true },
{ id: 'questions-answered', label: 'All questions were answered', isRequired: true },
{ id: 'no-pressure', label: 'Felt no pressure to participate', isRequired: true }
],
columns: [
{ id: 'strongly-agree', label: 'Strongly Agree' },
{ id: 'agree', label: 'Agree' },
{ id: 'neutral', label: 'Neutral' },
{ id: 'disagree', label: 'Disagree' },
{ id: 'strongly-disagree', label: 'Strongly Disagree' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 3: Study Staff & Communication
// ============================================
const staffSection = form.addSubform('staffSection', {
title: 'Study Staff & Communication',
isVisible: () => studySection.dropdown('studyPhase')?.value() !== null
});
staffSection.addRow(row => {
row.addStarRating('staffRating', {
label: 'How would you rate the study staff overall?',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true
});
});
staffSection.addSpacer({ height: '16px' });
staffSection.addRow(row => {
row.addMatrixQuestion('staffMatrix', {
label: 'Rate the research team on:',
rows: [
{ id: 'professionalism', label: 'Professionalism', isRequired: true },
{ id: 'responsiveness', label: 'Response to questions/concerns', isRequired: true },
{ id: 'empathy', label: 'Empathy and care', isRequired: true },
{ id: 'communication', label: 'Clear communication', isRequired: false },
{ id: 'punctuality', label: 'Appointment punctuality', isRequired: false }
],
columns: [
{ id: 'excellent', label: 'Excellent' },
{ id: 'good', label: 'Good' },
{ id: 'fair', label: 'Fair' },
{ id: 'poor', label: 'Poor' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 4: Side Effects & Safety
// ============================================
const safetySection = form.addSubform('safetySection', {
title: 'Side Effects & Safety',
isVisible: () => {
const phase = studySection.dropdown('studyPhase')?.value();
return phase !== null && phase !== 'just-enrolled';
}
});
safetySection.addRow(row => {
row.addRadioButton('experiencedSideEffects', {
label: 'Have you experienced any side effects during the study?',
options: [
{ id: 'none', name: 'No side effects' },
{ id: 'mild', name: 'Mild side effects' },
{ id: 'moderate', name: 'Moderate side effects' },
{ id: 'severe', name: 'Severe side effects' }
],
orientation: 'horizontal',
isRequired: true
});
});
// Side effect handling (conditional)
safetySection.addSpacer({ height: '16px' });
safetySection.addRow(row => {
row.addThumbRating('sideEffectsAddressed', {
label: 'Were your side effects addressed promptly and appropriately?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
size: 'lg',
alignment: 'center',
isVisible: () => {
const se = safetySection.radioButton('experiencedSideEffects')?.value();
return se === 'mild' || se === 'moderate' || se === 'severe';
}
});
});
safetySection.addRow(row => {
row.addSlider('sideEffectImpact', {
label: 'How much have side effects impacted your daily life?',
min: 0,
max: 10,
step: 1,
showValue: true,
defaultValue: 0,
isVisible: () => {
const se = safetySection.radioButton('experiencedSideEffects')?.value();
return se === 'mild' || se === 'moderate' || se === 'severe';
}
});
});
safetySection.addSpacer();
safetySection.addRow(row => {
row.addTextarea('sideEffectDetails', {
label: () => {
const severity = safetySection.radioButton('experiencedSideEffects')?.value();
if (severity === 'severe') return 'Please describe your side effects (IMPORTANT for safety review):';
return 'Any additional details about side effects? (Optional)';
},
placeholder: 'Describe symptoms, timing, duration...',
rows: 3,
autoExpand: true,
isVisible: () => {
const se = safetySection.radioButton('experiencedSideEffects')?.value();
return se !== 'none' && se !== null;
},
isRequired: () => safetySection.radioButton('experiencedSideEffects')?.value() === 'severe'
});
});
// ============================================
// SECTION 5: Study Logistics
// ============================================
const logisticsSection = form.addSubform('logisticsSection', {
title: 'Study Logistics',
isVisible: () => staffSection.starRating('staffRating')?.value() !== null
});
logisticsSection.addRow(row => {
row.addEmojiRating('schedulingEase', {
label: 'How easy is it to schedule study visits?',
preset: 'effort',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
logisticsSection.addSpacer({ height: '16px' });
logisticsSection.addRow(row => {
row.addRadioButton('visitDuration', {
label: 'Are visit durations reasonable?',
options: [
{ id: 'too-short', name: 'Too short (feel rushed)' },
{ id: 'just-right', name: 'Just right' },
{ id: 'too-long', name: 'Too long' }
],
orientation: 'horizontal'
}, '1fr');
row.addRadioButton('travelBurden', {
label: 'Is travel to the study site manageable?',
options: [
{ id: 'easy', name: 'Easy' },
{ id: 'manageable', name: 'Manageable' },
{ id: 'difficult', name: 'Difficult' }
],
orientation: 'horizontal'
}, '1fr');
});
// ============================================
// SECTION 6: Overall Experience
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Experience',
isVisible: () => logisticsSection.emojiRating('schedulingEase')?.value() !== null,
customStyles: () => {
const nps = overallSection.ratingScale('participantNps')?.npsCategory();
if (nps === 'promoter') return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (nps === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#f0f9ff', padding: '16px', borderRadius: '8px' };
}
});
overallSection.addRow(row => {
row.addRatingScale('participantNps', {
preset: 'nps',
label: 'How likely are you to recommend participating in research studies to others?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
overallSection.addSpacer({ height: '20px' });
overallSection.addRow(row => {
row.addRadioButton('wouldParticipateAgain', {
label: 'Would you participate in another research study?',
options: [
{ id: 'definitely', name: 'Definitely yes' },
{ id: 'probably', name: 'Probably yes' },
{ id: 'unsure', name: 'Unsure' },
{ id: 'probably-not', name: 'Probably not' },
{ id: 'definitely-not', name: 'Definitely not' }
],
orientation: 'horizontal'
});
});
overallSection.addSpacer();
overallSection.addRow(row => {
row.addTextarea('overallFeedback', {
label: () => {
const nps = overallSection.ratingScale('participantNps')?.npsCategory();
if (nps === 'promoter') return "What made your experience positive?";
if (nps === 'detractor') return "What could we have done better?";
return "Any other feedback about your study experience?";
},
placeholder: 'Share your thoughts...',
rows: 3,
autoExpand: true
});
});
// Contact permission
overallSection.addSpacer({ height: '16px' });
overallSection.addRow(row => {
row.addCheckbox('canContact', {
label: 'The study team may contact me to discuss my feedback'
});
});
// ============================================
// SECTION 7: Summary
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Feedback Summary',
isVisible: () => overallSection.ratingScale('participantNps')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summary', {
computedValue: () => {
const phase = studySection.dropdown('studyPhase')?.value();
const consentUnderstanding = consentSection.ratingScale('consentUnderstanding')?.value();
const staffRating = staffSection.starRating('staffRating')?.value();
const sideEffects = safetySection.radioButton('experiencedSideEffects')?.value();
const nps = overallSection.ratingScale('participantNps')?.value();
const category = overallSection.ratingScale('participantNps')?.npsCategory();
const wouldAgain = overallSection.radioButton('wouldParticipateAgain')?.value();
if (!phase || nps === null || nps === undefined) return '';
const phaseLabels: Record<string, string> = {
'just-enrolled': 'Just Enrolled',
'early-treatment': 'Early Treatment',
'mid-study': 'Mid-Study',
'near-end': 'Near Completion',
'completed': 'Completed',
'withdrew': 'Withdrew'
};
const sideEffectLabels: Record<string, string> = {
'none': 'None',
'mild': 'Mild',
'moderate': 'Moderate',
'severe': 'Severe'
};
const againLabels: Record<string, string> = {
'definitely': 'Definitely yes',
'probably': 'Probably yes',
'unsure': 'Unsure',
'probably-not': 'Probably not',
'definitely-not': 'Definitely not'
};
let emoji = '🔬';
if (category === 'promoter') emoji = '💚';
else if (category === 'detractor') emoji = '⚠️';
let summary = `${emoji} Participant Feedback Summary\n`;
summary += `${'═'.repeat(32)}\n\n`;
summary += `Study Phase: ${phaseLabels[phase]}\n`;
if (consentUnderstanding) summary += `Consent Understanding: ${consentUnderstanding}/5\n`;
if (staffRating) summary += `Staff Rating: ${'★'.repeat(staffRating)}${'☆'.repeat(5 - staffRating)}\n`;
if (sideEffects) summary += `Side Effects: ${sideEffectLabels[sideEffects]}\n`;
summary += `\n`;
summary += `NPS Score: ${nps}/10 (${category?.charAt(0).toUpperCase()}${category?.slice(1)})\n`;
if (wouldAgain) summary += `Would Participate Again: ${againLabels[wouldAgain]}`;
return summary;
},
customStyles: () => {
const category = overallSection.ratingScale('participantNps')?.npsCategory();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (category === 'promoter') {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (category === 'detractor') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => overallSection.ratingScale('participantNps')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback',
message: 'Your insights help us improve the research experience for all participants. Your responses will be kept confidential. Thank you for contributing to medical research!'
});
}