export function publicConsultationForm(form: FormTs) {
// Public Consultation Form - Citizen feedback on policies and initiatives
// Demonstrates: MatrixQuestion (priority ranking), RatingScale, conditional sections, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Public Consultation',
computedValue: () => 'Your voice matters! Help shape the future of our community by sharing your thoughts and priorities.',
customStyles: {
backgroundColor: '#1e40af',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Consultation Topic
// ============================================
const topicSection = form.addSubform('topic', {
title: 'About This Consultation',
customStyles: { backgroundColor: '#eff6ff', padding: '16px', borderRadius: '8px' }
});
topicSection.addRow(row => {
row.addTextPanel('topicDescription', {
computedValue: () => 'We are seeking public input on proposed community improvements for the upcoming fiscal year. Your feedback will directly influence budget allocation and project prioritization.',
customStyles: { fontSize: '15px', lineHeight: '1.6' }
});
});
topicSection.addRow(row => {
row.addDropdown('consultationType', {
label: 'Which topic would you like to provide feedback on?',
options: [
{ id: 'budget', name: 'Annual Budget Priorities' },
{ id: 'infrastructure', name: 'Infrastructure & Transportation' },
{ id: 'parks', name: 'Parks & Recreation' },
{ id: 'safety', name: 'Public Safety' },
{ id: 'environment', name: 'Environmental Initiatives' },
{ id: 'housing', name: 'Housing & Development' },
{ id: 'general', name: 'General Community Feedback' }
],
isRequired: true,
placeholder: 'Select a topic'
});
});
// ============================================
// SECTION 2: Priority Ranking
// ============================================
const prioritiesSection = form.addSubform('priorities', {
title: () => {
const type = topicSection.dropdown('consultationType')?.value();
const labels: Record<string, string> = {
'budget': 'Budget Priority Ranking',
'infrastructure': 'Infrastructure Priorities',
'parks': 'Parks & Recreation Priorities',
'safety': 'Public Safety Priorities',
'environment': 'Environmental Priorities',
'housing': 'Housing Priorities',
'general': 'Community Priorities'
};
return labels[type || ''] || 'Priority Ranking';
},
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null
});
// Budget priorities matrix
prioritiesSection.addRow(row => {
row.addMatrixQuestion('budgetPriorities', {
label: 'Rate the importance of each priority area:',
rows: () => {
const type = topicSection.dropdown('consultationType')?.value();
if (type === 'budget') {
return [
{ id: 'roads', label: 'Road maintenance & repairs', isRequired: true },
{ id: 'transit', label: 'Public transportation improvements' },
{ id: 'parks', label: 'Parks and green spaces' },
{ id: 'safety', label: 'Police and fire services' },
{ id: 'education', label: 'Education funding' },
{ id: 'social', label: 'Social services & support programs' },
{ id: 'economic', label: 'Economic development' }
];
} else if (type === 'infrastructure') {
return [
{ id: 'roads', label: 'Street and highway repairs', isRequired: true },
{ id: 'bridges', label: 'Bridge maintenance' },
{ id: 'sidewalks', label: 'Sidewalk improvements' },
{ id: 'bikelanes', label: 'Bike lanes and paths' },
{ id: 'transit', label: 'Public transit expansion' },
{ id: 'traffic', label: 'Traffic signal upgrades' },
{ id: 'utilities', label: 'Water/sewer infrastructure' }
];
} else if (type === 'parks') {
return [
{ id: 'playgrounds', label: 'Playground equipment', isRequired: true },
{ id: 'trails', label: 'Walking/biking trails' },
{ id: 'sports', label: 'Sports fields and courts' },
{ id: 'community', label: 'Community centers' },
{ id: 'pools', label: 'Swimming facilities' },
{ id: 'nature', label: 'Nature preservation areas' },
{ id: 'events', label: 'Public event spaces' }
];
} else if (type === 'safety') {
return [
{ id: 'police', label: 'Police presence and patrols', isRequired: true },
{ id: 'fire', label: 'Fire department resources' },
{ id: 'ems', label: 'Emergency medical services' },
{ id: 'lighting', label: 'Street lighting' },
{ id: 'cameras', label: 'Security cameras' },
{ id: 'prevention', label: 'Crime prevention programs' },
{ id: 'emergency', label: 'Emergency preparedness' }
];
} else if (type === 'environment') {
return [
{ id: 'recycling', label: 'Recycling programs', isRequired: true },
{ id: 'trees', label: 'Tree planting initiatives' },
{ id: 'solar', label: 'Solar energy projects' },
{ id: 'water', label: 'Water conservation' },
{ id: 'air', label: 'Air quality monitoring' },
{ id: 'wildlife', label: 'Wildlife habitat protection' },
{ id: 'education', label: 'Environmental education' }
];
} else if (type === 'housing') {
return [
{ id: 'affordable', label: 'Affordable housing development', isRequired: true },
{ id: 'seniors', label: 'Senior housing options' },
{ id: 'homeless', label: 'Homeless services' },
{ id: 'rental', label: 'Rental assistance programs' },
{ id: 'homeowner', label: 'First-time homeowner support' },
{ id: 'code', label: 'Housing code enforcement' },
{ id: 'mixed', label: 'Mixed-use development' }
];
}
return [
{ id: 'quality', label: 'Quality of life improvements', isRequired: true },
{ id: 'services', label: 'City services' },
{ id: 'growth', label: 'Managed growth' },
{ id: 'community', label: 'Community engagement' },
{ id: 'transparency', label: 'Government transparency' }
];
},
columns: [
{ id: 'not', label: 'Not Important' },
{ id: 'low', label: 'Low' },
{ id: 'medium', label: 'Medium' },
{ id: 'high', label: 'High' },
{ id: 'critical', label: 'Critical' }
],
alignment: 'center',
fullWidth: true,
striped: true
});
});
// ============================================
// SECTION 3: Overall Satisfaction
// ============================================
const satisfactionSection = form.addSubform('satisfaction', {
title: 'Current Satisfaction',
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null
});
satisfactionSection.addRow(row => {
row.addRatingScale('currentSatisfaction', {
label: () => {
const type = topicSection.dropdown('consultationType')?.value();
const labels: Record<string, string> = {
'budget': 'How satisfied are you with current budget priorities?',
'infrastructure': 'How satisfied are you with current infrastructure conditions?',
'parks': 'How satisfied are you with local parks and recreation?',
'safety': 'How safe do you feel in your community?',
'environment': 'How satisfied are you with environmental efforts?',
'housing': 'How satisfied are you with housing availability?',
'general': 'How satisfied are you with community services overall?'
};
return labels[type || ''] || 'How satisfied are you overall?';
},
preset: 'satisfaction',
size: 'lg',
alignment: 'center'
});
});
satisfactionSection.addRow(row => {
row.addEmojiRating('sentiment', {
label: 'How do you feel about the direction our community is heading?',
preset: 'mood',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
// ============================================
// SECTION 4: Detailed Feedback
// ============================================
const feedbackSection = form.addSubform('feedback', {
title: 'Your Input',
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null
});
feedbackSection.addRow(row => {
row.addTextarea('concerns', {
label: 'What are your main concerns or issues?',
placeholder: 'Share your thoughts on current challenges or problems that need attention...',
rows: 4,
maxLength: 1000
});
});
feedbackSection.addSpacer({ height: '20px' });
feedbackSection.addRow(row => {
row.addTextarea('suggestions', {
label: 'What suggestions do you have for improvement?',
placeholder: 'Share your ideas for how we can better serve the community...',
rows: 4,
maxLength: 1000
});
});
feedbackSection.addSpacer({ height: '20px' });
feedbackSection.addRow(row => {
row.addSuggestionChips('topics', {
label: 'Select any additional topics you\'d like to see addressed:',
suggestions: [
{ id: 'jobs', name: 'Job creation' },
{ id: 'youth', name: 'Youth programs' },
{ id: 'seniors', name: 'Senior services' },
{ id: 'arts', name: 'Arts & culture' },
{ id: 'health', name: 'Public health' },
{ id: 'tech', name: 'Technology access' },
{ id: 'diversity', name: 'Diversity & inclusion' },
{ id: 'business', name: 'Small business support' }
],
alignment: 'center'
});
});
// ============================================
// SECTION 5: Engagement Preferences
// ============================================
const engagementSection = form.addSubform('engagement', {
title: 'Stay Engaged',
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null
});
engagementSection.addRow(row => {
row.addRadioButton('attendMeeting', {
label: 'Would you attend a public meeting on this topic?',
options: [
{ id: 'yes-person', name: 'Yes, in person' },
{ id: 'yes-virtual', name: 'Yes, virtually' },
{ id: 'either', name: 'Either format' },
{ id: 'no', name: 'No, I prefer online feedback only' }
],
orientation: 'vertical'
}, '1fr');
row.addCheckboxList('communicationPref', {
label: 'How would you like to receive updates?',
options: [
{ id: 'email', name: 'Email newsletter' },
{ id: 'mail', name: 'Postal mail' },
{ id: 'social', name: 'Social media' },
{ id: 'website', name: 'Website announcements' },
{ id: 'app', name: 'Mobile app notifications' }
],
orientation: 'vertical'
}, '1fr');
});
// ============================================
// SECTION 6: Demographics (Optional)
// ============================================
const demographicsSection = form.addSubform('demographics', {
title: 'About You (Optional)',
isCollapsible: true,
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null,
customStyles: { backgroundColor: '#f8fafc', padding: '16px', borderRadius: '8px' }
});
demographicsSection.addRow(row => {
row.addTextPanel('demographicsNote', {
computedValue: () => 'This information helps us understand who is participating and ensure all community members are represented. All responses are anonymous.',
customStyles: { fontSize: '13px', color: '#6b7280', marginBottom: '16px' }
});
});
demographicsSection.addRow(row => {
row.addDropdown('ageGroup', {
label: 'Age Group',
options: [
{ 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: '65+', name: '65+' },
{ id: 'prefer-not', name: 'Prefer not to say' }
],
placeholder: 'Select age group'
}, '1fr');
row.addDropdown('residency', {
label: 'How long have you lived here?',
options: [
{ id: 'less-1', name: 'Less than 1 year' },
{ id: '1-5', name: '1-5 years' },
{ id: '5-10', name: '5-10 years' },
{ id: '10-20', name: '10-20 years' },
{ id: '20+', name: '20+ years' },
{ id: 'lifetime', name: 'Lifelong resident' }
],
placeholder: 'Select duration'
}, '1fr');
});
demographicsSection.addRow(row => {
row.addTextbox('neighborhood', {
label: 'Neighborhood/District',
placeholder: 'Enter your neighborhood name'
}, '1fr');
row.addTextbox('zipCode', {
label: 'ZIP Code',
placeholder: '12345',
maxLength: 10
}, '150px');
});
// ============================================
// SECTION 7: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Response Summary',
isVisible: () => {
const type = topicSection.dropdown('consultationType')?.value();
const satisfaction = satisfactionSection.ratingScale('currentSatisfaction')?.value();
return type !== null && satisfaction !== null;
}
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const type = topicSection.dropdown('consultationType')?.value();
const satisfaction = satisfactionSection.ratingScale('currentSatisfaction')?.value();
const sentiment = satisfactionSection.emojiRating('sentiment')?.value();
const topics = feedbackSection.suggestionChips('topics')?.value() || [];
const typeLabels: Record<string, string> = {
'budget': 'Annual Budget Priorities',
'infrastructure': 'Infrastructure & Transportation',
'parks': 'Parks & Recreation',
'safety': 'Public Safety',
'environment': 'Environmental Initiatives',
'housing': 'Housing & Development',
'general': 'General Community Feedback'
};
const sentimentLabels: Record<string, string> = {
'sad': 'Concerned',
'down': 'Somewhat Worried',
'neutral': 'Neutral',
'happy': 'Optimistic',
'excited': 'Very Positive'
};
let summary = 'YOUR FEEDBACK SUMMARY\n';
summary += `${'─'.repeat(30)}\n\n`;
summary += `Topic: ${typeLabels[type || ''] || 'Not selected'}\n`;
summary += `Satisfaction: ${satisfaction || 0}/5\n`;
if (sentiment) {
summary += `Outlook: ${sentimentLabels[sentiment] || sentiment}\n`;
}
if (topics.length > 0) {
summary += `\nAdditional interests: ${topics.length} topics selected`;
}
return summary;
},
customStyles: () => {
const satisfaction = satisfactionSection.ratingScale('currentSatisfaction')?.value() || 0;
let bgColor = '#f3f4f6';
let borderColor = '#9ca3af';
if (satisfaction >= 4) {
bgColor = '#d1fae5';
borderColor = '#10b981';
} else if (satisfaction <= 2) {
bgColor = '#fee2e2';
borderColor = '#ef4444';
} else if (satisfaction === 3) {
bgColor = '#fef3c7';
borderColor = '#f59e0b';
}
return {
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px',
padding: '16px',
backgroundColor: bgColor,
borderRadius: '8px',
borderLeft: `4px solid ${borderColor}`
};
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => topicSection.dropdown('consultationType')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Participating!',
message: 'Your feedback has been recorded. Your input is valuable and will be considered in our decision-making process. We appreciate your engagement in making our community better.'
});
}