export function focusGroupScreener(form: FormTs) {
// Focus Group Screening Form
// Demonstrates: Dropdown, RadioButton, CheckboxList, Datepicker, Timepicker, Integer, Email, Textbox, Slider, MatrixQuestion, EmojiRating
// Track qualification status
const qualificationState = form.state<{ qualified: boolean; disqualifyReason: string | null }>({ qualified: true, disqualifyReason: null });
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Research Study Screening',
computedValue: () => 'Thank you for your interest in participating in our research study. Please complete this brief questionnaire to help us determine if you qualify.',
customStyles: {
backgroundColor: '#4f46e5',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// Study information
form.addRow(row => {
row.addTextPanel('studyInfo', {
computedValue: () => `Study Details:\n• Duration: 90-minute focus group session\n• Compensation: $150 gift card\n• Format: In-person or virtual (based on location)\n• Topic: Consumer technology preferences`,
customStyles: {
backgroundColor: '#eef2ff',
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontSize: '14px',
borderLeft: '4px solid #4f46e5'
}
});
});
// ============================================
// SECTION 1: Basic Demographics
// ============================================
const demographicsSection = form.addSubform('demographics', {
title: 'Demographics'
});
demographicsSection.addRow(row => {
row.addDropdown('ageRange', {
label: 'What is your age range?',
options: [
{ id: 'under18', name: 'Under 18' },
{ id: '18-24', name: '18-24' },
{ id: '25-34', name: '25-34' },
{ id: '35-44', name: '35-44' },
{ id: '45-54', name: '45-54' },
{ id: '55-64', name: '55-64' },
{ id: '65plus', name: '65 or older' }
],
placeholder: 'Select age range',
isRequired: true,
onValueChange: (val) => {
if (val === 'under18') {
qualificationState.set({ qualified: false, disqualifyReason: 'age' });
} else if (qualificationState().disqualifyReason === 'age') {
qualificationState.set({ qualified: true, disqualifyReason: null });
}
}
}, '1fr');
row.addDropdown('gender', {
label: 'Gender',
options: [
{ id: 'female', name: 'Female' },
{ id: 'male', name: 'Male' },
{ id: 'nonbinary', name: 'Non-binary' },
{ id: 'other', name: 'Other' },
{ id: 'prefer-not', name: 'Prefer not to say' }
],
placeholder: 'Select gender',
isRequired: true
}, '1fr');
});
demographicsSection.addRow(row => {
row.addDropdown('education', {
label: 'Highest level of education completed',
options: [
{ id: 'high-school', name: 'High school or equivalent' },
{ id: 'some-college', name: 'Some college' },
{ id: 'associates', name: "Associate's degree" },
{ id: 'bachelors', name: "Bachelor's degree" },
{ id: 'masters', name: "Master's degree" },
{ id: 'doctorate', name: 'Doctorate or professional degree' }
],
placeholder: 'Select education level'
}, '1fr');
row.addDropdown('employment', {
label: 'Employment status',
options: [
{ id: 'full-time', name: 'Employed full-time' },
{ id: 'part-time', name: 'Employed part-time' },
{ id: 'self-employed', name: 'Self-employed' },
{ id: 'student', name: 'Student' },
{ id: 'homemaker', name: 'Homemaker' },
{ id: 'retired', name: 'Retired' },
{ id: 'unemployed', name: 'Unemployed' }
],
placeholder: 'Select employment status'
}, '1fr');
});
demographicsSection.addRow(row => {
row.addDropdown('income', {
label: 'Annual household income',
options: [
{ id: 'under25k', name: 'Under $25,000' },
{ id: '25k-50k', name: '$25,000 - $49,999' },
{ id: '50k-75k', name: '$50,000 - $74,999' },
{ id: '75k-100k', name: '$75,000 - $99,999' },
{ id: '100k-150k', name: '$100,000 - $149,999' },
{ id: '150kplus', name: '$150,000 or more' },
{ id: 'prefer-not', name: 'Prefer not to say' }
],
placeholder: 'Select income range'
}, '1fr');
row.addTextbox('location', {
label: 'City/Region',
placeholder: 'e.g., New York, NY'
}, '1fr');
});
// ============================================
// DISQUALIFICATION NOTICE
// ============================================
form.addRow(row => {
row.addTextPanel('disqualified', {
label: 'Thank You',
computedValue: () => 'Thank you for your interest in our study. Unfortunately, based on your responses, you do not meet the eligibility criteria for this particular research project. We appreciate your time and encourage you to check back for future study opportunities.',
customStyles: {
backgroundColor: '#fef3c7',
padding: '20px',
borderRadius: '8px',
textAlign: 'center',
border: '1px solid #f59e0b'
},
isVisible: () => !qualificationState().qualified
});
});
// ============================================
// SECTION 2: Industry & Experience (conditional)
// ============================================
const experienceSection = form.addSubform('experience', {
title: 'Professional Experience',
isVisible: () => qualificationState().qualified && demographicsSection.dropdown('ageRange')?.value() !== null
});
experienceSection.addRow(row => {
row.addRadioButton('industryWork', {
label: 'Do you or does anyone in your household work in any of the following industries?',
options: [
{ id: 'marketing', name: 'Marketing, Advertising, or Market Research' },
{ id: 'tech', name: 'Technology or Software Development' },
{ id: 'media', name: 'Media or Journalism' },
{ id: 'none', name: 'None of the above' }
],
orientation: 'vertical',
isRequired: true,
onValueChange: (val) => {
if (val === 'marketing' || val === 'media') {
qualificationState.set({ qualified: false, disqualifyReason: 'industry' });
} else if (qualificationState().disqualifyReason === 'industry') {
qualificationState.set({ qualified: true, disqualifyReason: null });
}
}
});
});
experienceSection.addRow(row => {
row.addRadioButton('recentFocusGroup', {
label: 'Have you participated in a paid focus group or research study in the past 6 months?',
options: [
{ id: 'yes', name: 'Yes' },
{ id: 'no', name: 'No' }
],
orientation: 'horizontal'
}, '1fr');
row.addInteger('focusGroupCount', {
label: 'How many focus groups have you participated in (lifetime)?',
min: 0,
max: 100,
placeholder: 'Enter number',
isVisible: () => experienceSection.radioButton('recentFocusGroup')?.value() === 'yes'
}, '1fr');
});
// ============================================
// SECTION 3: Technology Usage (topic-specific)
// ============================================
const techSection = form.addSubform('technology', {
title: 'Technology Usage',
isVisible: () => qualificationState().qualified && experienceSection.radioButton('industryWork')?.value() !== null
});
techSection.addRow(row => {
row.addCheckboxList('devices', {
label: 'Which devices do you use regularly? (Select all that apply)',
options: [
{ id: 'smartphone', name: 'Smartphone' },
{ id: 'tablet', name: 'Tablet' },
{ id: 'laptop', name: 'Laptop' },
{ id: 'desktop', name: 'Desktop computer' },
{ id: 'smartwatch', name: 'Smartwatch/Fitness tracker' },
{ id: 'smart-speaker', name: 'Smart speaker (Alexa, Google Home)' },
{ id: 'gaming', name: 'Gaming console' },
{ id: 'smart-tv', name: 'Smart TV' }
],
orientation: 'vertical',
min: 1
}, '1fr');
row.addCheckboxList('activities', {
label: 'Which activities do you do regularly online?',
options: [
{ id: 'shopping', name: 'Online shopping' },
{ id: 'social-media', name: 'Social media' },
{ id: 'streaming', name: 'Video streaming' },
{ id: 'gaming', name: 'Online gaming' },
{ id: 'banking', name: 'Online banking' },
{ id: 'work', name: 'Remote work/Collaboration' },
{ id: 'learning', name: 'Online learning' },
{ id: 'news', name: 'News consumption' }
],
orientation: 'vertical'
}, '1fr');
});
techSection.addRow(row => {
row.addSlider('techSavviness', {
label: 'How would you rate your technology savviness?',
min: 1,
max: 10,
step: 1,
showValue: true,
unit: '/10',
defaultValue: 5
});
});
techSection.addRow(row => {
row.addEmojiRating('techAttitude', {
label: 'How do you feel about trying new technology?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
// ============================================
// SECTION 4: Availability
// ============================================
const availabilitySection = form.addSubform('availability', {
title: 'Availability',
isVisible: () => qualificationState().qualified && techSection.slider('techSavviness')?.value() !== null
});
availabilitySection.addRow(row => {
row.addMatrixQuestion('dayAvailability', {
label: 'Please indicate your availability for each day (sessions run 6-8 PM):',
rows: [
{ id: 'monday', label: 'Monday' },
{ id: 'tuesday', label: 'Tuesday' },
{ id: 'wednesday', label: 'Wednesday' },
{ id: 'thursday', label: 'Thursday' },
{ id: 'friday', label: 'Friday' },
{ id: 'saturday', label: 'Saturday' }
],
columns: [
{ id: 'available', label: 'Available' },
{ id: 'maybe', label: 'Maybe' },
{ id: 'unavailable', label: 'Not Available' }
],
striped: true,
fullWidth: true
});
});
availabilitySection.addRow(row => {
row.addDatepicker('earliestDate', {
label: 'Earliest date you could participate',
minDate: () => new Date().toISOString()
}, '1fr');
row.addRadioButton('format', {
label: 'Preferred session format',
options: [
{ id: 'in-person', name: 'In-person' },
{ id: 'virtual', name: 'Virtual (video call)' },
{ id: 'either', name: 'Either works' }
],
orientation: 'vertical'
}, '1fr');
});
availabilitySection.addRow(row => {
row.addTimepicker('preferredTime', {
label: 'If you have a preferred time, enter it here',
tooltip: 'Sessions typically run between 5 PM and 9 PM'
}, '1fr');
row.addDropdown('timezone', {
label: 'Your timezone',
options: [
{ id: 'est', name: 'Eastern (EST/EDT)' },
{ id: 'cst', name: 'Central (CST/CDT)' },
{ id: 'mst', name: 'Mountain (MST/MDT)' },
{ id: 'pst', name: 'Pacific (PST/PDT)' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select timezone'
}, '1fr');
});
// ============================================
// SECTION 5: Contact Information
// ============================================
const contactSection = form.addSubform('contact', {
title: 'Contact Information',
isVisible: () => qualificationState().qualified && availabilitySection.matrixQuestion('dayAvailability')?.value() !== null
});
contactSection.addRow(row => {
row.addTextbox('firstName', {
label: 'First name',
placeholder: 'Your first name',
isRequired: true
}, '1fr');
row.addTextbox('lastName', {
label: 'Last name',
placeholder: 'Your last name',
isRequired: true
}, '1fr');
});
contactSection.addRow(row => {
row.addEmail('email', {
label: 'Email address',
placeholder: 'your@email.com',
isRequired: true,
tooltip: 'We will use this to contact you about the study'
}, '1fr');
row.addTextbox('phone', {
label: 'Phone number',
placeholder: '(555) 123-4567',
tooltip: 'Optional - for scheduling confirmation'
}, '1fr');
});
contactSection.addRow(row => {
row.addRadioButton('contactPreference', {
label: 'Preferred method of contact',
options: [
{ id: 'email', name: 'Email' },
{ id: 'phone', name: 'Phone' },
{ id: 'text', name: 'Text message' }
],
orientation: 'horizontal'
});
});
// ============================================
// SECTION 6: Additional Information
// ============================================
const additionalSection = form.addSubform('additional', {
title: 'Additional Information',
isVisible: () => qualificationState().qualified && contactSection.email('email')?.value() !== null
});
additionalSection.addRow(row => {
row.addTextarea('whyParticipate', {
label: 'Why are you interested in participating in this study? (Optional)',
placeholder: 'Tell us a bit about your interest...',
rows: 3,
autoExpand: true
});
});
additionalSection.addRow(row => {
row.addCheckboxList('consent', {
label: 'Please confirm the following:',
options: [
{ id: 'accurate', name: 'The information I provided is accurate to the best of my knowledge', isRequired: true },
{ id: 'contact', name: 'I agree to be contacted regarding this study', isRequired: true },
{ id: 'recording', name: 'I understand the session may be recorded for research purposes', isRequired: true },
{ id: 'future', name: 'I would like to be considered for future research opportunities' }
],
orientation: 'vertical'
});
});
// ============================================
// SECTION 7: Eligibility Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Application Summary',
isVisible: () => qualificationState().qualified && contactSection.email('email')?.value() !== null && contactSection.textbox('firstName')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const firstName = contactSection.textbox('firstName')?.value();
const lastName = contactSection.textbox('lastName')?.value();
const age = demographicsSection.dropdown('ageRange')?.value();
const techLevel = techSection.slider('techSavviness')?.value();
const devices = techSection.checkboxList('devices')?.value() || [];
const format = availabilitySection.radioButton('format')?.value();
if (!firstName) return '';
const ageLabels: Record<string, string> = {
'18-24': '18-24', '25-34': '25-34', '35-44': '35-44',
'45-54': '45-54', '55-64': '55-64', '65plus': '65+'
};
const formatLabels: Record<string, string> = {
'in-person': 'In-person', 'virtual': 'Virtual', 'either': 'Flexible'
};
let summary = `Screening Application\n`;
summary += `${'═'.repeat(25)}\n\n`;
summary += `Applicant: ${firstName} ${lastName}\n`;
summary += `Age Range: ${ageLabels[age || ''] || 'N/A'}\n`;
summary += `Tech Level: ${techLevel || 'N/A'}/10\n`;
summary += `Devices: ${devices.length} types\n`;
summary += `Format: ${formatLabels[format || ''] || 'Not specified'}\n\n`;
summary += `Status: Pending Review`;
return summary;
},
customStyles: {
padding: '16px',
borderRadius: '8px',
backgroundColor: '#eef2ff',
borderLeft: '4px solid #4f46e5',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
}
});
});
summarySection.addRow(row => {
row.addTextPanel('nextSteps', {
computedValue: () => 'What happens next?\n\n1. Our team will review your application\n2. If selected, we will contact you within 3-5 business days\n3. You will receive details about session date, time, and compensation\n4. Please keep your availability updated',
customStyles: {
padding: '16px',
borderRadius: '8px',
backgroundColor: '#f0fdf4',
borderLeft: '4px solid #22c55e',
whiteSpace: 'pre-wrap',
fontSize: '14px'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => qualificationState().qualified ? 'Submit Application' : 'Thank you',
isVisible: () => {
if (!qualificationState().qualified) return false;
const consent = additionalSection.checkboxList('consent')?.value() || [];
return consent.includes('accurate') && consent.includes('contact') && consent.includes('recording');
}
});
form.configureCompletionScreen({
type: 'text',
title: 'Application Submitted!',
message: 'Thank you for your interest in our research study. Our team will review your application and contact you within 3-5 business days if you are selected. Check your email (including spam folder) for updates.'
});
}