export function treatmentOutcomeSurvey(form: FormTs) {
// Treatment Outcome Survey - Before/After symptom tracking
// Demonstrates: Slider x4 (before/after), MatrixQuestion, StarRating x2,
// EmojiRating, CheckboxList, RadioButton, computed values, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Treatment Outcome Survey',
computedValue: () => 'Help us understand how your treatment is working. Your feedback guides your care plan.',
customStyles: {
background: 'linear-gradient(135deg, #0891b2 0%, #0e7490 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Baseline Symptoms (Before)
// ============================================
const baselineSection = form.addSubform('baselineSection', {
title: 'Baseline Symptoms (Before Treatment)',
customStyles: {
backgroundColor: '#f0f9ff',
padding: '16px',
borderRadius: '8px',
borderLeft: '4px solid #0ea5e9'
}
});
baselineSection.addRow(row => {
row.addTextPanel('baselineInfo', {
computedValue: () => 'Recall how you felt BEFORE starting this treatment',
customStyles: {
color: '#0369a1',
fontSize: '14px',
fontStyle: 'italic',
marginBottom: '8px'
}
});
});
baselineSection.addRow(row => {
row.addSlider('painBefore', {
label: 'Pain level before treatment',
min: 0,
max: 10,
step: 1,
showValue: true,
unit: '/10',
defaultValue: 5
});
});
baselineSection.addRow(row => {
row.addTextPanel('painBeforeLabel', {
computedValue: () => {
const val = baselineSection.slider('painBefore')?.value();
if (val === 0) return '0 = No pain';
if (val !== null && val !== undefined && val <= 3) return 'Mild discomfort';
if (val !== null && val !== undefined && val <= 6) return 'Moderate pain';
if (val !== null && val !== undefined && val <= 8) return 'Severe pain';
return 'Very severe pain';
},
customStyles: {
textAlign: 'center',
fontSize: '13px',
color: '#64748b',
marginTop: '-8px'
}
});
});
baselineSection.addRow(row => {
row.addSlider('functionBefore', {
label: 'Daily functioning ability before treatment',
min: 0,
max: 100,
step: 10,
showValue: true,
unit: '%',
defaultValue: 50
});
});
// ============================================
// SECTION 2: Current Symptoms (After)
// ============================================
const currentSection = form.addSubform('currentSection', {
title: 'Current Symptoms (After Treatment)',
customStyles: {
backgroundColor: '#f0fdf4',
padding: '16px',
borderRadius: '8px',
borderLeft: '4px solid #22c55e'
}
});
currentSection.addRow(row => {
row.addTextPanel('currentInfo', {
computedValue: () => 'Rate how you feel NOW, after treatment',
customStyles: {
color: '#15803d',
fontSize: '14px',
fontStyle: 'italic',
marginBottom: '8px'
}
});
});
currentSection.addRow(row => {
row.addSlider('painAfter', {
label: 'Current pain level',
min: 0,
max: 10,
step: 1,
showValue: true,
unit: '/10',
defaultValue: 3
});
});
currentSection.addRow(row => {
row.addSlider('functionAfter', {
label: 'Current daily functioning ability',
min: 0,
max: 100,
step: 10,
showValue: true,
unit: '%',
defaultValue: 70
});
});
// ============================================
// SECTION 3: Improvement Calculation
// ============================================
const improvementSection = form.addSubform('improvementSection', {
title: 'Your Progress'
});
improvementSection.addRow(row => {
row.addTextPanel('improvementCalc', {
computedValue: () => {
const painBefore = baselineSection.slider('painBefore')?.value() ?? 5;
const painAfter = currentSection.slider('painAfter')?.value() ?? 5;
const funcBefore = baselineSection.slider('functionBefore')?.value() ?? 50;
const funcAfter = currentSection.slider('functionAfter')?.value() ?? 50;
const painImprovement = painBefore > 0 ? Math.round(((painBefore - painAfter) / painBefore) * 100) : 0;
const funcImprovement = funcBefore > 0 ? Math.round(((funcAfter - funcBefore) / funcBefore) * 100) : 0;
let painEmoji = painImprovement >= 50 ? '🎉' : painImprovement >= 25 ? '👍' : painImprovement > 0 ? '📈' : '⚠️';
let funcEmoji = funcImprovement >= 50 ? '🎉' : funcImprovement >= 25 ? '👍' : funcImprovement > 0 ? '📈' : '⚠️';
let summary = `📊 Treatment Progress\n`;
summary += `${'─'.repeat(30)}\n\n`;
summary += `${painEmoji} Pain: ${painBefore}/10 → ${painAfter}/10 (${painImprovement > 0 ? '+' : ''}${painImprovement}% ${painImprovement >= 0 ? 'improvement' : 'change'})\n\n`;
summary += `${funcEmoji} Function: ${funcBefore}% → ${funcAfter}% (${funcImprovement > 0 ? '+' : ''}${funcImprovement}% improvement)`;
return summary;
},
customStyles: () => {
const painBefore = baselineSection.slider('painBefore')?.value() ?? 5;
const painAfter = currentSection.slider('painAfter')?.value() ?? 5;
const improvement = painBefore > 0 ? Math.round(((painBefore - painAfter) / painBefore) * 100) : 0;
const base = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px',
textAlign: 'center'
};
if (improvement >= 50) return { ...base, backgroundColor: '#dcfce7', borderLeft: '4px solid #22c55e' };
if (improvement >= 25) return { ...base, backgroundColor: '#fef9c3', borderLeft: '4px solid #eab308' };
if (improvement > 0) return { ...base, backgroundColor: '#e0f2fe', borderLeft: '4px solid #0ea5e9' };
return { ...base, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// SECTION 4: Symptom Details
// ============================================
const symptomsSection = form.addSubform('symptomsSection', {
title: 'Specific Symptoms'
});
symptomsSection.addRow(row => {
row.addMatrixQuestion('symptomChanges', {
label: 'How have these symptoms changed since treatment?',
rows: [
{ id: 'primary', label: 'Primary symptom/condition', isRequired: true },
{ id: 'energy', label: 'Energy levels' },
{ id: 'sleep', label: 'Sleep quality' },
{ id: 'mood', label: 'Mood/emotional state' },
{ id: 'appetite', label: 'Appetite' },
{ id: 'mobility', label: 'Mobility/movement' }
],
columns: [
{ id: 'much-worse', label: 'Much Worse' },
{ id: 'worse', label: 'Worse' },
{ id: 'same', label: 'Same' },
{ id: 'better', label: 'Better' },
{ id: 'much-better', label: 'Much Better' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 5: Side Effects
// ============================================
const sideEffectsSection = form.addSubform('sideEffectsSection', {
title: 'Side Effects'
});
sideEffectsSection.addRow(row => {
row.addRadioButton('hasSideEffects', {
label: 'Have you experienced any side effects from the treatment?',
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'
});
});
sideEffectsSection.addRow(row => {
row.addCheckboxList('sideEffectTypes', {
label: 'Which side effects have you experienced? (Select all that apply)',
options: [
{ id: 'nausea', name: 'Nausea/stomach upset' },
{ id: 'headache', name: 'Headache' },
{ id: 'fatigue', name: 'Fatigue/tiredness' },
{ id: 'dizziness', name: 'Dizziness' },
{ id: 'sleep-issues', name: 'Sleep disturbances' },
{ id: 'appetite', name: 'Appetite changes' },
{ id: 'skin', name: 'Skin reactions' },
{ id: 'other', name: 'Other' }
],
orientation: 'vertical',
isVisible: () => {
const val = sideEffectsSection.radioButton('hasSideEffects')?.value();
return val !== null && val !== 'none';
}
});
});
sideEffectsSection.addSpacer({ isVisible: () => {
const val = sideEffectsSection.radioButton('hasSideEffects')?.value();
return val !== null && val !== 'none';
}});
sideEffectsSection.addRow(row => {
row.addTextarea('sideEffectDetails', {
label: 'Please describe your side effects in more detail',
placeholder: 'Include severity, duration, and any patterns you\'ve noticed...',
rows: 2,
isVisible: () => {
const val = sideEffectsSection.radioButton('hasSideEffects')?.value();
return val !== null && val !== 'none';
}
});
});
// ============================================
// SECTION 6: Overall Assessment
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Assessment'
});
overallSection.addRow(row => {
row.addEmojiRating('overallWellbeing', {
label: 'How would you rate your overall wellbeing today?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
overallSection.addRow(row => {
row.addStarRating('treatmentSatisfaction', {
label: 'Overall satisfaction with your treatment',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
row.addStarRating('careTeamRating', {
label: 'Rating of your care team',
maxStars: 5,
size: 'lg',
alignment: 'center'
}, '1fr');
});
overallSection.addRow(row => {
row.addRadioButton('treatmentContinue', {
label: 'Would you like to continue with this treatment?',
options: [
{ id: 'yes-working', name: 'Yes, it\'s working well' },
{ id: 'yes-wait', name: 'Yes, but need more time to see results' },
{ id: 'unsure', name: 'Unsure, need to discuss with provider' },
{ id: 'no', name: 'No, prefer to try something different' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 7: Additional Comments
// ============================================
const commentsSection = form.addSubform('commentsSection', {
title: 'Additional Comments'
});
commentsSection.addSpacer();
commentsSection.addRow(row => {
row.addTextarea('additionalComments', {
label: 'Is there anything else you\'d like your care team to know?',
placeholder: 'Share any concerns, questions, or observations about your treatment...',
rows: 3
});
});
// ============================================
// SUMMARY SECTION
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Treatment Outcome Summary'
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const painBefore = baselineSection.slider('painBefore')?.value() ?? 5;
const painAfter = currentSection.slider('painAfter')?.value() ?? 5;
const funcBefore = baselineSection.slider('functionBefore')?.value() ?? 50;
const funcAfter = currentSection.slider('functionAfter')?.value() ?? 50;
const wellbeing = overallSection.emojiRating('overallWellbeing')?.value();
const satisfaction = overallSection.starRating('treatmentSatisfaction')?.value();
const continueChoice = overallSection.radioButton('treatmentContinue')?.value();
const painImprovement = painBefore > 0 ? Math.round(((painBefore - painAfter) / painBefore) * 100) : 0;
let emoji = painImprovement >= 50 ? '🎉' : painImprovement >= 25 ? '📈' : painImprovement > 0 ? '📊' : '⚠️';
let summary = `${emoji} Treatment Outcome Summary\n`;
summary += `${'═'.repeat(35)}\n\n`;
summary += `📉 Pain: ${painBefore}/10 → ${painAfter}/10\n`;
summary += `📈 Function: ${funcBefore}% → ${funcAfter}%\n`;
summary += `🎯 Overall Improvement: ${painImprovement}%\n`;
if (wellbeing) {
const wellbeingLabels: Record<string, string> = {
'very-bad': '😢 Struggling',
'bad': '😕 Not great',
'neutral': '😐 Fair',
'good': '🙂 Good',
'excellent': '😊 Excellent'
};
summary += `\n${wellbeingLabels[wellbeing] || wellbeing}`;
}
if (satisfaction) {
summary += `\n⭐ Satisfaction: ${satisfaction}/5`;
}
if (continueChoice) {
const choiceLabels: Record<string, string> = {
'yes-working': '✅ Wants to continue',
'yes-wait': '⏳ Needs more time',
'unsure': '❓ Needs discussion',
'no': '❌ Prefers alternative'
};
summary += `\n${choiceLabels[continueChoice] || ''}`;
}
return summary;
},
customStyles: () => {
const painBefore = baselineSection.slider('painBefore')?.value() ?? 5;
const painAfter = currentSection.slider('painAfter')?.value() ?? 5;
const improvement = painBefore > 0 ? Math.round(((painBefore - painAfter) / painBefore) * 100) : 0;
const base = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (improvement >= 50) return { ...base, backgroundColor: '#dcfce7', borderLeft: '4px solid #22c55e' };
if (improvement >= 25) return { ...base, backgroundColor: '#fef9c3', borderLeft: '4px solid #eab308' };
if (improvement > 0) return { ...base, backgroundColor: '#e0f2fe', borderLeft: '4px solid #0ea5e9' };
return { ...base, backgroundColor: '#fef2f2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Treatment Feedback'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank you for completing your treatment outcome survey!',
message: 'Your feedback helps us understand how your treatment is working and guides future care decisions. Your healthcare provider will review your responses. If you have urgent concerns, please contact your care team directly.'
});
}