export function accessibilityComplianceCalculator(form: FormTs) {
// WCAG level complexity multipliers
const wcagLevelMultipliers: Record<string, number> = {
'a': 1.0,
'aa': 1.4,
'aaa': 2.0
};
// Website size base costs
const websiteSizeCosts: Record<string, { audit: number; remediation: number }> = {
'small': { audit: 1500, remediation: 3000 },
'medium': { audit: 3500, remediation: 8000 },
'large': { audit: 7500, remediation: 20000 },
'enterprise': { audit: 15000, remediation: 50000 }
};
// Complexity multipliers
const complexityMultipliers: Record<string, number> = {
'simple': 0.8,
'moderate': 1.0,
'complex': 1.4,
'highly-complex': 1.8
};
// Current state discounts (better state = less work)
const currentStateFactors: Record<string, number> = {
'none': 1.0,
'partial': 0.7,
'mostly': 0.4,
'needs-audit': 0.2
};
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Accessibility Compliance Cost Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Website Profile Section
const websiteSection = form.addSubform('websiteProfile', { title: '🌐 Website Profile' });
websiteSection.addRow(row => {
row.addDropdown('websiteSize', {
label: 'Website Size',
options: [
{ id: 'small', name: 'Small (under 50 pages)' },
{ id: 'medium', name: 'Medium (50-200 pages)' },
{ id: 'large', name: 'Large (200-1,000 pages)' },
{ id: 'enterprise', name: 'Enterprise (1,000+ pages)' }
],
defaultValue: 'medium',
isRequired: true
}, '1fr');
row.addDropdown('complexity', {
label: 'Technical Complexity',
options: [
{ id: 'simple', name: 'Simple (static, basic forms)' },
{ id: 'moderate', name: 'Moderate (CMS, some dynamic)' },
{ id: 'complex', name: 'Complex (web app, many interactions)' },
{ id: 'highly-complex', name: 'Highly Complex (SPA, rich media)' }
],
defaultValue: 'moderate',
isRequired: true
}, '1fr');
});
websiteSection.addRow(row => {
row.addDropdown('currentState', {
label: 'Current Accessibility State',
options: [
{ id: 'none', name: 'No accessibility work done' },
{ id: 'partial', name: 'Some accessibility implemented' },
{ id: 'mostly', name: 'Mostly accessible (minor issues)' },
{ id: 'needs-audit', name: 'Unknown - need audit first' }
],
defaultValue: 'none',
isRequired: true
}, '1fr');
row.addDropdown('platform', {
label: 'Website Platform',
options: [
{ id: 'wordpress', name: 'WordPress' },
{ id: 'shopify', name: 'Shopify' },
{ id: 'drupal', name: 'Drupal' },
{ id: 'custom', name: 'Custom built' },
{ id: 'react', name: 'React / Vue / Angular' },
{ id: 'other', name: 'Other' }
],
defaultValue: 'wordpress'
}, '1fr');
});
// Compliance Requirements Section
const complianceSection = form.addSubform('compliance', { title: '📋 Compliance Requirements' });
complianceSection.addRow(row => {
row.addDropdown('wcagLevel', {
label: 'Target WCAG Level',
options: [
{ id: 'a', name: 'WCAG 2.1 Level A (minimum)' },
{ id: 'aa', name: 'WCAG 2.1 Level AA (recommended)' },
{ id: 'aaa', name: 'WCAG 2.1 Level AAA (highest)' }
],
defaultValue: 'aa',
isRequired: true
}, '1fr');
row.addDropdown('urgency', {
label: 'Project Urgency',
options: [
{ id: 'standard', name: 'Standard timeline' },
{ id: 'accelerated', name: 'Accelerated (+25%)' },
{ id: 'urgent', name: 'Urgent/Legal deadline (+50%)' }
],
defaultValue: 'standard'
}, '1fr');
});
complianceSection.addRow(row => {
row.addCheckbox('adaCompliance', {
label: 'ADA compliance (US)',
defaultValue: true
}, '1fr');
row.addCheckbox('section508', {
label: 'Section 508 (US Federal)',
defaultValue: false
}, '1fr');
});
complianceSection.addRow(row => {
row.addCheckbox('euDirective', {
label: 'EU Accessibility Directive (EN 301 549)',
defaultValue: false
}, '1fr');
row.addCheckbox('aoda', {
label: 'AODA (Ontario, Canada)',
defaultValue: false
}, '1fr');
});
// Audit Services Section
const auditSection = form.addSubform('auditServices', { title: '🔍 Audit Services' });
auditSection.addRow(row => {
row.addCheckbox('automatedAudit', {
label: 'Automated accessibility testing',
defaultValue: true
}, '1fr');
row.addCheckbox('manualAudit', {
label: 'Manual expert audit',
defaultValue: true
}, '1fr');
});
auditSection.addRow(row => {
row.addCheckbox('assistiveTechTesting', {
label: 'Assistive technology testing (screen readers)',
defaultValue: true
}, '1fr');
row.addCheckbox('userTesting', {
label: 'Testing with disabled users',
defaultValue: false
}, '1fr');
});
auditSection.addRow(row => {
row.addCheckbox('vpat', {
label: 'VPAT/ACR documentation',
defaultValue: false
}, '1fr');
row.addCheckbox('detailedReport', {
label: 'Detailed remediation report',
defaultValue: true
}, '1fr');
});
// Remediation Services Section
const remediationSection = form.addSubform('remediation', { title: '🔧 Remediation Services' });
remediationSection.addRow(row => {
row.addCheckbox('codeRemediation', {
label: 'Code/HTML remediation',
defaultValue: true
}, '1fr');
row.addCheckbox('designRemediation', {
label: 'Design/color contrast fixes',
defaultValue: true
}, '1fr');
});
remediationSection.addRow(row => {
row.addCheckbox('formRemediation', {
label: 'Form accessibility fixes',
defaultValue: true
}, '1fr');
row.addCheckbox('mediaRemediation', {
label: 'Media accessibility (alt text, captions)',
defaultValue: false
}, '1fr');
});
remediationSection.addRow(row => {
row.addCheckbox('pdfRemediation', {
label: 'PDF accessibility remediation',
defaultValue: false
}, '1fr');
row.addInteger('pdfCount', {
label: 'Number of PDFs',
min: 1,
max: 1000,
defaultValue: 10,
isVisible: () => remediationSection.checkbox('pdfRemediation')?.value() === true
}, '1fr');
});
remediationSection.addRow(row => {
row.addCheckbox('videoCaption', {
label: 'Video captioning',
defaultValue: false
}, '1fr');
row.addInteger('videoMinutes', {
label: 'Total Video Minutes',
min: 1,
max: 10000,
defaultValue: 30,
isVisible: () => remediationSection.checkbox('videoCaption')?.value() === true
}, '1fr');
});
// Ongoing Services Section
const ongoingSection = form.addSubform('ongoing', { title: '🔄 Ongoing Accessibility' });
ongoingSection.addRow(row => {
row.addCheckbox('staffTraining', {
label: 'Staff accessibility training',
defaultValue: false
}, '1fr');
row.addCheckbox('contentGuidelines', {
label: 'Accessible content guidelines',
defaultValue: false
}, '1fr');
});
ongoingSection.addRow(row => {
row.addCheckbox('quarterlyAudit', {
label: 'Quarterly accessibility audits',
defaultValue: false
}, '1fr');
row.addCheckbox('monitoring', {
label: 'Automated monitoring service',
defaultValue: false
}, '1fr');
});
ongoingSection.addRow(row => {
row.addCheckbox('supportRetainer', {
label: 'Remediation support retainer',
defaultValue: false
}, '1fr');
row.addCheckbox('accessibilityStatement', {
label: 'Accessibility statement & feedback process',
defaultValue: false
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Cost Summary Section
const summarySection = form.addSubform('summary', { title: '📊 Cost Breakdown', isCollapsible: false });
summarySection.addRow(row => {
row.addPriceDisplay('auditCost', {
label: 'Audit & Assessment',
computedValue: () => {
const size = websiteSection.dropdown('websiteSize')?.value() || 'medium';
const complexity = websiteSection.dropdown('complexity')?.value() || 'moderate';
const wcagLevel = complianceSection.dropdown('wcagLevel')?.value() || 'aa';
let baseCost = websiteSizeCosts[size]?.audit || 3500;
baseCost *= complexityMultipliers[complexity] || 1;
baseCost *= wcagLevelMultipliers[wcagLevel] || 1.4;
// Audit additions
if (auditSection.checkbox('assistiveTechTesting')?.value()) baseCost += 500;
if (auditSection.checkbox('userTesting')?.value()) baseCost += 2000;
if (auditSection.checkbox('vpat')?.value()) baseCost += 1500;
// Additional regulations
if (complianceSection.checkbox('section508')?.value()) baseCost += 500;
if (complianceSection.checkbox('euDirective')?.value()) baseCost += 500;
return Math.round(baseCost);
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('remediationCost', {
label: 'Remediation Work',
computedValue: () => {
const size = websiteSection.dropdown('websiteSize')?.value() || 'medium';
const complexity = websiteSection.dropdown('complexity')?.value() || 'moderate';
const currentState = websiteSection.dropdown('currentState')?.value() || 'none';
const wcagLevel = complianceSection.dropdown('wcagLevel')?.value() || 'aa';
const urgency = complianceSection.dropdown('urgency')?.value() || 'standard';
let baseCost = websiteSizeCosts[size]?.remediation || 8000;
baseCost *= complexityMultipliers[complexity] || 1;
baseCost *= currentStateFactors[currentState] || 1;
baseCost *= wcagLevelMultipliers[wcagLevel] || 1.4;
// Urgency multiplier
if (urgency === 'accelerated') baseCost *= 1.25;
if (urgency === 'urgent') baseCost *= 1.5;
// Specific remediation additions
if (remediationSection.checkbox('mediaRemediation')?.value()) baseCost += 1000;
// PDF remediation
if (remediationSection.checkbox('pdfRemediation')?.value()) {
const pdfCount = remediationSection.integer('pdfCount')?.value() || 10;
baseCost += pdfCount * 75;
}
// Video captioning
if (remediationSection.checkbox('videoCaption')?.value()) {
const videoMinutes = remediationSection.integer('videoMinutes')?.value() || 30;
baseCost += videoMinutes * 8;
}
return Math.round(baseCost);
},
variant: 'default'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('trainingCost', {
label: 'Training & Documentation',
computedValue: () => {
let cost = 0;
if (ongoingSection.checkbox('staffTraining')?.value()) cost += 1500;
if (ongoingSection.checkbox('contentGuidelines')?.value()) cost += 750;
if (ongoingSection.checkbox('accessibilityStatement')?.value()) cost += 500;
return cost;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('ongoingCost', {
label: 'Ongoing Services',
computedValue: () => {
const size = websiteSection.dropdown('websiteSize')?.value() || 'medium';
let monthlyCost = 0;
if (ongoingSection.checkbox('quarterlyAudit')?.value()) {
const auditCost = websiteSizeCosts[size]?.audit || 3500;
monthlyCost += (auditCost * 0.5) / 3; // Quarterly at 50% rate
}
if (ongoingSection.checkbox('monitoring')?.value()) monthlyCost += 100;
if (ongoingSection.checkbox('supportRetainer')?.value()) monthlyCost += 500;
return Math.round(monthlyCost);
},
variant: 'default',
suffix: '/month'
}, '1fr');
});
const finalSection = form.addSubform('final', {
title: '💰 Total Investment Estimate',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addPriceDisplay('initialCost', {
label: 'Initial Project Cost',
computedValue: () => {
const size = websiteSection.dropdown('websiteSize')?.value() || 'medium';
const complexity = websiteSection.dropdown('complexity')?.value() || 'moderate';
const currentState = websiteSection.dropdown('currentState')?.value() || 'none';
const wcagLevel = complianceSection.dropdown('wcagLevel')?.value() || 'aa';
const urgency = complianceSection.dropdown('urgency')?.value() || 'standard';
// Audit cost
let auditCost = websiteSizeCosts[size]?.audit || 3500;
auditCost *= complexityMultipliers[complexity] || 1;
auditCost *= wcagLevelMultipliers[wcagLevel] || 1.4;
if (auditSection.checkbox('assistiveTechTesting')?.value()) auditCost += 500;
if (auditSection.checkbox('userTesting')?.value()) auditCost += 2000;
if (auditSection.checkbox('vpat')?.value()) auditCost += 1500;
if (complianceSection.checkbox('section508')?.value()) auditCost += 500;
if (complianceSection.checkbox('euDirective')?.value()) auditCost += 500;
// Remediation cost
let remediationCost = websiteSizeCosts[size]?.remediation || 8000;
remediationCost *= complexityMultipliers[complexity] || 1;
remediationCost *= currentStateFactors[currentState] || 1;
remediationCost *= wcagLevelMultipliers[wcagLevel] || 1.4;
if (urgency === 'accelerated') remediationCost *= 1.25;
if (urgency === 'urgent') remediationCost *= 1.5;
if (remediationSection.checkbox('mediaRemediation')?.value()) remediationCost += 1000;
if (remediationSection.checkbox('pdfRemediation')?.value()) {
remediationCost += (remediationSection.integer('pdfCount')?.value() || 10) * 75;
}
if (remediationSection.checkbox('videoCaption')?.value()) {
remediationCost += (remediationSection.integer('videoMinutes')?.value() || 30) * 8;
}
// Training cost
let trainingCost = 0;
if (ongoingSection.checkbox('staffTraining')?.value()) trainingCost += 1500;
if (ongoingSection.checkbox('contentGuidelines')?.value()) trainingCost += 750;
if (ongoingSection.checkbox('accessibilityStatement')?.value()) trainingCost += 500;
return Math.round(auditCost + remediationCost + trainingCost);
},
variant: 'large'
}, '1fr');
row.addPriceDisplay('annualOngoing', {
label: 'Annual Ongoing Cost',
computedValue: () => {
const size = websiteSection.dropdown('websiteSize')?.value() || 'medium';
let monthlyCost = 0;
if (ongoingSection.checkbox('quarterlyAudit')?.value()) {
const auditCost = websiteSizeCosts[size]?.audit || 3500;
monthlyCost += (auditCost * 0.5) / 3;
}
if (ongoingSection.checkbox('monitoring')?.value()) monthlyCost += 100;
if (ongoingSection.checkbox('supportRetainer')?.value()) monthlyCost += 500;
return Math.round(monthlyCost * 12);
},
variant: 'large',
suffix: '/year'
}, '1fr');
});
finalSection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'This calculator provides estimates only. Actual costs depend on specific accessibility issues, website architecture, and remediation complexity. A detailed audit is required for accurate project scoping. This does not constitute legal advice regarding ADA compliance.',
customStyles: { 'font-size': '0.8rem', 'color': '#64748b', 'font-style': 'italic' }
});
});
form.configureSubmitButton({
label: 'Request Accessibility Assessment'
});
}